Subida del módulo y tema de PrestaShop

This commit is contained in:
Kaloyan
2026-04-09 18:31:51 +02:00
parent 12c253296f
commit 16b3ff9424
39262 changed files with 7418797 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
USE_BILLING_SANDBOX=0
USE_BILLING_PREPROD=0
USE_CLOUDSYNC_PREPROD=0

View File

@@ -0,0 +1,14 @@
# Apache 2.2
<IfModule !mod_authz_core.c>
<Files *.php>
order allow,deny
deny from all
</Files>
</IfModule>
# Apache 2.4
<IfModule mod_authz_core.c>
<Files *.php>
Require all denied
</Files>
</IfModule>

View File

@@ -0,0 +1,12 @@
<?php
$config = new PrestaShop\CodingStandards\CsFixer\Config();
$config
->setUsingCache(true)
->getFinder()
->in(__DIR__)
->exclude('translations')
->exclude('vendor');
return $config;

View File

@@ -0,0 +1,10 @@
# Apache 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
# Apache 2.4
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

View File

@@ -0,0 +1,70 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Adapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Http\HttpClient;
class BillingAdapter
{
private const BILLING_URL = 'https://billing-api.distribution.prestashop.net/v1/';
private const BILLING_PREPROD_URL = 'https://billing-api.distribution-preprod.prestashop.net/v1/';
/**
* @var string
*/
private $jwt;
/**
* @var string
*/
private $url;
/**
* @var bool
*/
private $isSandbox;
public function __construct($jwt, $isSandbox, $usePreprod)
{
$this->jwt = $jwt;
$this->isSandbox = $isSandbox;
$this->url = $usePreprod ? self::BILLING_PREPROD_URL : self::BILLING_URL;
}
public function getCurrentSubscription($shopId, $productId)
{
$httpClient = new HttpClient($this->url);
$headers = [
'Accept: application/json',
'Authorization: Bearer ' . $this->jwt,
'Content-Type: application/json',
'User-Agent : module-lib-billing v3 (' . $productId . ')',
];
if ($this->isSandbox === true) {
$headers[] = 'sandbox: true';
}
$httpClient->setHeaders($headers);
return $httpClient->get('/customers/' . $shopId . '/subscriptions/' . $productId);
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Adapter;
use Configuration;
class ConfigurationAdapter
{
/**
* @var int
*/
private $shopId;
public function __construct($shopId)
{
$this->shopId = $shopId;
}
public function get($key, $idLang = null, $idShopGroup = null, $idShop = null, $default = false)
{
if ($idShop === null) {
$idShop = $this->shopId;
}
return Configuration::get($key, $idLang, $idShopGroup, $idShop, $default);
}
public function updateValue($key, $values, $html = false, $idShopGroup = null, $idShop = null)
{
if ($idShop === null) {
$idShop = $this->shopId;
}
return Configuration::updateValue($key, $values, $html, $idShopGroup, $idShop);
}
public function deleteByName($key)
{
return Configuration::deleteByName($key);
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,80 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Buffer;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
class TemplateBuffer
{
/**
* @var Session
*/
private $session;
/**
* @param string $userId
*/
public function init($userId)
{
$this->session = new Session(
new MockFileSessionStorage(
\_PS_CACHE_DIR_ . '/psxmarketingwithgoogle_sessions',
'conversionaction'
)
);
$this->session->setId($userId);
$this->session->start();
register_shutdown_function([$this, 'save']);
}
/**
* add data to the buffer
*
* @param string $data
*
* @return void
*/
public function add($data)
{
$this->session->getFlashBag()->add('gtag_events', $data);
}
/**
* return buffer content and reset it
*
* @return string
*/
public function flush(): string
{
$data = '';
foreach ($this->session->getFlashBag()->get('gtag_events', []) as $message) {
$data .= $message;
}
return $data;
}
public function save(): void
{
$this->session->save();
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,232 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Builder;
use Carrier;
use Currency;
use Language;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\Carrier as DTOCarrier;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\CarrierDetail;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\CarrierTax;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CarrierRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\StateRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\TaxRepository;
use RangePrice;
use RangeWeight;
class CarrierBuilder
{
/**
* @var CarrierRepository
*/
private $carrierRepository;
/**
* @var CountryRepository
*/
private $countryRepository;
/**
* @var StateRepository
*/
private $stateRepository;
/**
* @var TaxRepository
*/
private $taxRepository;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(
CarrierRepository $carrierRepository,
CountryRepository $countryRepository,
StateRepository $stateRepository,
TaxRepository $taxRepository,
ConfigurationAdapter $configurationAdapter
) {
$this->carrierRepository = $carrierRepository;
$this->countryRepository = $countryRepository;
$this->stateRepository = $stateRepository;
$this->taxRepository = $taxRepository;
$this->configurationAdapter = $configurationAdapter;
}
public function buildCarriers(array $carriers, Language $lang, Currency $currency, string $weightUnit): array
{
$carrierLines = [];
foreach ($carriers as $carrier) {
$carrierLines[] = self::buildCarrier(
new Carrier($carrier['id_carrier'], $lang->id),
$currency->iso_code,
$weightUnit
);
}
$formattedCarriers = [];
/** @var DTOCarrier $carrierLine */
foreach ($carrierLines as $carrierLine) {
$formattedCarriers = array_merge($formattedCarriers, $carrierLine->jsonSerialize());
}
return $formattedCarriers;
}
public function buildCarrier(Carrier $carrier, string $currencyIsoCode, string $weightUnit): DTOCarrier
{
$carrierLine = new DTOCarrier();
$freeShippingStartsAtPrice = (float) $this->configurationAdapter->get('PS_SHIPPING_FREE_PRICE');
$freeShippingStartsAtWeight = (float) $this->configurationAdapter->get('PS_SHIPPING_FREE_WEIGHT');
$carrierLine->setFreeShippingStartsAtPrice($freeShippingStartsAtPrice);
$carrierLine->setFreeShippingStartsAtWeight($freeShippingStartsAtWeight);
$carrierLine->setShippingHandling($this->getShippingHandlePrice((bool) $carrier->shipping_handling));
$countryIsoCodes = [];
foreach ($carrier->getZones() as $zone) {
$countryIsoCodes = array_merge($countryIsoCodes, $this->countryRepository->getCountryIsoCodesByZoneId($zone['id_zone']));
}
$carrierLine
->setIdCarrier((int) $carrier->id)
->setIdReference((int) $carrier->id_reference)
->setName($carrier->name)
->setTaxesRatesGroupId((int) $carrier->getIdTaxRulesGroup())
->setUrl((string) $carrier->url)
->setActive($carrier->active)
->setDeleted($carrier->deleted)
->setDisableCarrierWhenOutOfRange((bool) $carrier->range_behavior)
->setIsModule($carrier->is_module)
->setIsFree($carrier->is_free)
->setShippingExternal($carrier->shipping_external)
->setNeedRange($carrier->need_range)
->setExternalModuleName((string) $carrier->external_module_name)
->setMaxWidth($carrier->max_width)
->setMaxHeight($carrier->max_height)
->setMaxDepth($carrier->max_depth)
->setMaxWeight($carrier->max_weight)
->setGrade($carrier->grade)
->setDelay($carrier->delay)
->setCurrency($currencyIsoCode)
->setWeightUnit($weightUnit)
->setCountryIsoCodes($countryIsoCodes);
$deliveryPriceByRanges = $this->carrierRepository->getDeliveryPriceByRange($carrier);
$carrierLine->setCarrierTaxes($this->buildCarrierTaxes($carrier));
if (!$deliveryPriceByRanges) {
return $carrierLine;
}
$carrierDetails = [];
foreach ($deliveryPriceByRanges as $deliveryPriceByRange) {
$range = $this->carrierRepository->getCarrierRange($deliveryPriceByRange);
if (!$range) {
continue;
}
foreach ($deliveryPriceByRange['zones'] as $zone) {
$carrierDetail = $this->buildCarrierDetails($carrier, $range, $zone, $deliveryPriceByRange);
if ($carrierDetail) {
$carrierDetails[] = $carrierDetail;
}
}
}
$carrierLine->setCarrierDetails($carrierDetails);
return $carrierLine;
}
/**
* @param Carrier $carrier
* @param RangeWeight|RangePrice $range
* @param array $zone
* @param array $deliveryPriceByRange
*
* @return ?CarrierDetail
*/
private function buildCarrierDetails(Carrier $carrier, $range, array $zone, array $deliveryPriceByRange)
{
$rangeTable = $carrier->getRangeTable();
$carrierDetailId = isset($deliveryPriceByRange['id_range_weight']) ? $deliveryPriceByRange['id_range_weight'] : $deliveryPriceByRange['id_range_price'];
$carrierDetail = new CarrierDetail();
$carrierDetail->setShippingMethod($rangeTable);
$carrierDetail->setCarrierDetailId($carrierDetailId);
$carrierDetail->setDelimiter1($range->delimiter1);
$carrierDetail->setDelimiter2($range->delimiter2);
$carrierDetail->setPrice($zone['price']);
$carrierDetail->setCarrierReference($carrier->id_reference);
$carrierDetail->setZoneId($zone['id_zone']);
$carrierDetail->setRangeId($range->id);
$countryIsoCodes = $this->countryRepository->getCountryIsoCodesByZoneId($zone['id_zone']);
if (!$countryIsoCodes) {
return null;
}
$carrierDetail->setCountryIsoCodes($countryIsoCodes);
$stateIsoCodes = $this->stateRepository->getStateIsoCodesByZoneId($zone['id_zone']);
$carrierDetail->setStateIsoCodes($stateIsoCodes);
return $carrierDetail;
}
/**
* @return array<CarrierTax>
*/
private function buildCarrierTaxes(Carrier $carrier): array
{
$taxRulesGroupId = (int) $carrier->getIdTaxRulesGroup();
$carrierTaxesByZone = $this->taxRepository->getCarrierTaxesByTaxRulesGroupId($taxRulesGroupId);
if (!$carrierTaxesByZone[0]['country_iso_code']) {
return [];
}
$carrierTaxesByZone = $carrierTaxesByZone[0];
$carrierTax = new CarrierTax();
$carrierTax->setCarrierReference($carrier->id_reference);
$carrierTax->setTaxRulesGroupId($taxRulesGroupId);
$carrierTax->setCountryIsoCode((string) $carrierTaxesByZone['country_iso_code']);
$carrierTax->setStateIsoCodes((string) $carrierTaxesByZone['state_iso_code']);
$carrierTax->setTaxRate($carrierTaxesByZone['rate']);
return [
$carrierTax,
];
}
private function getShippingHandlePrice(bool $shippingHandling): float
{
if ($shippingHandling) {
return (float) $this->configurationAdapter->get('PS_SHIPPING_HANDLING');
}
return 0.0;
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,76 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
class EnhancedConversionToggle
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(
ConfigurationAdapter $configurationAdapter
) {
$this->configurationAdapter = $configurationAdapter;
}
public function enable(): bool
{
$snippet = base64_decode($this->configurationAdapter->get(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG
));
$alteredSnippet = (new SnippetUpdater($snippet))
->addEnhancedConversion()
->getSnippet();
return $this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG,
base64_encode($alteredSnippet)
) && $this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_ENHANCED_STATUS,
true
);
}
public function disable(): bool
{
$snippet = base64_decode($this->configurationAdapter->get(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG
));
$alteredSnippet = (new SnippetUpdater($snippet))
->removeEnhancedConversion()
->getSnippet();
return $this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG,
base64_encode($alteredSnippet)
) && $this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_ENHANCED_STATUS,
false
);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
class Hasher
{
/**
* @param string|null $data
*
* @return string|null
*/
public static function hash($data)
{
if (!$data) {
return null;
}
return hash('sha256', $data, false);
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
use Brick\PhoneNumber\PhoneNumber;
use Brick\PhoneNumber\PhoneNumberFormat;
use Exception;
class Normalizer
{
/**
* @param string|null $data
* @param string|null $additionalNormalization
*
* @return string|null
*/
public static function normalize($data, $additionalNormalization = null)
{
if (empty($data)) {
return null;
}
$data = trim(strtolower($data));
if ($additionalNormalization === 'phone') {
return self::normalizePhoneNumber($data);
}
return $data;
}
public static function normalizePhoneNumber(string $data): string
{
$dataWithPlusAndNumbers = preg_replace('/([-\s\(\)])/', '', $data);
return preg_replace('/^(0{2})/', '+', $dataWithPlusAndNumbers);
}
/**
* @param string|null $data
* @param string $countryCode
*
* @return string|null
*/
public static function normalizeInE164($data, $countryCode)
{
if (empty($data)) {
return null;
}
try {
return PhoneNumber::parse($data, $countryCode)->format(PhoneNumberFormat::E164);
} catch (Exception $e) {
return $data;
}
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
class SnippetUpdater
{
/**
* @var string
*/
private $snippet;
public function __construct(
string $originalSnippet
) {
$this->snippet = $originalSnippet;
}
public function addEnhancedConversion(): self
{
$this->snippet = preg_replace("/(gtag\('config', 'AW-[0-9]+')()(\);)/im", '${1}, {\'allow_enhanced_conversions\': true}${3}', $this->snippet);
return $this;
}
public function removeEnhancedConversion(): self
{
$this->snippet = str_replace(", {'allow_enhanced_conversions': true}", '', $this->snippet);
return $this;
}
public function getSnippet(): string
{
return $this->snippet;
}
}

View File

@@ -0,0 +1,278 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
use JsonSerializable;
class UserAddressData implements JsonSerializable
{
/**
* @var string|null
*/
private $firstName;
/**
* @var string|null
*/
private $lastName;
/**
* @var string|null
*/
private $street;
/**
* @var string|null
*/
private $city;
/**
* @var string|null
*/
private $region;
/**
* @var string|null
*/
private $postalCode;
/**
* @var string|null
*/
private $country;
public function jsonSerialize(): array
{
$data = [];
if (!empty($this->firstName)) {
$data['sha256_first_name'] = $this->firstName;
}
if (!empty($this->lastName)) {
$data['sha256_last_name'] = $this->lastName;
}
if (!empty($this->street)) {
$data['street'] = $this->street;
}
if (!empty($this->city)) {
$data['city'] = $this->city;
}
if (!empty($this->region)) {
$data['region'] = $this->region;
}
if (!empty($this->postalCode)) {
$data['postal_code'] = $this->postalCode;
}
if (!empty($this->country)) {
$data['country'] = $this->country;
}
return $data;
}
/**
* @return bool
*/
public function isEmpty()
{
foreach (get_object_vars($this) as $value) {
if (!empty($value)) {
return false;
}
}
return true;
}
/**
* Get the value of firstName
*
* @return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Set the value of firstName
*
* @param string|null $firstName
*
* @return self
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
return $this;
}
/**
* Get the value of lastName
*
* @return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Set the value of lastName
*
* @param string|null $lastName
*
* @return self
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
return $this;
}
/**
* Get the value of street
*
* @return string
*/
public function getStreet()
{
return $this->street;
}
/**
* Set the value of street
*
* @param string|null $street
*
* @return self
*/
public function setStreet($street)
{
$this->street = $street;
return $this;
}
/**
* Get the value of city
*
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set the value of city
*
* @param string|null $city
*
* @return self
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get the value of region
*
* @return string
*/
public function getRegion()
{
return $this->region;
}
/**
* Set the value of region
*
* @param string|null $region
*
* @return self
*/
public function setRegion($region)
{
$this->region = $region;
return $this;
}
/**
* Get the value of postalCode
*
* @return string
*/
public function getPostalCode()
{
return $this->postalCode;
}
/**
* Set the value of postalCode
*
* @param string|null $postalCode
*
* @return self
*/
public function setPostalCode($postalCode)
{
$this->postalCode = $postalCode;
return $this;
}
/**
* Get the value of country
*
* @return string
*/
public function getCountry()
{
return $this->country;
}
/**
* Set the value of country
*
* @param string|null $country
*
* @return self
*/
public function setCountry($country)
{
$this->country = $country;
return $this;
}
}

View File

@@ -0,0 +1,153 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
use JsonSerializable;
class UserData implements JsonSerializable
{
/**
* @var string|null
*/
private $email;
/**
* @var string|null
*/
private $phoneNumber;
/**
* @var UserAddressData|null
*/
private $address;
public function jsonSerialize(): array
{
$data = [];
if (!empty($this->email)) {
$data['sha256_email_address'] = $this->email;
}
if (!empty($this->phoneNumber)) {
$data['sha256_phone_number'] = $this->phoneNumber;
}
if (!empty($this->address) && !$this->address->isEmpty()) {
$data['address'] = $this->address;
}
return $data;
}
/**
* @return bool
*/
public function isEmpty()
{
if (!$this->address->isEmpty()) {
return false;
}
foreach (get_object_vars($this) as $var => $value) {
if ($var === 'address') {
continue;
}
if (!empty($value)) {
return false;
}
}
return true;
}
/**
* Get the value of email
*
* @return string|null
*/
public function getEmail()
{
return $this->email;
}
/**
* Set the value of email
*
* @param string|null $email
*
* @return self
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get the value of phoneNumber
*
* @return string|null
*/
public function getPhoneNumber()
{
return $this->phoneNumber;
}
/**
* Set the value of phoneNumber
*
* @param string|null $phoneNumber
*
* @return self
*/
public function setPhoneNumber($phoneNumber)
{
$this->phoneNumber = $phoneNumber;
return $this;
}
/**
* Get the value of address
*
* @return UserAddressData|null
*/
public function getAddress()
{
return $this->address;
}
/**
* Set the value of address
*
* @param UserAddressData|null $address
*
* @return self
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Conversion;
use Address;
use Cart;
use Country;
use Customer;
use State;
class UserDataProvider
{
/**
* @var Customer
*/
private $customer;
/**
* @var Cart
*/
private $cart;
public function __construct(
Customer $customer,
Cart $cart
) {
$this->customer = $customer;
$this->cart = $cart;
}
/**
* Return the user personal details
*
* @see https://support.google.com/google-ads/answer/13258081#zippy=%2Cidentify-and-define-your-enhanced-conversions-fields
*/
public function getUserData(): UserData
{
$userData = new UserData();
$userDataAddress = new UserAddressData();
$userData->setEmail(Hasher::hash(Normalizer::normalize($this->customer->email)));
$userDataAddress->setFirstName(Hasher::hash(Normalizer::normalize($this->customer->firstname)));
$userDataAddress->setLastName(Hasher::hash(Normalizer::normalize($this->customer->lastname)));
$address = $this->getAddressFromCart();
if (!empty($address)) {
$userData->setPhoneNumber(Hasher::hash(Normalizer::normalizeInE164($address->phone ?: $address->phone_mobile, $this->getCountryIsoCodeFromAddress($address))));
$userDataAddress->setStreet(Normalizer::normalize(trim($address->address1 . ' ' . $address->address2)));
$userDataAddress->setCity(Normalizer::normalize($address->city));
$userDataAddress->setRegion(Normalizer::normalize($address->id_state ? (new State($address->id_state))->name : null));
$userDataAddress->setPostalCode(Normalizer::normalize($address->postcode));
$userDataAddress->setCountry(Normalizer::normalize($address->country));
}
$userData->setAddress($userDataAddress);
return $userData;
}
/**
* @return Address|null
*/
protected function getAddressFromCart()
{
if (!empty($this->cart->id_address_invoice)) {
return new Address($this->cart->id_address_invoice);
}
return null;
}
/**
* @return string|null
*/
protected function getCountryIsoCodeFromAddress(Address $address)
{
if (!empty($address->id_country)) {
return (new Country($address->id_country))->iso_code;
}
return null;
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,551 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\DTO;
use JsonSerializable;
class Carrier implements JsonSerializable
{
/**
* @var string
*/
private $collection = 'carriers';
/**
* @var int
*/
private $idCarrier;
/**
* @var int
*/
private $idReference;
/**
* @var int
*/
private $taxesRatesGroupId;
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $url;
/**
* @var bool
*/
private $active;
/**
* @var bool
*/
private $deleted;
/**
* @var float
*/
private $shippingHandling = 0;
/**
* @var float
*/
private $freeShippingStartsAtPrice;
/**
* @var float
*/
private $freeShippingStartsAtWeight;
/**
* @var bool
*/
private $disableCarrierWhenOutOfRange;
/**
* @var bool
*/
private $isModule;
/**
* @var bool
*/
private $isFree;
/**
* @var bool
*/
private $shippingExternal;
/**
* @var bool
*/
private $needRange;
/**
* @var string
*/
private $externalModuleName;
/**
* @var float
*/
private $maxWidth;
/**
* @var float
*/
private $maxHeight;
/**
* @var float
*/
private $maxDepth;
/**
* @var float
*/
private $maxWeight;
/**
* @var int
*/
private $grade;
/**
* @var string
*/
private $delay;
/**
* @var string
*/
private $currency;
/**
* @var string
*/
private $weightUnit;
/**
* @var array
*/
private $countryIsoCodes;
/**
* @var CarrierDetail[]
*/
private $carrierDetails = [];
/**
* @var CarrierTax[]
*/
private $carrierTaxes = [];
public function getCollection(): string
{
return $this->collection;
}
public function setCollection(string $collection): Carrier
{
$this->collection = $collection;
return $this;
}
public function getIdCarrier(): int
{
return $this->idCarrier;
}
public function setIdCarrier(int $idCarrier): Carrier
{
$this->idCarrier = $idCarrier;
return $this;
}
public function getIdReference(): int
{
return $this->idReference;
}
public function setIdReference(int $idReference): Carrier
{
$this->idReference = $idReference;
return $this;
}
public function getTaxesRatesGroupId(): int
{
return $this->taxesRatesGroupId;
}
public function setTaxesRatesGroupId(int $taxesRatesGroupId): Carrier
{
$this->taxesRatesGroupId = $taxesRatesGroupId;
return $this;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): Carrier
{
$this->name = $name;
return $this;
}
public function getUrl(): string
{
return $this->url;
}
public function setUrl(string $url): Carrier
{
$this->url = $url;
return $this;
}
public function isActive(): bool
{
return $this->active;
}
public function setActive(bool $active): Carrier
{
$this->active = $active;
return $this;
}
public function isDeleted(): bool
{
return $this->deleted;
}
public function setDeleted(bool $deleted): Carrier
{
$this->deleted = $deleted;
return $this;
}
public function getShippingHandling(): float
{
return $this->shippingHandling;
}
public function setShippingHandling(float $shippingHandling): Carrier
{
$this->shippingHandling = $shippingHandling;
return $this;
}
public function getFreeShippingStartsAtPrice(): float
{
return $this->freeShippingStartsAtPrice;
}
public function setFreeShippingStartsAtPrice(float $freeShippingStartsAtPrice): Carrier
{
$this->freeShippingStartsAtPrice = $freeShippingStartsAtPrice;
return $this;
}
public function getFreeShippingStartsAtWeight(): float
{
return $this->freeShippingStartsAtWeight;
}
public function setFreeShippingStartsAtWeight(float $freeShippingStartsAtWeight): Carrier
{
$this->freeShippingStartsAtWeight = $freeShippingStartsAtWeight;
return $this;
}
public function isDisableCarrierWhenOutOfRange(): bool
{
return $this->disableCarrierWhenOutOfRange;
}
public function setDisableCarrierWhenOutOfRange(bool $disableCarrierWhenOutOfRange): Carrier
{
$this->disableCarrierWhenOutOfRange = $disableCarrierWhenOutOfRange;
return $this;
}
public function isModule(): bool
{
return $this->isModule;
}
public function setIsModule(bool $isModule): Carrier
{
$this->isModule = $isModule;
return $this;
}
public function isFree(): bool
{
return $this->isFree;
}
public function setIsFree(bool $isFree): Carrier
{
$this->isFree = $isFree;
return $this;
}
public function isShippingExternal(): bool
{
return $this->shippingExternal;
}
public function setShippingExternal(bool $shippingExternal): Carrier
{
$this->shippingExternal = $shippingExternal;
return $this;
}
public function isNeedRange(): bool
{
return $this->needRange;
}
public function setNeedRange(bool $needRange): Carrier
{
$this->needRange = $needRange;
return $this;
}
public function getExternalModuleName(): string
{
return $this->externalModuleName;
}
public function setExternalModuleName(string $externalModuleName): Carrier
{
$this->externalModuleName = $externalModuleName;
return $this;
}
public function getMaxWidth(): float
{
return $this->maxWidth;
}
public function setMaxWidth(float $maxWidth): Carrier
{
$this->maxWidth = $maxWidth;
return $this;
}
public function getMaxHeight(): float
{
return $this->maxHeight;
}
public function setMaxHeight(float $maxHeight): Carrier
{
$this->maxHeight = $maxHeight;
return $this;
}
public function getMaxDepth(): float
{
return $this->maxDepth;
}
public function setMaxDepth(float $maxDepth): Carrier
{
$this->maxDepth = $maxDepth;
return $this;
}
public function getMaxWeight(): float
{
return $this->maxWeight;
}
public function setMaxWeight(float $maxWeight): Carrier
{
$this->maxWeight = $maxWeight;
return $this;
}
public function getGrade(): int
{
return $this->grade;
}
public function setGrade(int $grade): Carrier
{
$this->grade = $grade;
return $this;
}
public function getDelay(): string
{
return $this->delay;
}
public function setDelay(string $delay): Carrier
{
$this->delay = $delay;
return $this;
}
public function getCurrency(): string
{
return $this->currency;
}
public function setCurrency(string $currency): Carrier
{
$this->currency = $currency;
return $this;
}
public function getWeightUnit(): string
{
return $this->weightUnit;
}
public function setWeightUnit(string $weightUnit): Carrier
{
$this->weightUnit = $weightUnit;
return $this;
}
public function getCountryIsoCodes(): array
{
return $this->countryIsoCodes;
}
public function setCountryIsoCodes(array $countryIsoCodes): Carrier
{
$this->countryIsoCodes = $countryIsoCodes;
return $this;
}
public function getCarrierDetails(): array
{
return $this->carrierDetails;
}
public function setCarrierDetails(array $carrierDetails): Carrier
{
$this->carrierDetails = $carrierDetails;
return $this;
}
public function getCarrierTaxes(): array
{
return $this->carrierTaxes;
}
public function setCarrierTaxes(array $carrierTaxes): Carrier
{
$this->carrierTaxes = $carrierTaxes;
return $this;
}
public function jsonSerialize()
{
$return = [];
$return[] = [
'collection' => $this->getCollection(),
'id' => (string) $this->getIdReference(),
'properties' => [
'id_carrier' => (string) $this->getIdCarrier(),
'id_reference' => (string) $this->getIdReference(),
'name' => (string) $this->getName(),
'carrier_taxes_rates_group_id' => (string) $this->getTaxesRatesGroupId(),
'url' => (string) $this->getUrl(),
'active' => (bool) $this->isActive(),
'deleted' => (bool) $this->isDeleted(),
'shipping_handling' => (float) $this->getShippingHandling(),
'free_shipping_starts_at_price' => (float) $this->getFreeShippingStartsAtPrice(),
'free_shipping_starts_at_weight' => (float) $this->getFreeShippingStartsAtWeight(),
'disable_carrier_when_out_of_range' => (bool) $this->isDisableCarrierWhenOutOfRange(),
'is_module' => (bool) $this->isModule(),
'is_free' => (bool) $this->isFree(),
'shipping_external' => (bool) $this->isShippingExternal(),
'need_range' => (bool) $this->isNeedRange(),
'external_module_name' => (string) $this->getExternalModuleName(),
'max_width' => (float) $this->getMaxWidth(),
'max_height' => (float) $this->getMaxHeight(),
'max_depth' => (float) $this->getMaxDepth(),
'max_weight' => (float) $this->getMaxWeight(),
'grade' => (int) $this->getGrade(),
'delay' => (string) $this->getDelay(),
'currency' => (string) $this->getCurrency(),
'weight_unit' => (string) $this->getWeightUnit(),
'country_ids' => (string) implode(',', $this->getCountryIsoCodes()),
],
];
$carrierDetails = [];
foreach ($this->getCarrierDetails() as $carrierDetail) {
$carrierDetails[] = $carrierDetail->jsonSerialize();
}
$carrierTaxRates = [];
foreach ($this->getCarrierTaxes() as $carrierTax) {
$carrierTaxRates[] = $carrierTax->jsonSerialize();
}
return array_merge($return, $carrierDetails, $carrierTaxRates);
}
}

View File

@@ -0,0 +1,239 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\DTO;
use JsonSerializable;
class CarrierDetail implements JsonSerializable
{
public const RANGE_BY_WEIGHT = 0;
public const RANGE_BY_PRICE = 1;
/**
* @var string
*/
private $collection = 'carrier_details';
/**
* @var string
*/
private $shippingMethod;
/**
* @var int
*/
private $carrierReference;
/**
* @var int
*/
private $carrierDetailId;
/**
* @var int
*/
private $zoneId;
/**
* @var int
*/
private $rangeId;
/**
* @var float
*/
private $delimiter1;
/**
* @var float
*/
private $delimiter2;
/**
* @var array
*/
private $countryIsoCodes;
/**
* @var array
*/
private $stateIsoCodes;
/**
* @var float
*/
private $price;
public function getCollection(): string
{
return $this->collection;
}
public function setCollection(string $collection): CarrierDetail
{
$this->collection = $collection;
return $this;
}
public function getShippingMethod(): string
{
return $this->shippingMethod;
}
public function setShippingMethod(string $shippingMethod): CarrierDetail
{
$this->shippingMethod = $shippingMethod;
return $this;
}
public function getCarrierReference(): int
{
return $this->carrierReference;
}
public function setCarrierReference(int $carrierReference): CarrierDetail
{
$this->carrierReference = $carrierReference;
return $this;
}
public function getCarrierDetailId(): int
{
return $this->carrierDetailId;
}
public function setCarrierDetailId(int $carrierDetailId): CarrierDetail
{
$this->carrierDetailId = $carrierDetailId;
return $this;
}
public function getZoneId(): int
{
return $this->zoneId;
}
public function setZoneId(int $zoneId): CarrierDetail
{
$this->zoneId = $zoneId;
return $this;
}
public function getRangeId(): int
{
return $this->rangeId;
}
public function setRangeId(int $rangeId): CarrierDetail
{
$this->rangeId = $rangeId;
return $this;
}
public function getDelimiter1(): float
{
return $this->delimiter1;
}
public function setDelimiter1(float $delimiter1): CarrierDetail
{
$this->delimiter1 = $delimiter1;
return $this;
}
public function getDelimiter2(): float
{
return $this->delimiter2;
}
public function setDelimiter2(float $delimiter2): CarrierDetail
{
$this->delimiter2 = $delimiter2;
return $this;
}
public function getCountryIsoCodes(): array
{
return $this->countryIsoCodes;
}
public function setCountryIsoCodes(array $countryIsoCodes): CarrierDetail
{
$this->countryIsoCodes = $countryIsoCodes;
return $this;
}
public function getStateIsoCodes(): array
{
return $this->stateIsoCodes;
}
public function setStateIsoCodes(array $stateIsoCodes): CarrierDetail
{
$this->stateIsoCodes = $stateIsoCodes;
return $this;
}
public function getPrice(): float
{
return $this->price;
}
public function setPrice(float $price): CarrierDetail
{
$this->price = $price;
return $this;
}
public function jsonSerialize()
{
$countryIds = implode(',', $this->getCountryIsoCodes());
$stateIds = implode(',', $this->getStateIsoCodes());
$shippingMethod = $this->getShippingMethod() === 'range_weight' ? self::RANGE_BY_WEIGHT : self::RANGE_BY_PRICE;
return [
'collection' => $this->getCollection(),
'id' => $this->getCarrierReference() . '-' . $this->getZoneId() . '-' . $shippingMethod . '-' . $this->getRangeId(),
'properties' => [
'id_reference' => (string) $this->getCarrierReference(),
'id_carrier_detail' => (string) $this->getCarrierDetailId(),
'shipping_method' => (string) $this->getShippingMethod(),
'delimiter1' => (float) $this->getDelimiter1(),
'delimiter2' => (float) $this->getDelimiter2(),
'country_ids' => (string) $countryIds,
'state_ids' => (string) $stateIds,
'price' => (float) $this->getPrice(),
],
];
}
}

View File

@@ -0,0 +1,142 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\DTO;
use JsonSerializable;
class CarrierTax implements JsonSerializable
{
/**
* @var string
*/
private $collection = 'carrier_taxes';
/**
* @var int
*/
private $carrierReference;
/**
* @var int
*/
private $taxRulesGroupId;
/**
* @var string
*/
private $countryIsoCode;
/**
* @var string
*/
private $stateIsoCodes;
/**
* @var float
*/
private $taxRate;
public function getCollection(): string
{
return $this->collection;
}
public function setCollection(string $collection): CarrierTax
{
$this->collection = $collection;
return $this;
}
public function getCarrierReference(): int
{
return $this->carrierReference;
}
public function setCarrierReference(int $carrierReference): CarrierTax
{
$this->carrierReference = $carrierReference;
return $this;
}
public function getTaxRulesGroupId(): int
{
return $this->taxRulesGroupId;
}
public function setTaxRulesGroupId(int $taxRulesGroupId): CarrierTax
{
$this->taxRulesGroupId = $taxRulesGroupId;
return $this;
}
public function getCountryIsoCode(): string
{
return $this->countryIsoCode;
}
public function setCountryIsoCode(string $countryIsoCode): CarrierTax
{
$this->countryIsoCode = $countryIsoCode;
return $this;
}
public function getStateIsoCodes(): string
{
return $this->stateIsoCodes;
}
public function setStateIsoCodes(string $stateIsoCodes): CarrierTax
{
$this->stateIsoCodes = $stateIsoCodes;
return $this;
}
public function getTaxRate(): float
{
return $this->taxRate;
}
public function setTaxRate(float $taxRate): CarrierTax
{
$this->taxRate = $taxRate;
return $this;
}
public function jsonSerialize()
{
return [
'collection' => $this->getCollection(),
'id' => $this->getCarrierReference(),
'properties' => [
'id_reference' => (string) $this->getCarrierReference(),
'id_carrier_tax' => (string) $this->getTaxRulesGroupId(),
'country_id' => (string) $this->getCountryIsoCode(),
'state_ids' => (string) $this->getStateIsoCodes(),
'tax_rate' => (float) $this->getTaxRate(),
],
];
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\DTO;
use JsonSerializable;
/**
* @see https://developers.google.com/analytics/devguides/collection/gtagjs/enhanced-ecommerce#action-data
*/
class ConversionEventData implements JsonSerializable
{
/**
* Value (i.e. revenue) associated with the event.
*
* @var string
*/
protected $value;
/**
* @var string
*/
protected $currency;
/**
* @var string
*/
protected $sendTo;
/**
* The transaction ID (e.g. T1234).
*
* @var string|null
*/
protected $transactionId;
public function jsonSerialize(): array
{
$eventData = [
'send_to' => $this->sendTo,
'value' => $this->value,
'currency' => $this->currency,
];
if ($this->transactionId) {
$eventData['transaction_id'] = $this->transactionId;
}
return $eventData;
}
/**
* @param string|int $transactionId
*
* @return self
*/
public function setTransactionId($transactionId)
{
$this->transactionId = $transactionId;
return $this;
}
/**
* Set value (i.e. revenue) associated with the event.
*
* @param string|null $value Value (i.e. revenue) associated with the event.
*
* @return self
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* @param string|null $currency
*
* @return self
*/
public function setCurrency($currency)
{
$this->currency = $currency;
return $this;
}
/**
* @param string|null $sendTo
*
* @return self
*/
public function setSendTo($sendTo)
{
$this->sendTo = $sendTo;
return $this;
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\DTO\Remarketing;
use JsonSerializable;
class ProductData implements JsonSerializable
{
/**
* The product ID or SKU (e.g. P67890).
*
* @var string
*/
protected $id;
/**
* The price of a product (e.g. 29.20).
* Kept as a float
*
* @var float|null
*/
protected $price;
/**
* The quantity of a product (e.g. 2).
*
* @var int|null
*/
protected $quantity;
public function jsonSerialize(): array
{
return [
'id' => $this->id,
'quantity' => $this->quantity,
'price' => $this->price,
];
}
/**
* Set the product ID or SKU (e.g. P67890).
*
* @param string $id The product ID or SKU (e.g. P67890).
*
* @return self
*/
public function setId(string $id)
{
$this->id = $id;
return $this;
}
/**
* Set kept as a string to avoid float issues
*
* @param float|null $price Kept as a string to avoid float issues
*
* @return self
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Set the quantity of a product (e.g. 2).
*
* @param int|null $quantity The quantity of a product (e.g. 2).
*
* @return self
*/
public function setQuantity($quantity)
{
$this->quantity = $quantity;
return $this;
}
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\DTO\Remarketing;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\ConversionEventData;
class PurchaseEventData extends ConversionEventData
{
/**
* @var ProductData[]
*/
protected $items;
/**
* @var int
*/
protected $awMerchandId;
/**
* @var string
*/
protected $awFeedCountry;
/**
* @var string
*/
protected $awFeedLanguage;
/**
* @var float
*/
protected $discount;
public function jsonSerialize(): array
{
return array_merge(
parent::jsonSerialize(),
[
'items' => $this->items,
'discount' => $this->discount,
'aw_merchant_id' => $this->awMerchandId,
'aw_feed_country' => $this->awFeedCountry,
'aw_feed_language' => $this->awFeedLanguage,
]
);
}
/**
* Set the value of awFeedLanguage
*
* @param string $awFeedLanguage
*
* @return self
*/
public function setAwFeedLanguage(string $awFeedLanguage)
{
$this->awFeedLanguage = $awFeedLanguage;
return $this;
}
/**
* Set the value of awMerchandId
*
* @param int $awMerchandId
*
* @return self
*/
public function setAwMerchandId(int $awMerchandId)
{
$this->awMerchandId = $awMerchandId;
return $this;
}
/**
* Set the value of awFeedCountry
*
* @param string $awFeedCountry
*
* @return self
*/
public function setAwFeedCountry(string $awFeedCountry)
{
$this->awFeedCountry = $awFeedCountry;
return $this;
}
/**
* Set the value of items
*
* @param array $items
*
* @return self
*/
public function setItems(array $items)
{
$this->items = $items;
return $this;
}
/**
* Set the value of discount
*
* @param float $discount
*
* @return self
*/
public function setDiscount(float $discount)
{
$this->discount = $discount;
return $this;
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,223 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Database;
use Exception;
use Language;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Exception\MktgWithGoogleInstallerException;
use PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler;
use PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment;
use PsxMarketingWithGoogle;
use Tab;
class Installer
{
public const CLASS_NAME = 'Installer';
private $module;
/**
* @var array
*/
private $errors = [];
/**
* @var Segment
*/
private $segment;
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(PsxMarketingWithGoogle $module, Segment $segment, ErrorHandler $errorHandler)
{
$this->module = $module;
$this->segment = $segment;
$this->errorHandler = $errorHandler;
}
/**
* @return bool
*/
public function install()
{
$this->segment->setMessage('PSX Marketing With Google installed');
$this->segment->track();
return $this->installConfiguration() &&
$this->installTabs() &&
$this->installTables();
}
/**
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* Install configuration for each shop
*
* @return bool
*/
public function installConfiguration()
{
$result = true;
foreach (\Shop::getShops(false, null, true) as $shopId) {
/* todo: remove ignore when first configuration is added to the list */
/* @phpstan-ignore-next-line */
foreach (Config::CONFIGURATION_LIST as $name => $value) {
if (false === \Configuration::hasKey((string) $name, null, null, (int) $shopId)) {
$result = $result && \Configuration::updateValue(
(string) $name,
$value,
false,
null,
(int) $shopId
);
}
}
}
return $result;
}
/**
* This method is often use to create an ajax controller
*
* @return bool
*/
public function installTabs()
{
$installTabCompleted = true;
foreach ($this->getTabs() as $tab) {
try {
$installTabCompleted = $installTabCompleted && $this->installTab(
$tab['className'],
$tab['parent'],
$tab['name'],
$tab['module'],
$tab['active'],
$tab['icon']
);
} catch (Exception $e) {
$this->errorHandler->handle(
new MktgWithGoogleInstallerException(
'Failed to install module tabs',
MktgWithGoogleInstallerException::MKTG_WITH_GOOGLE_INSTALL_EXCEPTION,
$e
),
MktgWithGoogleInstallerException::MKTG_WITH_GOOGLE_INSTALL_EXCEPTION,
false
);
$this->errors[] = sprintf($this->module->l('Failed to install %1s tab', self::CLASS_NAME), $tab['className']);
return false;
}
}
return $installTabCompleted;
}
public function installTab($className, $parent, $name, $module, $active, $icon)
{
if (Tab::getIdFromClassName($className)) {
return true;
}
$idParent = is_int($parent) ? $parent : Tab::getIdFromClassName($parent);
$moduleTab = new Tab();
$moduleTab->class_name = $className;
$moduleTab->id_parent = $idParent;
$moduleTab->module = $module;
$moduleTab->active = $active;
if (property_exists($moduleTab, 'icon')) {
$moduleTab->icon = $icon;
}
$languages = Language::getLanguages(true);
foreach ($languages as $language) {
$moduleTab->name[$language['id_lang']] = $name;
}
return $moduleTab->add();
}
public function installTables()
{
try {
include dirname(__FILE__) . '/../../sql/install.php';
} catch (\Exception $e) {
$this->errorHandler->handle(
new MktgWithGoogleInstallerException(
'Failed to install database tables',
MktgWithGoogleInstallerException::MKTG_WITH_GOOGLE_UNINSTALL_EXCEPTION,
$e
),
$e->getCode(),
false
);
$this->errors[] = $this->module->l('Failed to install database tables', self::CLASS_NAME);
return false;
}
return true;
}
private function getTabs()
{
return [
[
'className' => 'Marketing',
'parent' => 'IMPROVE',
'name' => 'Marketing',
'module' => '',
'active' => true,
'icon' => 'campaign',
],
[
'className' => 'AdminPsxMktgWithGoogleModule',
'parent' => 'Marketing',
'name' => 'Google',
'module' => $this->module->name,
'active' => true,
'icon' => '',
],
[
'className' => 'AdminAjaxPsxMktgWithGoogle',
'parent' => -1,
'name' => $this->module->name,
'module' => $this->module->name,
'active' => true,
'icon' => '',
],
];
}
}

View File

@@ -0,0 +1,154 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Database;
use Exception;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Exception\MktgWithGoogleInstallerException;
use PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\TabRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment;
class Uninstaller
{
public const CLASS_NAME = 'Uninstaller';
/**
* @var TabRepository
*/
private $tabRepository;
/**
* @var Segment
*/
private $segment;
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(
TabRepository $tabRepository,
Segment $segment,
ErrorHandler $errorHandler
) {
$this->tabRepository = $tabRepository;
$this->segment = $segment;
$this->errorHandler = $errorHandler;
}
/**
* @return bool
*
* @throws Exception
*/
public function uninstall()
{
$this->segment->setMessage('PS Google shopping uninstalled');
$this->segment->track();
/* todo: remove ignore when first configuration is added to the list */
/* @phpstan-ignore-next-line */
foreach (array_keys(Config::CONFIGURATION_LIST) as $name) {
\Configuration::deleteByName((string) $name);
}
return $this->uninstallTabs() && $this->uninstallTables();
}
/**
* @return bool
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException|Exception
*/
private function uninstallTabs()
{
$uninstallTabCompleted = true;
try {
foreach (Config::MODULE_ADMIN_CONTROLLERS as $controllerName) {
$id_tab = (int) \Tab::getIdFromClassName($controllerName);
$tab = new \Tab($id_tab);
if (\Validate::isLoadedObject($tab)) {
$uninstallTabCompleted = $uninstallTabCompleted && $tab->delete();
}
}
$uninstallTabCompleted = $uninstallTabCompleted && $this->uninstallMarketingTab();
} catch (Exception $e) {
$this->errorHandler->handle(
new MktgWithGoogleInstallerException(
'Failed to uninstall module tabs',
MktgWithGoogleInstallerException::MKTG_WITH_GOOGLE_UNINSTALL_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return $uninstallTabCompleted;
}
/**
* @return bool
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException
*/
private function uninstallMarketingTab()
{
$id_tab = (int) \Tab::getIdFromClassName('Marketing');
$tab = new \Tab($id_tab);
if (!\Validate::isLoadedObject($tab)) {
return true;
}
if ($this->tabRepository->hasChildren($id_tab)) {
return true;
}
return $tab->delete();
}
public function uninstallTables()
{
try {
include dirname(__FILE__) . '/../../sql/uninstall.php';
} catch (\Exception $e) {
$this->errorHandler->handle(
new MktgWithGoogleInstallerException(
'Failed to uninstall database tables',
MktgWithGoogleInstallerException::MKTG_WITH_GOOGLE_UNINSTALL_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return true;
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,34 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Exception;
use Exception;
class ApiClientException extends Exception
{
public const REQUEST_EXCEPTION = 501;
public const GET_EXCEPTION = 502;
public const POST_EXCEPTION = 503;
public const DELETE_EXCEPTION = 504;
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Exception;
use Exception;
class MktgWithGoogleInstallerException extends Exception
{
public const MKTG_WITH_GOOGLE_INSTALL_EXCEPTION = 1;
public const MKTG_WITH_GOOGLE_UNINSTALL_EXCEPTION = 2;
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,93 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Factory;
use Configuration;
use Context;
use Currency;
class ContextFactory
{
public static function getContext()
{
return Context::getContext();
}
public static function getLanguage()
{
return Context::getContext()->language;
}
public static function getCart()
{
return Context::getContext()->cart;
}
/**
* Return the currency present in the context, or the default one
* when the context doesn't have a currency yet (i.e when user session is empty).
*
* @return Currency
*/
public static function getCurrency()
{
if (Context::getContext()->currency !== null) {
return Context::getContext()->currency;
}
return new Currency((int) Configuration::get('PS_CURRENCY_DEFAULT'));
}
public static function getCustomer()
{
return Context::getContext()->customer;
}
public static function getSmarty()
{
return Context::getContext()->smarty;
}
public static function getShop()
{
return Context::getContext()->shop;
}
public static function getController()
{
return Context::getContext()->controller;
}
public static function getCookie()
{
return Context::getContext()->cookie;
}
public static function getLink()
{
return Context::getContext()->link;
}
public static function getCountry()
{
return Context::getContext()->country;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Factory;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Env;
class ParametersFactory
{
public static function getBillingEnv()
{
return (bool) (new Env())->get('USE_BILLING_SANDBOX');
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,126 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Handler;
use Exception;
use Module;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
use PsxMarketingWithGoogle;
/**
* Handle Error.
*/
class ErrorHandler
{
/**
* @var ModuleFilteredRavenClient
*/
protected $client;
/**
* @var ErrorHandler
*/
private static $instance;
public function __construct()
{
/** @var PsxMarketingWithGoogle */
$module = Module::getInstanceByName('psxmarketingwithgoogle');
$this->client = new ModuleFilteredRavenClient(
Config::PSX_MKTG_WITH_GOOGLE_SENTRY_CREDENTIALS_PHP,
[
'level' => 'warning',
'tags' => [
'php_version' => phpversion(),
'psxmarketingwithgoogle_version' => $module->version,
'prestashop_version' => _PS_VERSION_,
'psxmarketingwithgoogle_is_enabled' => \Module::isEnabled('psxmarketingwithgoogle'),
'psxmarketingwithgoogle_is_installed' => \Module::isInstalled('psxmarketingwithgoogle'),
],
'release' => "v{$module->version}",
]
);
try {
$psAccountsService = $module->getService(PsAccounts::class)->getPsAccountsService();
$this->client->user_context([
'id' => $psAccountsService->getShopUuidV4(),
]);
} catch (Exception $e) {
// Do nothing
}
// We use realpath to get errors even if module is behind a symbolic link
$this->client->setAppPath(realpath(_PS_MODULE_DIR_ . $module->name . '/'));
// - Do no not add the shop root folder, it will exclude everything even if specified in the app path.
// - Excluding vendor/ avoids errors comming from one of your libraries library when called by another module.
$this->client->setExcludedAppPaths([
realpath(_PS_MODULE_DIR_ . $module->name . '/vendor/'),
]);
$this->client->setExcludedDomains(['127.0.0.1', 'localhost', '.local']);
if (version_compare(phpversion(), '7.4.0', '>=') && version_compare(_PS_VERSION_, '1.7.8.0', '<')) {
return;
}
$this->client->install();
}
/**
* @param \Exception $error
* @param mixed $code
* @param bool|null $throw
* @param array|null $data
*
* @return void
*
* @throws \Exception
*/
public function handle($error, $code = null, $throw = true, $data = null)
{
$this->client->captureException($error, $data);
if ($code && true === $throw) {
http_response_code($code);
throw $error;
}
}
/**
* @return ErrorHandler
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new ErrorHandler();
}
return self::$instance;
}
/**
* @return void
*/
private function __clone()
{
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Handler;
use Raven_Client;
/**
* Inheritance allow us to check data generated by Raven and filter errors
* that are not related to the module.
* Raven does not filter errors by itself depending on the appPath and any
* excludedAppPaths, but declares what phase of the stack trace is outside the app.
* We use this data to allow each module filtering their own errors.
*
* IMPORTANT NOTE: This class is present is this module during the
* stabilisation phase, and will be moved later in a library.
*/
class ModuleFilteredRavenClient extends Raven_Client
{
/**
* @var string[]|null
*/
protected $excluded_domains;
public function capture($data, $stack = null, $vars = null)
{
/*
Content of $data:
array:2 [▼
"exception" => array:1 [▼
"values" => array:1 [▼
0 => array:3 [▼
"value" => "Class 'DogeInPsFacebook' not found"
"type" => "Error"
"stacktrace" => array:1 [▼
"frames" => array:4 [▼
0 => array:7 [▼
"filename" => "index.php"
"lineno" => 93
"function" => null
"pre_context" => array:5 [▶]
"context_line" => " Dispatcher::getInstance()->dispatch();"
"post_context" => array:2 [▶]
"in_app" => false
1 => array:3 [▼
[Can be defined when a subexception is set]
*/
if (!isset($data['exception']['values'][0]['stacktrace']['frames'])) {
return null;
}
if ($this->isErrorFilteredByContext()) {
return null;
}
$allowCapture = false;
foreach ($data['exception']['values'] as $errorValues) {
$allowCapture = $allowCapture || $this->isErrorInApp($errorValues);
}
if (!$allowCapture) {
return null;
}
return parent::capture($data, $stack, $vars);
}
/**
* @return self
*/
public function setExcludedDomains(array $domains)
{
$this->excluded_domains = $domains;
return $this;
}
/**
* @return bool
*/
private function isErrorInApp(array $data)
{
$atLeastOneFileIsInApp = false;
foreach ($data['stacktrace']['frames'] as $frame) {
$atLeastOneFileIsInApp = $atLeastOneFileIsInApp || ((isset($frame['in_app']) && $frame['in_app']));
}
return $atLeastOneFileIsInApp;
}
/**
* Check the conditions in which the error is thrown, so we can apply filters
*
* @return bool
*/
private function isErrorFilteredByContext()
{
if ($this->excluded_domains && !empty($_SERVER['REMOTE_ADDR'])) {
foreach ($this->excluded_domains as $domain) {
if (strpos($_SERVER['REMOTE_ADDR'], $domain) !== false) {
return true;
}
}
}
return false;
}
}

View File

@@ -0,0 +1,222 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Handler;
use Context;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Buffer\TemplateBuffer;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Conversion\UserDataProvider;
use PrestaShop\Module\PsxMarketingWithGoogle\Provider\CartEventDataProvider;
use PrestaShop\Module\PsxMarketingWithGoogle\Provider\PageViewEventDataProvider;
use PrestaShop\Module\PsxMarketingWithGoogle\Provider\PurchaseEventDataProvider;
use PsxMarketingWithGoogle;
class RemarketingHookHandler
{
/**
* @var ConfigurationAdapter
*/
protected $configurationAdapter;
/**
* @var TemplateBuffer
*/
protected $templateBuffer;
/**
* @var Context
*/
protected $context;
/**
* @var PsxMarketingWithGoogle
*/
protected $module;
/**
* @var bool
*/
protected $active;
/**
* @var bool
*/
protected $enhancedConversionActive;
/**
* @var array
*/
protected $conversionLabels;
public function __construct(ConfigurationAdapter $configurationAdapter, TemplateBuffer $templateBuffer, Context $context, $module)
{
$this->configurationAdapter = $configurationAdapter;
$this->templateBuffer = $templateBuffer;
$this->context = $context;
$this->module = $module;
$this->active = (bool) $this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS)
&& (bool) $this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG)
&& in_array($this->context->controller->controller_type, ['front', 'modulefront']);
$this->enhancedConversionActive = (bool) $this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_ENHANCED_STATUS);
$this->conversionLabels = json_decode($this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_CONVERSION_LABELS), true)
?: [];
if ($this->active) {
$this->templateBuffer->init($this->findIdentifierFromContext($context));
}
}
public function handleHook(string $hookName, array $data = []): string
{
if (!$this->active) {
return '';
}
switch ($hookName) {
case 'hookDisplayTop':
if (($sendTo = $this->getSendTo(Config::REMARKETING_CONVERSION_LABEL_PAGE_VIEW)) === null) {
break;
}
$eventData = $this->module->getService(PageViewEventDataProvider::class)->getEventData($sendTo);
if ($eventData === null) {
break;
}
$this->context->smarty->assign([
'eventData' => $eventData,
]);
$this->templateBuffer->add(
$this->module->display($this->module->getfilePath(), 'views/templates/hook/gtagEvent.tpl')
);
break;
case 'hookDisplayOrderConfirmation':
if (($sendTo = $this->getSendTo(Config::REMARKETING_CONVERSION_LABEL_PURCHASE)) === null) {
break;
}
$this->context->smarty->assign([
'eventData' => $this->module->getService(PurchaseEventDataProvider::class)->getEventData($sendTo, $data['order']),
]);
$this->templateBuffer->add(
$this->module->display($this->module->getfilePath(), 'views/templates/hook/gtagEvent.tpl')
);
break;
case 'hookActionCartUpdateQuantityBefore':
if ($data['operator'] !== 'up') {
break;
}
if (($sendTo = $this->getSendTo(Config::REMARKETING_CONVERSION_LABEL_ADD_TO_CART)) === null) {
break;
}
$this->context->smarty->assign([
'eventData' => $this->module->getService(CartEventDataProvider::class)->getEventData($sendTo, $data),
]);
$this->templateBuffer->add(
$this->module->display($this->module->getfilePath(), 'views/templates/hook/gtagEvent.tpl')
);
break;
}
if ($hookName === 'hookDisplayHeader') {
$snippet = base64_decode($this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG));
if (!$this->enhancedConversionActive) {
return $snippet;
}
$userData = $this->module->getService(UserDataProvider::class)->getUserData();
if ($userData->isEmpty()) {
return $snippet;
}
$this->context->smarty->assign([
'userData' => $userData,
]);
return $snippet . $this->module->display($this->module->getfilePath(), 'views/templates/hook/enhancedConversions.tpl');
}
// Return the existing content in case we have a display hook
if (strpos($hookName, 'Display') === 4 && !$this->isCurrentRequestAnAjax()) {
return $this->templateBuffer->flush();
}
return '';
}
private function getSendTo($eventName)
{
if (!empty($this->conversionLabels[$eventName])) {
return $this->conversionLabels[$eventName];
}
return null;
}
/**
* @return bool
*/
private function isCurrentRequestAnAjax()
{
/*
* An ajax property is available in controllers
* when the whole page template should not be generated.
*/
if ($this->context->controller->ajax) {
return true;
}
/*
* In case the ajax property is not properly set, there is
* another check available.
*/
if ($this->context->controller->isXmlHttpRequest()) {
return true;
}
return false;
}
/**
* @return string
*/
private function findIdentifierFromContext(Context $context)
{
if (!empty($context->customer->id_guest)) {
return 'guest_' . $context->customer->id_guest;
}
if (!empty($context->cart->id)) {
return 'cart_' . $context->cart->id;
}
return '';
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,245 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
declare(strict_types=1);
namespace PrestaShop\Module\PsxMarketingWithGoogle\Http;
use RuntimeException;
class HttpClient
{
private $curl;
/** @var array<int|string,string> */
private $headers = [];
/** @var array<int|string,bool|int> */
private $options = [];
/** @var string */
private $baseUrl = '';
/**
* Constructor initializes cURL
*
* @param string $baseUrl Optional base URL for all requests
*
* @throws RuntimeException if cURL extension is not loaded
*/
public function __construct(string $baseUrl = '')
{
if (!extension_loaded('curl')) {
throw new RuntimeException('cURL extension is not loaded');
}
$this->baseUrl = rtrim($baseUrl, '/');
$this->curl = curl_init();
// Set default options
$this->setDefaultOptions();
}
/**
* Set default cURL options
*/
private function setDefaultOptions(): void
{
$this->options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
];
}
/**
* Set custom headers for the request
*
* @param array<int|string,string> $headers
*
* @return self
*/
public function setHeaders(array $headers): self
{
$this->headers = $headers;
return $this;
}
/**
* Add a single header
*
* @param string $name
* @param string $value
*
* @return self
*/
public function addHeader(string $name, string $value): self
{
$this->headers[] = "$name: $value";
return $this;
}
/**
* Set custom cURL options
*
* @param array<string,bool|int> $options
*
* @return self
*/
public function setOptions(array $options): self
{
$this->options = $options + $this->options;
return $this;
}
/**
* Execute HTTP request
*
* @param string $method HTTP method
* @param string $url URL endpoint
* @param array<string,string|bool|int>|string|null $data Request data
*
* @return Response
*
* @throws RuntimeException on cURL errors
*/
public function request(string $method, string $url, $data = null)
{
$url = $this->baseUrl . '/' . ltrim($url, '/');
$options = $this->options + [
CURLOPT_URL => $url,
CURLOPT_CUSTOMREQUEST => strtoupper($method),
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => $this->headers,
];
if ($data !== null) {
if (is_array($data)) {
$data = http_build_query($data);
}
if ($method === 'GET') {
/* @phpstan-ignore-next-line */
$options[CURLOPT_URL] .= '?' . $data;
} else {
$options[CURLOPT_POSTFIELDS] = $data;
}
}
curl_setopt_array($this->curl, $options);
$response = curl_exec($this->curl);
if ($response === false) {
throw new \RuntimeException(sprintf('cURL error (%s): %s', curl_errno($this->curl), curl_error($this->curl)));
}
$headerSize = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE);
$httpCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
// Split response into headers and body
$headerStr = substr((string) $response, 0, $headerSize);
$body = substr((string) $response, $headerSize);
$error = curl_error($this->curl);
// Parse headers
$headers = [];
foreach (explode("\r\n", $headerStr) as $line) {
if (preg_match('/^([^:]+):(.+)$/', $line, $matches)) {
$headers[trim($matches[1])] = trim($matches[2]);
}
}
return new Response(
$httpCode,
$body,
$headers,
$error
);
}
/**
* Convenience method for GET requests
*
* @param string $url
* @param array<string, string> $params Query parameters
*
* @return Response
*/
public function get(string $url, array $params = [])
{
return $this->request('GET', $url, $params);
}
/**
* Convenience method for POST requests
*
* @param string $url
* @param array<string, string>|string $data
*
* @return Response
*/
public function post(string $url, $data = [])
{
return $this->request('POST', $url, $data);
}
/**
* Convenience method for PUT requests
*
* @param string $url
* @param array<string, string>|string $data
*
* @return Response
*/
public function put(string $url, $data = [])
{
return $this->request('PUT', $url, $data);
}
/**
* Convenience method for DELETE requests
*
* @param string $url
* @param array<string, string> $params
*
* @return Response
*/
public function delete(string $url, array $params = [])
{
return $this->request('DELETE', $url, $params);
}
/**
* Destructor closes cURL connection
*/
public function __destruct()
{
if ($this->curl) {
curl_close($this->curl);
}
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
declare(strict_types=1);
namespace PrestaShop\Module\PsxMarketingWithGoogle\Http;
class Response
{
/** @var int */
private $statusCode;
/** @var string */
private $body;
/** @var array<string,string> */
private $headers;
/** @var string|null */
private $error;
/**
* @param int $statusCode
* @param string $body
* @param array<string,string> $headers
* @param string|null $error
*
**/
public function __construct($statusCode, $body, $headers = [], $error = null)
{
$this->statusCode = $statusCode;
$this->body = $body;
$this->headers = $headers;
$this->error = $error;
}
/**
* @return int
*/
public function getStatusCode()
{
return $this->statusCode;
}
/**
* @return array<string,string>
*/
public function getHeaders()
{
return $this->headers;
}
/**
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* @return string|null
*/
public function getError()
{
return $this->error;
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,124 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter;
class AttributeMapConditionOutput
{
const STRING = 'string';
const INT = 'int';
const BOOLEAN = 'boolean';
const OBJECT = 'object';
const MAP = [
AttributeType::BRAND => [
Condition::DOES_CONTAIN => [
'multiple' => true,
'type' => self::STRING,
],
Condition::DOES_NOT_CONTAIN => [
'multiple' => true,
'type' => self::STRING,
],
Condition::IS => [
'multiple' => true,
'type' => self::OBJECT,
'keys' => ['value', 'id'],
],
Condition::IS_NOT => [
'multiple' => true,
'type' => self::OBJECT,
'keys' => ['value', 'id'],
],
],
AttributeType::CATEGORY => [
Condition::DOES_CONTAIN => [
'multiple' => true,
'type' => self::STRING,
],
Condition::DOES_NOT_CONTAIN => [
'multiple' => true,
'type' => self::STRING,
],
Condition::IS => [
'multiple' => true,
'type' => self::OBJECT,
'keys' => ['value', 'id'],
],
Condition::IS_NOT => [
'multiple' => true,
'type' => self::OBJECT,
'keys' => ['value', 'id'],
],
],
AttributeType::PRICE => [
Condition::IS => [
'multiple' => false,
'type' => self::INT,
'positive' => true,
'integer' => false,
],
Condition::GREATER => [
'multiple' => false,
'type' => self::INT,
'positive' => true,
'integer' => false,
],
Condition::LOWER => [
'multiple' => false,
'type' => self::INT,
'positive' => true,
'integer' => false,
],
],
AttributeType::PRODUCT_ID => [
Condition::IS => [
'multiple' => true,
'type' => self::INT,
'positive' => true,
'integer' => true,
],
Condition::IS_NOT => [
'multiple' => true,
'type' => self::INT,
'positive' => true,
'integer' => true,
],
],
AttributeType::OUT_OF_STOCK => [
Condition::IS => [
'multiple' => false,
'type' => self::BOOLEAN,
],
],
AttributeType::FEATURE => [
Condition::IS => [
'multiple' => true,
'type' => self::OBJECT,
'keys' => ['id', 'key', 'value', 'language'],
],
Condition::IS_NOT => [
'multiple' => true,
'type' => self::OBJECT,
'keys' => ['id', 'key', 'value', 'language'],
],
],
];
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter;
/**
* enum only exists from PHP 8 and the module is compliant with PHP 7.2+,
* thus cannot be used here.
*/
class AttributeType
{
const BRAND = 'brand';
const CATEGORY = 'category';
const FEATURE = 'feature';
const PRICE = 'price';
const PRODUCT_ID = 'id';
const OUT_OF_STOCK = 'out_of_stock';
public static function all()
{
return [
static::BRAND,
static::CATEGORY,
static::FEATURE,
static::PRICE,
static::PRODUCT_ID,
static::OUT_OF_STOCK,
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter;
/**
* enum only exists from PHP 8 and the module is compliant with PHP 7.2+,
* thus cannot be used here.
*/
class Condition
{
const DOES_CONTAIN = 'does_contain';
const DOES_NOT_CONTAIN = 'does_not_contain';
const GREATER = 'greater';
const LOWER = 'lower';
const IS = 'is';
const IS_NOT = 'is_not';
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Condition;
class BrandQueryBuilder implements QueryBuilderInterface
{
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery
{
switch ($filter['condition']) {
case Condition::DOES_CONTAIN:
$queryConditions = [];
foreach ($filter['value'] as $value) {
$queryConditions[] = 'm' . $index . '.name LIKE "%' . pSQL($value) . '%"';
}
return $query->where('(' . implode(' OR ', $queryConditions) . ')');
case Condition::DOES_NOT_CONTAIN:
$queryConditions = [];
foreach ($filter['value'] as $value) {
$queryConditions[] = 'm' . $index . '.name NOT LIKE "%' . pSQL($value) . '%"';
}
return $query->where('(' . implode(' OR ', $queryConditions) . ')');
case Condition::IS:
$filteredValues = array_map(function ($item) {
return $item['value'];
}, $filter['value']);
return $query->where('m' . $index . '.name IN ("' . implode('", "', array_map('pSQL', $filteredValues)) . '")');
case Condition::IS_NOT:
$filteredValues = array_map(function ($item) {
return $item['value'];
}, $filter['value']);
return $query->where('m' . $index . '.name NOT IN ("' . implode('", "', array_map('pSQL', $filteredValues)) . '")');
}
return $query;
}
public function addRelations(DbQuery $query, int $index): DbQuery
{
return $query->innerJoin('manufacturer', 'm' . $index, 'm' . $index . '.id_manufacturer = p.id_manufacturer')
->where('m' . $index . '.active = 1');
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use Context;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Condition;
class CategoryQueryBuilder implements QueryBuilderInterface
{
/**
* @var Context
*/
protected $context;
public function __construct(Context $context)
{
$this->context = $context;
}
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery
{
// At the time of implementation, CloudSync gets only the default category of the product.
// We add the condition based on the default category here as well.
switch ($filter['condition']) {
case Condition::DOES_CONTAIN:
$queryConditions = [];
foreach ($filter['value'] as $value) {
$queryConditions[] = 'cl' . $index . '.name LIKE "%' . pSQL($value) . '%"';
}
return $query->where('(' . implode(' OR ', $queryConditions) . ')');
case Condition::DOES_NOT_CONTAIN:
$queryConditions = [];
foreach ($filter['value'] as $value) {
$queryConditions[] = 'cl' . $index . '.name NOT LIKE "%' . pSQL($value) . '%"';
}
return $query->where('(' . implode(' OR ', $queryConditions) . ')');
case Condition::IS:
$filteredValues = array_map(function ($item) {
return $item['id'];
}, $filter['value']);
return $query->where('c' . $index . '.id_category IN (' . implode(', ', array_map('intval', $filteredValues)) . ')');
case Condition::IS_NOT:
$filteredValues = array_map(function ($item) {
return $item['id'];
}, $filter['value']);
return $query->where('c' . $index . '.id_category NOT IN (' . implode(', ', array_map('intval', $filteredValues)) . ')');
}
return $query;
}
public function addRelations(DbQuery $query, int $index): DbQuery
{
return $query->innerJoin('category_product', 'cp' . $index, 'cp' . $index . '.id_product = p.id_product')
->innerJoin('category', 'c' . $index, 'c' . $index . '.id_category = cp' . $index . '.id_category')
->innerJoin('category_lang', 'cl' . $index, 'c' . $index . '.id_category = cl' . $index . '.id_category')
->where('cl' . $index . '.id_lang = ' . (int) $this->context->language->id)
->where('c' . $index . '.active = 1');
}
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use Context;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Condition;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\LanguageRepository;
class FeatureQueryBuilder implements QueryBuilderInterface
{
/**
* @var Context
*/
protected $context;
/**
* @var LanguageRepository
*/
protected $languageRepository;
/**
* @var string
*/
protected $currentLanguageIsoCode;
public function __construct(
Context $context,
LanguageRepository $languageRepository
) {
$this->context = $context;
$this->languageRepository = $languageRepository;
$this->currentLanguageIsoCode = $this->languageRepository->getIsoById(
(int) $this->context->language->id
);
}
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery
{
$uniqueFeature = [];
foreach ($filter['value'] as $value) {
$uniqueFeature[$value['id']] = $value;
}
$uniqueFeature = array_values($uniqueFeature);
switch ($filter['condition']) {
case Condition::IS:
$queryConditions = [];
foreach ($uniqueFeature as $value) {
$queryConditions[] = 'fvl' . $index . '.value = "' . pSQL($value['value']) . '"';
}
return $query->where('fl' . $index . '.name = "' . pSQL($uniqueFeature[0]['key']) . '" AND (' . implode(' OR ', $queryConditions) . ')');
case Condition::IS_NOT:
$queryConditions = [];
foreach ($uniqueFeature as $value) {
$queryConditions[] = 'fvl' . $index . '.value <> "' . pSQL($value['value']) . '"';
}
return $query->where('fl' . $index . '.name = "' . pSQL($uniqueFeature[0]['key']) . '" AND (' . implode(' AND ', $queryConditions) . ')');
}
return $query;
}
public function addRelations(DbQuery $query, int $index): DbQuery
{
return $query
->leftJoin('feature_product', 'fp' . $index, 'fp' . $index . '.id_product = p.id_product')
->innerJoin('feature_shop', 'fs' . $index, 'fs' . $index . '.id_feature = fp' . $index . '.id_feature')
->innerJoin('feature_lang', 'fl' . $index, 'fl' . $index . '.id_feature = fp' . $index . '.id_feature')
->innerJoin('feature_value', 'fv' . $index, 'fv' . $index . '.id_feature = fp' . $index . '.id_feature')
->innerJoin('feature_value_lang', 'fvl' . $index, '(fvl' . $index . '.id_feature_value = fv' . $index . '.id_feature_value AND fp' . $index . '.id_feature_value = fvl' . $index . '.id_feature_value AND fl' . $index . '.id_lang = fvl' . $index . '.id_lang)')
->where('fs' . $index . '.id_shop = ' . (int) $this->context->shop->id);
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Condition;
class OutOfStockQueryBuilder implements QueryBuilderInterface
{
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery
{
if ($filter['condition'] === Condition::IS) {
return $filter['value'] ? $query->where('sa' . $index . '.quantity <= 0') : $query->where('sa' . $index . '.quantity > 0');
}
return $query;
}
public function addRelations(DbQuery $query, int $index): DbQuery
{
return $query->innerJoin('stock_available', 'sa' . $index, 'sa' . $index . '.id_product = p.id_product');
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Condition;
class PriceQueryBuilder implements QueryBuilderInterface
{
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery
{
switch ($filter['condition']) {
case Condition::GREATER:
return $query->where('(
p.price > ' . (float) $filter['value'] . '
OR (p.price + pa' . $index . '.price) > ' . (float) $filter['value'] . '
)');
case Condition::LOWER:
return $query->where('(
p.price < ' . (float) $filter['value'] . '
OR (p.price + pa' . $index . '.price) < ' . (float) $filter['value'] . '
)');
case Condition::IS:
return $query->where('(
p.price = ' . (float) $filter['value'] . '
OR (p.price + pa' . $index . '.price) = ' . (float) $filter['value'] . '
)');
}
return $query;
}
public function addRelations(DbQuery $query, int $index): DbQuery
{
return $query->leftJoin('product_attribute', 'pa' . $index, 'pa' . $index . '.id_product = p.id_product');
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Condition;
class ProductIdQueryBuilder implements QueryBuilderInterface
{
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery
{
switch ($filter['condition']) {
case Condition::IS:
return $query->where('p.id_product IN (' . implode(', ', array_map('intval', $filter['value'])) . ')');
case Condition::IS_NOT:
return $query->where('p.id_product NOT IN (' . implode(', ', array_map('intval', $filter['value'])) . ')');
}
return $query;
}
public function addRelations(DbQuery $query, int $index): DbQuery
{
// Do nothing, product data is already loaded
return $query;
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder;
use DbQuery;
interface QueryBuilderInterface
{
public function addWhereFromFilter(DbQuery $query, $filter, int $index): DbQuery;
public function addRelations(DbQuery $query, int $index): DbQuery;
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,300 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication;
use InvalidArgumentException;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\AttributeMapConditionOutput;
class FilterValidator
{
/**
* @throws InvalidArgumentException
*
* See https://phpstan.org/writing-php-code/phpdoc-types#general-arrays
*/
public function validate(array $filters): void
{
foreach ($filters as $index => $filter) {
if (!isset(AttributeMapConditionOutput::MAP[$filter['attribute']])) {
throw new InvalidArgumentException('Filter #' . $index . ' has no valid "attribute" field.');
}
$attributeConditions = AttributeMapConditionOutput::MAP[$filter['attribute']];
if (!isset($attributeConditions[$filter['condition']])) {
throw new InvalidArgumentException('Filter #' . $index . ' has no valid "condition" field.');
}
$conditionRequirements = $attributeConditions[$filter['condition']];
$this->hasValueCompliantWithCondition($filter, $index, $conditionRequirements);
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
* @param $conditionRequirements
*
* @return void
*/
protected function hasValueCompliantWithCondition($filter, int $index, $conditionRequirements): void
{
// number of values check
if ($conditionRequirements['multiple']) {
$this->mustHaveSeveralValues($filter, $index);
} else {
$this->mustHaveOneValue($filter, $index);
}
// type check
switch ($conditionRequirements['type']) {
case AttributeMapConditionOutput::STRING:
$this->mustBeString($filter, $index, $conditionRequirements);
break;
case AttributeMapConditionOutput::INT:
$this->mustBeNumber($filter, $index, $conditionRequirements);
if ($conditionRequirements['positive']) {
$this->mustBePositiveNumber($filter, $index, $conditionRequirements);
}
if ($conditionRequirements['integer']) {
$this->mustBeInteger($filter, $index, $conditionRequirements);
}
break;
case AttributeMapConditionOutput::BOOLEAN:
$this->mustBeBoolean($filter, $index);
break;
case AttributeMapConditionOutput::OBJECT:
$this->mustBeValidObject($filter, $index, $conditionRequirements);
break;
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
*
* @return void
*/
protected function mustHaveOneValue($filter, int $index): void
{
if (!isset($filter['value'])) {
throw new InvalidArgumentException('Filter #' . $index . ' requires a "value" field.');
}
if (is_array($filter['value']) && !$this->isAssociativeArray($filter['value'])) {
throw new InvalidArgumentException('Filter #' . $index . ' is malformed, "value" field need to be one value.');
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
*
* @return void
*/
protected function mustHaveSeveralValues($filter, int $index): void
{
if (!isset($filter['value'])) {
throw new InvalidArgumentException('Filter #' . $index . ' requires a "value" field.');
}
if (!is_array($filter['value']) || $this->isAssociativeArray($filter['value'])) {
throw new InvalidArgumentException('Filter #' . $index . ' is malformed, "value" field need to be an array of value.');
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
*
* @return void
*/
protected function mustBeBoolean($filter, int $index): void
{
if (gettype($filter['value']) !== 'boolean') {
throw new InvalidArgumentException("Value of filter #$index must be a boolean, " . gettype($filter['value']) . ' provided');
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
* @param $conditionRequirements
*
* @return void
*/
protected function mustBeString($filter, int $index, $conditionRequirements): void
{
$checkValueIsString = function ($value) use ($index): void {
if (!is_string($value)) {
throw new InvalidArgumentException('Value ' . $value . " of filter #$index must be a string.");
}
};
// Single Value
if ($conditionRequirements['multiple']) {
foreach ($filter['value'] as $value) {
$checkValueIsString($value);
}
} else {
$checkValueIsString($filter['value']);
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
* @param $conditionRequirements
*
* @return void
*/
protected function mustBeNumber($filter, int $index, $conditionRequirements): void
{
$checkValueIsNumber = function ($value) use ($index): void {
if (!is_numeric($value)) {
throw new InvalidArgumentException('Value ' . $value . " of filter #$index must be a number.");
}
};
if ($conditionRequirements['multiple']) {
foreach ($filter['value'] as $value) {
$checkValueIsNumber($value);
}
} else {
$checkValueIsNumber($filter['value']);
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
* @param $conditionRequirements
*
* @return void
*/
protected function mustBePositiveNumber($filter, int $index, $conditionRequirements): void
{
$checkValueIsPositive = function ($value) use ($index): void {
if ($value < 0) {
throw new InvalidArgumentException('Value ' . $value . " of filter #$index is not a positive number.");
}
};
if ($conditionRequirements['multiple']) {
foreach ($filter['value'] as $value) {
$checkValueIsPositive($value);
}
} else {
$checkValueIsPositive($filter['value']);
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
* @param $conditionRequirements
*
* @return void
*/
protected function mustBeInteger($filter, int $index, $conditionRequirements): void
{
$checkValueIsInteger = function ($value) use ($index): void {
if (!is_int($value)) {
throw new InvalidArgumentException('Value ' . $value . " of filter #$index is not an integer.");
}
};
if ($conditionRequirements['multiple']) {
foreach ($filter['value'] as $value) {
$checkValueIsInteger($value);
}
} else {
$checkValueIsInteger($filter['value']);
}
}
/**
* @throws InvalidArgumentException
*
* @param $filter
* @param int $index
* @param $conditionRequirements
*
* @return void
*/
protected function mustBeValidObject($filter, int $index, $conditionRequirements): void
{
$checkValueIsValidObject = function ($value) use ($index, $conditionRequirements): void {
if (!$this->isAssociativeArray($value)) {
throw new InvalidArgumentException('Value ' . json_encode($value) . " of filter #$index is not an object.");
}
foreach ($conditionRequirements['keys'] as $key) {
if (!array_key_exists($key, $value)) {
throw new InvalidArgumentException('Value ' . json_encode($value) . " of filter #$index does not have the required '" . $key . '\' key.');
}
}
};
if ($conditionRequirements['multiple']) {
foreach ($filter['value'] as $value) {
$checkValueIsValidObject($value);
}
} else {
$checkValueIsValidObject($filter['value']);
}
}
/**
* @param $array
*
* @return bool
*/
protected function isAssociativeArray($array): bool
{
if (!is_array($array)) {
return false;
}
foreach (array_keys($array) as $key) {
if (!is_string($key)) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication;
use Db;
use DbQuery;
class ProductEnumerator
{
/**
* @var FilterValidator
*/
protected $filterValidator;
/**
* @var QueryBuilder
*/
protected $queryBuilder;
public function __construct(
FilterValidator $filterValidator,
QueryBuilder $queryBuilder
) {
$this->filterValidator = $filterValidator;
$this->queryBuilder = $queryBuilder;
}
public function countProductsMatchingFilters(array $filters): int
{
$this->filterValidator->validate($filters);
$res = $this->execute(
$this->queryBuilder->buildQueryToCount($filters)
);
return $res[0]['total'] ?? 0;
}
public function listProductsMatchingFilters(array $filters, array $paginationParams): array
{
$this->filterValidator->validate($filters);
return $this->execute(
$this->queryBuilder->buildQueryToList($filters)
);
}
protected function execute(DbQuery $query): array
{
return Db::getInstance()->executeS($query);
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\AttributeType;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\BrandQueryBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\CategoryQueryBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\FeatureQueryBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\OutOfStockQueryBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\PriceQueryBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\ProductIdQueryBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\FilterApplication\AttributeQueryBuilder\QueryBuilderInterface;
class QueryBuilder
{
/**
* @var int
*/
private $shopId;
/**
* @var QueryBuilderInterface[]
*/
private $builders;
public function __construct(
int $shopId,
BrandQueryBuilder $brandQueryBuilder,
CategoryQueryBuilder $categoryQueryBuilder,
FeatureQueryBuilder $featureQueryBuilder,
OutOfStockQueryBuilder $outOfStockQueryBuilder,
PriceQueryBuilder $priceQueryBuilder,
ProductIdQueryBuilder $productIdQueryBuilder
) {
$this->shopId = $shopId;
$this->builders = [
AttributeType::BRAND => $brandQueryBuilder,
AttributeType::CATEGORY => $categoryQueryBuilder,
AttributeType::FEATURE => $featureQueryBuilder,
AttributeType::OUT_OF_STOCK => $outOfStockQueryBuilder,
AttributeType::PRICE => $priceQueryBuilder,
AttributeType::PRODUCT_ID => $productIdQueryBuilder,
];
}
public function buildQueryToCount(array $filters): DbQuery
{
$query = $this->buildCommonQuery($filters);
$query->select('COUNT(DISTINCT p.id_product) as total');
return $query;
}
public function buildQueryToList(array $filters): DbQuery
{
$query = $this->buildCommonQuery($filters);
// TODO: Selection of columns seems to depend on filters.
$query->select('DISTINCT p.id_product, p.*');
return $query;
}
protected function buildCommonQuery(array $filters): DbQuery
{
$initiatedRelations = $this->initRelations();
$query = new DbQuery();
$query->from('product', 'p');
$query->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
$query->where('ps.id_shop = ' . (int) $this->shopId);
$query->where('ps.active = 1');
foreach ($filters as $index => $filter) {
$query = $this->builders[$filter['attribute']]->addRelations($query, $index);
$query = $this->builders[$filter['attribute']]->addWhereFromFilter($query, $filter, $index);
}
return $query;
}
private function initRelations(): array
{
$initiatedRelations = [];
foreach (AttributeType::all() as $attribute) {
$initiatedRelations[$attribute] = false;
}
return $initiatedRelations;
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,47 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Options;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\ManufacturerRepository;
class BrandOptionsProvider implements OptionsProviderInterface
{
/**
* @var ManufacturerRepository
*/
protected $manufacturerRepository;
public function __construct(
ManufacturerRepository $manufacturerRepository
) {
$this->manufacturerRepository = $manufacturerRepository;
}
public function getOptions(): array
{
return array_map(function ($brand) {
return [
'id' => $brand['id'],
'value' => $brand['name'],
];
}, $this->manufacturerRepository->getManufacturersList());
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Options;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CategoryRepository;
class CategoryOptionsProvider implements OptionsProviderInterface
{
/**
* @var CategoryRepository
*/
protected $categoryRepository;
public function __construct(
CategoryRepository $categoryRepository
) {
$this->categoryRepository = $categoryRepository;
}
public function getOptions(): array
{
return array_map(function ($category) {
return [
'id' => $category['id'],
'value' => $category['name'],
];
}, $this->categoryRepository->getCategoriesList());
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Options;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\AttributesRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\LanguageRepository;
class FeatureOptionsProvider implements OptionsProviderInterface
{
/**
* @var AttributesRepository
*/
protected $attributeRepository;
/**
* @var LanguageRepository
*/
protected $languageRepository;
/**
* @var int
*/
private $currentLanguageId;
public function __construct(
AttributesRepository $attributeRepository,
LanguageRepository $languageRepository,
int $currentLanguageId
) {
$this->attributeRepository = $attributeRepository;
$this->languageRepository = $languageRepository;
$this->currentLanguageId = $currentLanguageId;
}
public function getOptions(): array
{
$rawData = $this->attributeRepository->getFeaturesWithLocalizedValues();
$options = [];
foreach ($rawData as $rawAttribute) {
if (!isset($options[$rawAttribute['id_feature']])) {
$options[$rawAttribute['id_feature']] = [
'id' => $rawAttribute['id_feature'],
'key' => $rawAttribute['feature_name'],
'values' => [],
];
}
if ($this->currentLanguageId === (int) $rawAttribute['id_lang']) {
$options[$rawAttribute['id_feature']]['key'] = $rawAttribute['feature_name'];
}
$options[$rawAttribute['id_feature']]['values'][] = [
'id' => $rawAttribute['id_feature_value'],
// Repeat key to ease the creation of payload when value is selected
'key' => $rawAttribute['feature_name'],
'value' => $rawAttribute['value'],
'language' => $this->languageRepository->getIsoById($rawAttribute['id_lang']),
];
}
return array_values($options);
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Options;
interface OptionsProviderInterface
{
public function getOptions(): array;
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\Options;
use InvalidArgumentException;
use PrestaShop\Module\PsxMarketingWithGoogle\ProductFilter\AttributeType;
class Resolver
{
public function getProvider(string $kind): string
{
$providersList = $this->getAttributeKindsAndProviders();
if (!array_key_exists($kind, $providersList)) {
throw new InvalidArgumentException("Provided attribute kind '$kind' is not a valid value");
}
return $providersList[$kind];
}
protected function getAttributeKindsAndProviders(): array
{
return [
AttributeType::BRAND => BrandOptionsProvider::class,
AttributeType::CATEGORY => CategoryOptionsProvider::class,
AttributeType::FEATURE => FeatureOptionsProvider::class,
];
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,89 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Provider;
use Carrier;
use Currency;
use Language;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Builder\CarrierBuilder;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\Carrier as DTOCarrier;
use RangePrice;
use RangeWeight;
class CarrierDataProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var CarrierBuilder
*/
private $carrierBuilder;
public function __construct(
ConfigurationAdapter $configurationAdapter,
CarrierBuilder $carrierBuilder
) {
$this->configurationAdapter = $configurationAdapter;
$this->carrierBuilder = $carrierBuilder;
}
public function getFormattedData(): array
{
$language = new Language($this->configurationAdapter->get('PS_LANG_DEFAULT'));
$currency = new Currency($this->configurationAdapter->get('PS_CURRENCY_DEFAULT'));
$carriers = Carrier::getCarriers($language->id, false, false, false, null, Carrier::ALL_CARRIERS);
/** @var DTOCarrier[] $carrierLines */
$carrierLines = $this->carrierBuilder->buildCarriers(
$carriers,
$language,
$currency,
$this->configurationAdapter->get('PS_WEIGHT_UNIT')
);
return $carrierLines;
}
/**
* @param array $deliveryPriceByRange
*
* @return false|RangeWeight|RangePrice
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException
*/
public function getCarrierRange(array $deliveryPriceByRange)
{
if (isset($deliveryPriceByRange['id_range_weight'])) {
return new RangeWeight($deliveryPriceByRange['id_range_weight']);
}
if (isset($deliveryPriceByRange['id_range_price'])) {
return new RangePrice($deliveryPriceByRange['id_range_price']);
}
return false;
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Provider;
use Context;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\ConversionEventData;
class CartEventDataProvider
{
/**
* @var Context
*/
protected $context;
public function __construct(Context $context)
{
$this->context = $context;
}
/**
* Return the items concerned by the transaction
* https://developers.google.com/analytics/devguides/collection/gtagjs/enhanced-ecommerce#action-data
*/
public function getEventData($sendTo, $data): ConversionEventData
{
$product = $data['product'];
$idProductAttribute = isset($data['id_product_attribute']) ? $data['id_product_attribute'] : 0;
return (new ConversionEventData())
->setSendTo($sendTo)
->setCurrency($this->context->currency->iso_code)
->setValue((string) \Product::getPriceStatic($product->id, true, $idProductAttribute, 2));
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Provider;
use Context;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\ConversionEventData;
class PageViewEventDataProvider
{
/**
* @var Context
*/
protected $context;
public function __construct(Context $context)
{
$this->context = $context;
}
/**
* Return the items concerned by the transaction
* https://developers.google.com/analytics/devguides/collection/gtagjs/enhanced-ecommerce#action-data
*
* @return ConversionEventData|null
*/
public function getEventData($sendTo)
{
if ($this->context->controller instanceof \ProductControllerCore) {
/** @var \ProductControllerCore $controller */
$controller = $this->context->controller;
$product = $controller->getTemplateVarProduct();
return (new ConversionEventData())
->setSendTo($sendTo)
->setCurrency($this->context->currency->iso_code)
->setValue((string) $product['price_amount']);
}
return null;
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Provider;
use Context;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\Remarketing\ProductData;
class ProductDataProvider
{
/**
* @var Context
*/
protected $context;
public function __construct(Context $context)
{
$this->context = $context;
}
public function getProductDataByProductArray(array $product): ProductData
{
$productData = new ProductData();
$productData->setId(implode(
'-',
[
(int) $product['id_product'],
(int) $product['id_product_attribute'],
]
));
$productData->setPrice((float) $product['product_price_wt']);
$productData->setQuantity((int) $product['product_quantity']);
return $productData;
}
public function getProductDataByProductObject(array $params): ProductData
{
$product = $params['product'];
$productData = new ProductData();
$productData->setId(implode(
'-',
[
(int) $product->id,
(int) $params['id_product_attribute'],
]
));
$productData->setPrice($product->price);
$productData->setQuantity($params['quantity']);
return $productData;
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Provider;
use Context;
use Order;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\Remarketing\PurchaseEventData;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\LanguageRepository;
class PurchaseEventDataProvider
{
/**
* @var ProductDataProvider
*/
protected $productDataProvider;
/**
* @var Context
*/
protected $context;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var LanguageRepository
*/
private $languageRepository;
/**
* @var CountryRepository
*/
private $countryRepository;
public function __construct(
ProductDataProvider $productDataProvider,
Context $context,
ConfigurationAdapter $configurationAdapter,
LanguageRepository $languageRepository,
CountryRepository $countryRepository
) {
$this->productDataProvider = $productDataProvider;
$this->context = $context;
$this->configurationAdapter = $configurationAdapter;
$this->languageRepository = $languageRepository;
$this->countryRepository = $countryRepository;
}
/**
* Return the items concerned by the transaction
*
* @see https://support.google.com/google-ads/answer/9028614
*/
public function getEventData($sendTo, Order $order): PurchaseEventData
{
$purchaseData = new PurchaseEventData();
// Common details
$purchaseData->setSendTo($sendTo);
$purchaseData->setCurrency($this->context->currency->iso_code);
$purchaseData->setValue((string) $order->total_products_wt);
$purchaseData->setTransactionId($order->id_cart);
// CwCD Parameters
$purchaseData->setDiscount((float) $order->total_discounts_tax_incl);
$purchaseData->setAwMerchandId((int) $this->configurationAdapter->get(Config::REMARKETING_CONVERSION_MERCHANT_GMC_ID));
$purchaseData->setAwFeedCountry(
$this->countryRepository->getIsoById(
$this->context->country->id
)
);
$purchaseData->setAwFeedLanguage(
$this->languageRepository->getIsoById(
$this->context->language->id
)
);
$items = [];
foreach ($order->getCartProducts() as $product) {
$items[] = $this->productDataProvider->getProductDataByProductArray($product);
}
$purchaseData->setItems($items);
return $purchaseData;
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Provider;
use DateInterval;
use DateTimeImmutable;
use DateTimeZone;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\VerificationTagRepository;
class VerificationTagDataProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var VerificationTagRepository
*/
private $verificationTagRepository;
public function __construct(
ConfigurationAdapter $configurationAdapter,
VerificationTagRepository $verificationTagRepository
) {
$this->configurationAdapter = $configurationAdapter;
$this->verificationTagRepository = $verificationTagRepository;
}
public function isUpdateRequested(): bool
{
// If GMC account is not onboarded, do nothing.
if (empty($this->configurationAdapter->get(Config::REMARKETING_CONVERSION_MERCHANT_GMC_ID))) {
return false;
}
$configuration = $this->verificationTagRepository->getConfiguration();
return !$configuration || (
(new DateTimeImmutable($configuration['date_upd'], new DateTimeZone('UTC'))) <
(new DateTimeImmutable('now', new DateTimeZone('UTC')))->sub(new DateInterval('P30D'))
);
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,94 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Db;
use DbQuery;
class AttributesRepository
{
/**
* @var Context
*/
private $context;
public function __construct(Context $context)
{
$this->context = $context;
}
/**
* Get all custom attributes that are used as product features and combination of attributes.
* Data used in Product feed configuration > Attribute mapping.
*
* @return array
*/
public function getAllAttributes(): array
{
$attributes = [];
foreach ($this->getCustomAttributes() as $attr) {
$attributes[] = [
// Not the best way in terms of permances, but avoid being responsible of a whole SQL query.
'name' => array_values(array_unique((array) (new \AttributeGroupCore($attr['id_attribute_group']))->name)),
'type' => 'custom',
];
}
foreach ($this->getFeatures() as $feature) {
$attributes[] = [
// Not the best way in terms of permances, but avoid being responsible of a whole SQL query.
'name' => array_values(array_unique((array) (new \FeatureCore($feature['id_feature']))->name)),
'type' => 'feature',
];
}
return $attributes;
}
/**
* Data used for Product filters
*/
public function getFeaturesWithLocalizedValues(): array
{
$query = new DbQuery();
$query->select('f.id_feature, fvl.id_lang, fl.name AS feature_name, fvl.id_feature_value, fvl.value')
->from('feature', 'f')
->innerJoin('feature_shop', 'fs', 'fs.id_feature = f.id_feature')
->innerJoin('feature_lang', 'fl', 'fl.id_feature = f.id_feature')
->innerJoin('feature_value', 'fv', 'fv.id_feature = f.id_feature')
->innerJoin('feature_value_lang', 'fvl', 'fvl.id_feature_value = fv.id_feature_value AND fvl.id_lang = fl.id_lang')
->where('fs.id_shop = ' . (int) $this->context->shop->id);
return Db::getInstance()->executeS($query);
}
protected function getCustomAttributes(): array
{
return \AttributeGroupCore::getAttributesGroups($this->context->language->id);
}
protected function getFeatures(): array
{
return \FeatureCore::getFeatures($this->context->language->id);
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Carrier;
use RangePrice;
use RangeWeight;
class CarrierRepository
{
public function getCarriers(int $langId): array
{
$carriers = Carrier::getCarriers($langId, false, false, false, null, Carrier::ALL_CARRIERS);
$data = [];
foreach ($carriers as $key => $carrier) {
$carrierObj = new Carrier($carrier['id_carrier']);
$data[$key]['collection'] = 'carriers';
$data[$key]['id'] = $carrierObj->id;
$data[$key]['properties'] = $carrier;
$deliveryPriceByRanges = self::getDeliveryPriceByRange($carrierObj);
foreach ($deliveryPriceByRanges as $deliveryPriceByRange) {
$data[$key]['collection'] = 'carriers_details';
$data[$key]['id'] = $deliveryPriceByRange['id_range_weight'];
$data[$key]['properties'] = $deliveryPriceByRange;
}
}
return $data;
}
public function getDeliveryPriceByRange(Carrier $carrierObj): array
{
$rangeTable = $carrierObj->getRangeTable();
switch ($rangeTable) {
case 'range_weight':
return self::getCarrierByWeightRange($carrierObj);
case 'range_price':
return self::getCarrierByPriceRange($carrierObj);
default:
return [];
}
}
private function getCarrierByPriceRange(Carrier $carrierObj): array
{
$deliveryPriceByRange = Carrier::getDeliveryPriceByRanges('range_price', (int) $carrierObj->id);
$filteredRanges = [];
foreach ($deliveryPriceByRange as $range) {
$filteredRanges[$range['id_range_price']]['id_range_price'] = $range['id_range_price'];
$filteredRanges[$range['id_range_price']]['id_carrier'] = $range['id_carrier'];
$filteredRanges[$range['id_range_price']]['zones'][$range['id_zone']]['id_zone'] = $range['id_zone'];
$filteredRanges[$range['id_range_price']]['zones'][$range['id_zone']]['price'] = $range['price'];
}
return $filteredRanges;
}
private function getCarrierByWeightRange(Carrier $carrierObj): array
{
$deliveryPriceByRange = Carrier::getDeliveryPriceByRanges('range_weight', (int) $carrierObj->id);
$filteredRanges = [];
foreach ($deliveryPriceByRange as $range) {
$filteredRanges[$range['id_range_weight']]['id_range_weight'] = $range['id_range_weight'];
$filteredRanges[$range['id_range_weight']]['id_carrier'] = $range['id_carrier'];
$filteredRanges[$range['id_range_weight']]['zones'][$range['id_zone']]['id_zone'] = $range['id_zone'];
$filteredRanges[$range['id_range_weight']]['zones'][$range['id_zone']]['price'] = $range['price'];
}
return $filteredRanges;
}
/**
* @param array $deliveryPriceByRange
*
* @return false|RangeWeight|RangePrice
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException
*/
public function getCarrierRange(array $deliveryPriceByRange)
{
if (isset($deliveryPriceByRange['id_range_weight'])) {
return new RangeWeight($deliveryPriceByRange['id_range_weight']);
}
if (isset($deliveryPriceByRange['id_range_price'])) {
return new RangePrice($deliveryPriceByRange['id_range_price']);
}
return false;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Db;
use DbQuery;
class CategoryRepository
{
/**
* @var Context
*/
private $context;
public function __construct(Context $context)
{
$this->context = $context;
}
public function getCategoriesList(): array
{
$query = new DbQuery();
$query->select('DISTINCT c.id_category AS id, cl.name AS name')
->from('category', 'c')
->innerJoin('category_shop', 'cs', 'cs.id_category = c.id_category')
->innerJoin('category_lang', 'cl', 'cl.id_category = c.id_category')
->where('cs.id_shop = ' . (int) $this->context->shop->id)
->where('cl.id_lang = ' . (int) $this->context->language->id)
// allows you to remove the root category and the categories cannot be administered or assigned to a product.
->where('c.id_parent <> 0')
->where('c.active = 1');
return Db::getInstance()->executeS($query);
}
}

View File

@@ -0,0 +1,183 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Country;
use Db;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
class CountryRepository
{
/**
* @var Db
*/
private $db;
/**
* @var Context
*/
private $context;
private $countryIsoCodeCache = [];
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
private $country;
public function __construct(Db $db, Context $context, Country $country, ConfigurationAdapter $configAdapter)
{
$this->db = $db;
$this->context = $context;
$this->country = $country;
$this->configurationAdapter = $configAdapter;
}
private function getBaseQuery(): DbQuery
{
$query = new DbQuery();
$query->from('country', 'c')
->innerJoin('country_shop', 'cs', 'cs.id_country = c.id_country')
->innerJoin('country_lang', 'cl', 'cl.id_country = c.id_country')
->where('cs.id_shop = ' . (int) $this->context->shop->id)
->where('cl.id_lang = ' . (int) $this->context->language->id);
return $query;
}
public function getCountryIsoCodesByZoneId(int $zoneId, bool $active = true): array
{
$cacheKey = $zoneId . '-' . (int) $active;
if (!isset($this->countryIsoCodeCache[$cacheKey])) {
$query = $this->getBaseQuery();
$query->select('iso_code');
$query->where('id_zone = ' . (int) $zoneId);
$query->where('active = ' . (bool) $active);
$isoCodes = [];
foreach ($this->db->executeS($query) as $country) {
$isoCodes[] = $country['iso_code'];
}
$this->countryIsoCodeCache[$cacheKey] = $isoCodes;
}
return $this->countryIsoCodeCache[$cacheKey];
}
public function getActiveCountries(): array
{
$query = $this->getBaseQuery();
$query->select('iso_code');
$query->where('active = ' . true);
$isoCodes = [];
foreach ($this->db->executeS($query) as $country) {
$isoCodes[] = $country['iso_code'];
}
return $isoCodes;
}
public function getShopDefaultCountry(): array
{
return [
'name' => Country::getNameById($this->context->language->id, $this->configurationAdapter->get('PS_COUNTRY_DEFAULT')),
'iso_code' => Country::getIsoById($this->configurationAdapter->get('PS_COUNTRY_DEFAULT')),
];
}
public function getIsoById(int $countryId)
{
return Country::getIsoById($countryId);
}
public function getShopContactCountry(): array
{
if (empty($this->configurationAdapter->get('PS_SHOP_COUNTRY_ID'))) {
return [
'name' => null,
'iso_code' => null,
];
}
return [
'name' => Country::getNameById($this->context->language->id, $this->configurationAdapter->get('PS_SHOP_COUNTRY_ID')),
'iso_code' => Country::getIsoById($this->configurationAdapter->get('PS_SHOP_COUNTRY_ID')),
];
}
public function countryNeedState(int $countryId): bool
{
return Country::containsStates($this->configurationAdapter->get($countryId));
}
/**
* isCompatibleForCSS
*
* @return bool
*/
public function isCompatibleForCSS()
{
$availableCountries = [
'BG',
'BE',
'CZ',
'DK',
'CY',
'LV',
'LT',
'LU',
'ES',
'FR',
'HR',
'IT',
'PL',
'PT',
'RO',
'SI',
'HU',
'MT',
'NL',
'AT',
'IS',
'LI',
'NO',
'SK',
'FI',
'SE',
'DE',
'IE',
'EL',
'CH',
'GB',
];
return in_array($this->country->iso_code, $availableCountries);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Currency;
class CurrencyRepository
{
/**
* @var Currency
*/
private $currency;
/**
* @var Context
*/
private $context;
public function __construct(Currency $currency, Context $context)
{
$this->currency = $currency;
$this->context = $context;
}
/**
* Get details about the currency associated to the shop context.
* Don't return all the details about the currency, as they should be
* available from another source (i.e CLDR json).
*
* @return array
*/
public function getShopCurrency(): array
{
return [
'isoCode' => $this->currency->iso_code,
];
}
public function getActiveCurrencies(): array
{
$isoCodes = [];
foreach (Currency::getCurrenciesByIdShop((int) $this->context->shop->id) as $currency) {
if (!$currency['active'] || $currency['deleted']) {
continue;
}
$isoCodes[] = $currency['iso_code'];
}
return $isoCodes;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Language;
class LanguageRepository
{
/**
* @var int
*/
private $shopId;
public function __construct(int $shopId)
{
$this->shopId = $shopId;
}
public function getIsoById(int $id)
{
return Language::getIsoById($id);
}
public function getLanguages(): array
{
$languages = Language::getLanguages(false, $this->shopId);
return array_map(function ($language) {
return $language['iso_code'];
}, $languages);
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Db;
use DbQuery;
class ManufacturerRepository
{
/**
* @var Context
*/
private $context;
public function __construct(Context $context)
{
$this->context = $context;
}
public function getManufacturersList(): array
{
$query = new DbQuery();
$query->select('DISTINCT m.id_manufacturer AS id, m.name AS name')
->from('manufacturer', 'm')
->innerJoin('manufacturer_shop', 'ms', 'ms.id_manufacturer = m.id_manufacturer')
->where('ms.id_shop = ' . (int) $this->context->shop->id)
->where('m.active = 1');
return Db::getInstance()->executeS($query);
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Module;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
class ModuleRepository
{
/**
* @var string
*/
private $moduleName;
public function __construct(string $moduleName)
{
$this->moduleName = $moduleName;
}
/**
* @return string|null
*/
public function getModuleVersion()
{
/** @var Module|null $module */
$module = Module::getInstanceByName($this->moduleName);
if (!empty($module)) {
return $module->version;
}
return null;
}
/**
* @return string
*/
public function getUpgradeLink()
{
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'upgrade',
'module_name' => $this->moduleName,
]);
}
/**
* @return string
*/
public function getEnableLink()
{
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'enable',
'module_name' => $this->moduleName,
]);
}
/**
* @return array
*/
public function getInformationsAboutModule(): array
{
return [
'version' => $this->getModuleVersion(),
'upgradeLink' => $this->getUpgradeLink(),
'hooks' => $this->getActiveHooks(),
];
}
/**
* @return bool
*/
public function moduleIsEnabled(): bool
{
return Module::isEnabled($this->moduleName);
}
/**
* @return array
*/
public function getActiveHooks(): array
{
$context = Context::getContext();
$hooks = [];
/** @var Module|null $moduleInstance */
$moduleInstance = Module::getInstanceByName($this->moduleName);
if (empty($moduleInstance)) {
return $hooks;
}
foreach (Config::HOOK_LIST as $hook) {
$hooks[$hook] = \Hook::isModuleRegisteredOnHook($moduleInstance, $hook, $context->shop->id);
}
return $hooks;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Db;
use DbQuery;
class ProductRepository
{
public function getProductsTotal($shopId, array $options = [])
{
$sql = new DbQuery();
$sql->select('COUNT(1) as total');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
if (isset($options['splitPerLangAndCombination'])) {
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = ps.id_product AND pl.id_shop = ps.id_shop');
$sql->leftJoin('product_attribute_shop', 'pas', 'pas.id_product = ps.id_product AND pas.id_shop = ps.id_shop');
}
$sql->where('ps.id_shop = ' . (int) $shopId);
if (isset($options['onlyActive'])) {
$sql->where('ps.active = 1');
}
$res = Db::getInstance()->executeS($sql);
return $res[0]['total'];
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Db;
use DbQuery;
class StateRepository
{
/**
* @var Db
*/
private $db;
private $stateIsoCodeCache = [];
public function __construct(Db $db)
{
$this->db = $db;
}
private function getBaseQuery(): DbQuery
{
$query = new DbQuery();
$query->from('state', 's');
return $query;
}
public function getStateIsoCodesByZoneId(int $zoneId, bool $active = true): array
{
$cacheKey = $zoneId . '-' . (int) $active;
if (!isset($this->stateIsoCodeCache[$cacheKey])) {
$query = $this->getBaseQuery();
$query->select('s.iso_code');
$query->innerJoin('country', 'c', 'c.id_country = s.id_country');
$query->where('s.id_zone = ' . (int) $zoneId);
$query->where('s.active = ' . (bool) $active);
$query->where('c.active = ' . (bool) $active);
$isoCodes = [];
foreach ($this->db->executeS($query) as $state) {
$isoCodes[] = $state['iso_code'];
}
$this->stateIsoCodeCache[$cacheKey] = $isoCodes;
}
return $this->stateIsoCodeCache[$cacheKey];
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Db;
use DbQuery;
class TabRepository
{
public function hasChildren(int $tabId): bool
{
$sql = new DbQuery();
$sql->select('id_tab');
$sql->from('tab');
$sql->where('`id_parent` = "' . (int) $tabId . '"');
return (bool) Db::getInstance()->getValue($sql);
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Db;
use DbQuery;
class TaxRepository
{
/**
* @var Db
*/
private $db;
/**
* @var Context
*/
private $context;
private $countryIsoCodeCache = [];
public function __construct(Db $db, Context $context)
{
$this->db = $db;
$this->context = $context;
}
private function getBaseQuery(): DbQuery
{
$query = new DbQuery();
$query->from('tax', 't')
->innerJoin('tax_rule', 'tr', 'tr.id_tax = t.id_tax')
->innerJoin('tax_rules_group', 'trg', 'trg.id_tax_rules_group = tr.id_tax_rules_group')
->innerJoin('tax_rules_group_shop', 'trgs', 'trgs.id_tax_rules_group = tr.id_tax_rules_group')
->innerJoin('tax_lang', 'tl', 'tl.id_tax = t.id_tax')
->where('trgs.id_shop = ' . (int) $this->context->shop->id)
->where('tl.id_lang = ' . (int) $this->context->language->id);
return $query;
}
public function getCarrierTaxesByTaxRulesGroupId(int $taxRulesGroupId, bool $active = true): array
{
$cacheKey = (int) $taxRulesGroupId . '-' . (int) $active;
if (!isset($this->countryIsoCodeCache[$cacheKey])) {
$query = $this->getBaseQuery();
$query->select('rate, c.iso_code as country_iso_code, GROUP_CONCAT(s.iso_code SEPARATOR ",") as state_iso_code');
$query->leftJoin('country', 'c', 'c.id_country = tr.id_country');
$query->leftJoin('state', 's', 's.id_state = tr.id_state');
$query->where('tr.id_tax_rules_group = ' . (int) $taxRulesGroupId);
$query->where('c.active = ' . (bool) $active);
$query->where('s.active = ' . (bool) $active . ' OR s.active IS NULL');
$query->where('t.active = ' . (bool) $active);
$query->where('c.iso_code IS NOT NULL');
$this->countryIsoCodeCache[$cacheKey] = $this->db->executeS($query);
}
return $this->countryIsoCodeCache[$cacheKey];
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Repository;
use Context;
use Db;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
class VerificationTagRepository
{
/**
* @var Db
*/
private $db;
/**
* @var Context
*/
private $context;
public function __construct(Db $db, Context $context)
{
$this->db = $db;
$this->context = $context;
}
/**
* @return array|false
*/
public function getConfiguration()
{
$query = new DbQuery();
$query->select('c.value, c.date_upd')
->from('configuration', 'c')
->where('(c.id_shop = ' . (int) $this->context->shop->id . ' or ISNULL(c.id_shop))')
->where('c.name = "' . Config::PSX_MKTG_WITH_GOOGLE_WEBSITE_VERIFICATION_META . '"');
return $this->db->getRow($query);
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,192 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Tracker;
use Context;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
class Segment implements TrackerInterface
{
/**
* @var string
*/
private $message = '';
/**
* @var array
*/
private $options = [];
/**
* @var Context
*/
private $context;
/**
* Segment constructor.
*/
public function __construct(Context $context)
{
$this->context = $context;
$this->init();
}
/**
* Init segment client with the api key
*/
private function init()
{
\Segment::init(Config::PSX_MKTG_WITH_GOOGLE_SEGMENT_API_KEY);
}
/**
* Track event on segment
*
* @return bool
*
* @throws \PrestaShopException
*/
public function track()
{
if (empty($this->message)) {
throw new \PrestaShopException('Message cannot be empty. Need to set it with setMessage() method.');
}
// Dispatch track depending on context shop
$this->dispatchTrack();
return true;
}
private function segmentTrack($userId)
{
$userAgent = array_key_exists('HTTP_USER_AGENT', $_SERVER) === true ? $_SERVER['HTTP_USER_AGENT'] : '';
$ip = array_key_exists('REMOTE_ADDR', $_SERVER) === true ? $_SERVER['REMOTE_ADDR'] : '';
$referer = array_key_exists('HTTP_REFERER', $_SERVER) === true ? $_SERVER['HTTP_REFERER'] : '';
$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
\Segment::track([
'userId' => $userId,
'event' => $this->message,
'channel' => 'browser',
'context' => [
'ip' => $ip,
'userAgent' => $userAgent,
'locale' => $this->context->language->iso_code,
'page' => [
'referrer' => $referer,
'url' => $url,
],
],
'properties' => array_merge([
'module' => 'psxmarketingwithgoogle',
], $this->options),
]);
\Segment::flush();
}
/**
* Handle tracking differently depending on the shop context
*
* @return mixed
*/
private function dispatchTrack()
{
$dictionary = [
\Shop::CONTEXT_SHOP => function () {
return $this->trackShop();
},
\Shop::CONTEXT_GROUP => function () {
return $this->trackShopGroup();
},
\Shop::CONTEXT_ALL => function () {
return $this->trackAllShops();
},
];
return call_user_func($dictionary[$this->context->shop->getContext()]);
}
/**
* Send track segment only for the current shop
*/
private function trackShop()
{
$userId = $this->context->shop->domain;
$this->segmentTrack($userId);
}
/**
* Send track segment for each shop in the current shop group
*/
private function trackShopGroup()
{
$shops = $this->context->shop->getShops(true, $this->context->shop->getContextShopGroupID());
foreach ($shops as $shop) {
$this->segmentTrack($shop['domain']);
}
}
/**
* Send track segment for all shops
*/
private function trackAllShops()
{
$shops = $this->context->shop->getShops();
foreach ($shops as $shop) {
$this->segmentTrack($shop['domain']);
}
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @param string $message
*/
public function setMessage($message)
{
$this->message = $message;
}
/**
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* @param array $options
*/
public function setOptions($options)
{
$this->options = $options;
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Tracker;
interface TrackerInterface
{
/**
* @return void
*/
public function track();
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,74 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Config;
class Config
{
public const PSX_MKTG_WITH_GOOGLE_API_URL = 'https://googleshopping-api.psessentials.net';
public const PSX_MKTG_WITH_GOOGLE_CDN_URL = 'https://storage.googleapis.com/psxmarketing-cdn/v1.x.x/js/';
public const PSX_MKTG_WITH_GOOGLE_BILLING_CDC_URL = 'https://unpkg.com/@prestashopcorp/billing-cdc/dist/bundle.js';
public const PSX_MKTG_WITH_GOOGLE_BILLING_PREPROD_CDC_URL = 'https://unpkg.com/@prestashopcorp/billing-cdc@preprod/dist/bundle.js';
public const PSX_MKTG_WITH_GOOGLE_CLOUDSYNC_CDC_URL = 'https://assets.prestashop3.com/ext/cloudsync-merchant-sync-consent/latest/cloudsync-cdc.js';
public const PSX_MKTG_WITH_GOOGLE_CLOUDSYNC_PREPROD_CDC_URL = 'https://integration-assets.prestashop3.com/ext/cloudsync-merchant-sync-consent/latest/cloudsync-cdc.js';
public const HOOK_LIST = [
'displayBackOfficeHeader',
'displayHeader',
'displayOrderConfirmation',
'displayTop',
'actionCartUpdateQuantityBefore',
];
public const CONFIGURATION_LIST = [];
public const MODULE_ADMIN_CONTROLLERS = [
'AdminAjaxPsgoogleshipping',
'AdminPsgoogleshippingModule',
];
public const PSX_MKTG_WITH_GOOGLE_SENTRY_CREDENTIALS_PHP = 'https://446479f8bca645fa8838c1a5f99dceba@o298402.ingest.sentry.io/5949536';
public const PSX_MKTG_WITH_GOOGLE_SENTRY_CREDENTIALS_VUE = 'https://6504c60594bd490eab93afa78f274e35@o298402.ingest.sentry.io/5984715';
public const USE_LOCAL_VUE_APP = false;
public const USE_LIVE_VUE_APP = false;
public const USE_BILLING_SANDBOX = 0;
public const USE_BILLING_PREPROD = 0;
public const USE_CLOUDSYNC_PREPROD = 0;
public const PSX_MKTG_WITH_GOOGLE_SEGMENT_API_KEY = 'RqYiLJKyoWv13t9aKxBvza6vsCsRpPpC';
public const PSX_MKTG_WITH_GOOGLE_WEBSITE_VERIFICATION_META = 'PSX_MKTG_WITH_GOOGLE_WEBSITE_VERIFICATION_META';
public const PSX_MKTG_WITH_GOOGLE_WEBSITE_REQUIREMENTS_STATUS = 'PSX_MKTG_WITH_GOOGLE_WEBSITE_REQUIREMENTS_STATUS';
public const PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS = 'PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS';
public const PSX_MKTG_WITH_GOOGLE_REMARKETING_ENHANCED_STATUS = 'PSX_MKTG_WITH_GOOGLE_REMARKETING_ENHANCED_STATUS';
public const PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG = 'PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG';
public const PSX_MKTG_WITH_GOOGLE_REMARKETING_CONVERSION_LABELS = 'PSX_MKTG_WITH_GOOGLE_REMARKETING_CONVERSION_LABELS';
public const REMARKETING_CONVERSION_LABEL_PURCHASE = 'PURCHASE';
public const REMARKETING_CONVERSION_LABEL_ADD_TO_CART = 'ADD_TO_CART';
public const REMARKETING_CONVERSION_LABEL_PAGE_VIEW = 'PAGE_VIEW';
public const REMARKETING_CONVERSION_LABELS = [
self::REMARKETING_CONVERSION_LABEL_PURCHASE,
self::REMARKETING_CONVERSION_LABEL_ADD_TO_CART,
self::REMARKETING_CONVERSION_LABEL_PAGE_VIEW,
];
public const REMARKETING_CONVERSION_MERCHANT_GMC_ID = 'REMARKETING_CONVERSION_MERCHANT_GMC_ID';
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PsxMarketingWithGoogle\Config;
/**
* This class allows to retrieve config data that can be overwritten by a .env file.
* Otherwise it returns by default from the Config class.
*/
class Env
{
/**
* @param string $key
*
* @return string
*/
public function get($key)
{
if (!empty($_ENV[$key])) {
return $_ENV[$key];
}
return constant(Config::class . '::' . $key);
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>psxmarketingwithgoogle</name>
<displayName><![CDATA[Marketing with Google]]></displayName>
<version><![CDATA[1.75.6]]></version>
<description><![CDATA[PrestaShop Marketing makes it easy to connect your store with Google and promote your products to millions of shoppers across multiple Google channels. Create Performance Max campaigns without leaving your PrestaShop dashboard and drive more traffic.]]></description>
<author><![CDATA[PrestaShop]]></author>
<tab><![CDATA[advertising_marketing]]></tab>
<confirmUninstall><![CDATA[Are you sure you want to uninstall this module?]]></confirmUninstall>
<is_configurable>1</is_configurable>
<need_instance>0</need_instance>
<limited_countries></limited_countries>
</module>

View File

@@ -0,0 +1,10 @@
# Apache 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
# Apache 2.4
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

View File

@@ -0,0 +1,12 @@
services:
PrestaShop\PsAccountsInstaller\Installer\Installer:
class: 'PrestaShop\PsAccountsInstaller\Installer\Installer'
public: true
arguments:
- '5.0.2'
PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts:
class: 'PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts'
public: true
arguments:
- '@PrestaShop\PsAccountsInstaller\Installer\Installer'

View File

@@ -0,0 +1,21 @@
services:
PrestaShopCorp\Billing\Wrappers\BillingContextWrapper:
class: 'PrestaShopCorp\Billing\Wrappers\BillingContextWrapper'
arguments:
- '@PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts'
- '@psxmarketingwithgoogle.context'
- '@psxmarketingwithgoogle.billing_env'
PrestaShopCorp\Billing\Presenter\BillingPresenter:
class: 'PrestaShopCorp\Billing\Presenter\BillingPresenter'
public: true
arguments:
- '@PrestaShopCorp\Billing\Wrappers\BillingContextWrapper'
- '@psxmarketingwithgoogle'
PrestaShopCorp\Billing\Services\BillingService:
class: 'PrestaShopCorp\Billing\Services\BillingService'
public: true
arguments:
- '@PrestaShopCorp\Billing\Wrappers\BillingContextWrapper'
- '@psxmarketingwithgoogle'

View File

@@ -0,0 +1,11 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Builder\CarrierBuilder:
class: PrestaShop\Module\PsxMarketingWithGoogle\Builder\CarrierBuilder
public: true
arguments:
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\CarrierRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\StateRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\TaxRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter'

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,16 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Database\Installer:
class: PrestaShop\Module\PsxMarketingWithGoogle\Database\Installer
public: true
arguments:
- '@psxmarketingwithgoogle'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler'
PrestaShop\Module\PsxMarketingWithGoogle\Database\Uninstaller:
class: PrestaShop\Module\PsxMarketingWithGoogle\Database\Uninstaller
public: true
arguments:
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\TabRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler'

Some files were not shown because too many files have changed in this diff Show More