first commit

This commit is contained in:
2024-11-05 12:22:50 +01:00
commit e5682a3912
19641 changed files with 2948548 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
![Marketing With Google logo](views/img/google-icon.svg)
# Marketing With Google (psxmarketingwithgoogle)
[![JS tests](https://github.com/PrestaShopCorp/psxmarketingwithgoogle/actions/workflows/js.yml/badge.svg)](https://github.com/PrestaShopCorp/psxmarketingwithgoogle/actions/workflows/js.yml)
[![Storybook CI/CD](https://github.com/PrestaShopCorp/psxmarketingwithgoogle/actions/workflows/storybook-ci-cd.yml/badge.svg)](https://github.com/PrestaShopCorp/psxmarketingwithgoogle/actions/workflows/storybook-ci-cd.yml)
[![PHP tests](https://github.com/PrestaShopCorp/psxmarketingwithgoogle/actions/workflows/php.yml/badge.svg)](https://github.com/PrestaShopCorp/psxmarketingwithgoogle/actions/workflows/php.yml)
## About
**Sync your product catalog with Google**
Connect your store to Google Merchant Center and synchroniwe your entire product catalog in a few clicks. Product attributes such as price and availability will be automatically updated everyday.
**Enable free listings for your products**
Free listings allow to show your product attributes, including image and price in organically-ranked listings on the Shopping tab.
Once your catalog has been synchronised, enable free listings on your dashboard and start showing your products on the Shopping tab for free.
**Create and manage Smart Shopping campaigns**
Smart Shopping campaigns are ads that use Googles smart technology for bidding and ad placement to maximize conversion value and strategically display your ads to people searching for products like yours.
Set a daily budget and let Google's smart technology optimize your campaigns across different networks like Google Search, YouTube or Gmail. You only pay when people click.
## Download & Installation
Modules archives can be found and downloaded:
* On the [PrestaShop Addons Marketplace](https://addons.prestashop.com/en/essentials/85751-prestashop-marketing-with-google-.html) (Latest stable release only)
* On the [releases page](https://github.com/PrestaShopCorp/pasmarketingwithgoogle/releases) of this repository (Stable & beta releases available)
Downloaded archives can be uploaded on PrestaShop instances, as detailed in the [user documentation](https://doc.prestashop.com/display/PS17/Modules+Selection#ModulesSelection-Uploadingamodulemanually).
## Building
This part covers the steps to get this project ready locally.
In order to run on a PrestaShop instance, dependencies needs to be downloaded and the JS application built.
### PHP
Retrieve dependencies with composer
```
composer install
# or
make docker-build-composer
```
Composer has been configured in authoritative mode, which means it won't look in the filesystem when a class is not found in the current autoloader.
When a class is added or deleted, it is required to rerun the above command.
### VueJS
The following commands need to be run in the `_dev/` folder.
To build the application in production mode:
```
npm install --n
npm run build
# or
make vuejs
```
To compiles and watch for new changes (development mode):
```
npm install --n
npm run dev
```
## Testing
Tests will be run at each commit on this repository or any pull-request. These command reproduce the checks done by the CI.
* JS checks: Unit tests & coding standards
```
npm run lint
npm run test:unit
# or
make test-front
```
* PHP checks: Unit tests, coding standards...
```
vendor/bin/php-cs-fixer fix
vendor/bin/phpunit tests/
docker run -tid --rm -v ps-volume:/var/www/html --name temp-ps prestashop/prestashop; docker run --rm --volumes-from temp-ps -v $PWD:/web/module -e _PS_ROOT_DIR_=/var/www/html --workdir=/web/module phpstan/phpstan analyse --configuration=/web/module/tests/phpstan/phpstan.neon;
php vendor/bin/header-stamp --license=vendor/prestashop/header-stamp/assets/afl.txt --exclude=vendor,tests,_dev
# or
make test-back
```
## Environment customization
By default, PHP & JS will define data to the application that are related to the production.
In case you need to modify these variables while maintaining this project, you may
overwrite them in a freshly `.env` file created in the root directory of this module, by using the
keys that can be found in `classes/config/Config.php`.
If you want to use local vue app, set on your .env USE_LOCAL_VUE_APP at 1.
For instance to modify the base URL of the services for a local one:
```
PSX_MKTG_WITH_GOOGLE_API_URL=https://localhost:8080
PSX_MKTG_WITH_GOOGLE_API_KEY=API_KEY
USE_LOCAL_VUE_APP=1
```
Some values are managed by the Vue.js application and are provided in the [`_dev/.env` file](_dev/.env).
## Releasing
To publish a new version on the marketplace:
* Update the version in the main class of this module, and in `config.xml` ifit exists,
* Create a new release on the [releases page](https://github.com/PrestaShopCorp/pasmarketingwithgoogle/releases) with a tag that matches the version provided in the main class.
## Documentation
### User help
Documentation is hosted [online](
https://storage.googleapis.com/psessentials-documentation/psxmarketingwithgoogle/user_guide_en.pdf), and is available in several languages. Translated documentation in your language can be found in the module configuration page, in the "Help" tab.
### Storybook
All components and pages of this module are available on a [dedicated website running Storybook](https://storybook-google.psessentials-integration.net/). It is updated on each push to the `master` branch.
## Contributing
PrestaShop modules are open source extensions to the PrestaShop e-commerce platform. Everyone is welcome and even encouraged to contribute with their own improvements!
Just make sure to follow our contribution guidelines.
## Reporting issues
You can report issues with this module by using the link available in the module configuration page, in the "Help" tab.
## License
This module is released under the Academic Free License 3.0

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\Adapter;
use Configuration;
use Shop;
class ConfigurationAdapter
{
/**
* @var Shop
*/
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,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,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\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;
}
public function setTransactionId(string $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,165 @@
<?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 array
*/
private $errors = [];
private $module;
/**
* @var TabRepository
*/
private $tabRepository;
/**
* @var Segment
*/
private $segment;
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(
\PsxMarketingWithGoogle $module,
TabRepository $tabRepository,
Segment $segment,
ErrorHandler $errorHandler
) {
$this->module = $module;
$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
);
$this->errors[] = $this->module->l('Failed to uninstall database tables', self::CLASS_NAME);
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
);
$this->errors[] = $this->module->l('Failed to uninstall database tables', self::CLASS_NAME);
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,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\Factory;
use GuzzleHttp\Client;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Env;
class ApiClientFactory implements ApiClientFactoryInterface
{
/**
* @var string
*/
private $apiUrl;
public function __construct(Env $env)
{
$this->apiUrl = $env->get('PSX_MKTG_WITH_GOOGLE_API_URL');
}
public function createClient()
{
return new Client(['base_url' => $this->apiUrl]);
}
}

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 GuzzleHttp\Client;
interface ApiClientFactoryInterface
{
/**
* @return Client
*/
public function createClient();
}

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\Factory;
use Configuration;
use Context;
use Currency;
class ContextFactory
{
public static function getContext()
{
return Context::getContext();
}
public static function getLanguage()
{
return Context::getContext()->language;
}
/**
* 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 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,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,198 @@
<?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\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 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->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') {
return base64_decode($this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG));
}
// 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,97 @@
<?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 PrestaShop\Module\PsxMarketingWithGoogle\Repository\CarrierRepository;
use RangePrice;
use RangeWeight;
class CarrierDataProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var CarrierBuilder
*/
private $carrierBuilder;
/**
* @var CarrierRepository
*/
private $carrierRepository;
public function __construct(
ConfigurationAdapter $configurationAdapter,
CarrierBuilder $carrierBuilder,
CarrierRepository $carrierRepository
) {
$this->configurationAdapter = $configurationAdapter;
$this->carrierBuilder = $carrierBuilder;
$this->carrierRepository = $carrierRepository;
}
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,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\Provider;
use Context;
use Currency;
use Order;
use PrestaShop\Module\PsxMarketingWithGoogle\DTO\ConversionEventData;
class ConversionEventDataProvider
{
/**
* @var Context
*/
protected $context;
public function __construct(Context $context)
{
$this->context = $context;
}
public function getActionDataByOrderObject(Order $order): ConversionEventData
{
return (new ConversionEventData())
->setTransactionId((string) $order->id)
->setValue((string) $order->total_products_wt)
->setCurrency((new Currency($order->id_currency))->iso_code);
}
}

View File

@@ -0,0 +1,77 @@
<?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;
class GoogleTagProvider
{
/**
* html contents (front office)
*
* @var string|bool
*/
private $contents;
/**
* Check if the given tag already exist on the shop
*
* @param string $googleTag eg: AW-253749562
*
* @return bool
*/
public function checkGoogleTagAlreadyExists(string $googleTag, int $shopId): bool
{
$this->crawlFront($shopId);
if (empty($this->contents)) {
return false;
}
return str_contains($this->contents, $googleTag);
}
/**
* Crawl front office
*
* @param int $shopId
*
* @return void
*/
private function crawlFront(int $shopId): void
{
$shop = \Shop::getShop($shopId);
$url = \Tools::getShopProtocol() . $shop[$this->getDomainType()] . $shop['uri'];
$contents = \Tools::file_get_contents($url);
$this->contents = $contents;
}
/**
* Retrieve the domain type to use depending on ssl
*
* @return string domain type can be domain_ssl || domain
*/
private function getDomainType(): string
{
return \Tools::usingSecureMode() ? 'domain_ssl' : 'domain';
}
}

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->reference);
// 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,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,66 @@
<?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;
class AttributesRepository
{
/**
* @var Context
*/
private $context;
public function __construct(Context $context)
{
$this->context = $context;
}
/**
* Get all custom and product attributes.
*
* @return array
*/
public function getAllAttributes(): array
{
$attributes = [];
$customAttributes = \AttributeGroupCore::getAttributesGroups($this->context->language->id);
$features = \FeatureCore::getFeatures($this->context->language->id);
foreach ($customAttributes 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 ($features 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;
}
}

View File

@@ -0,0 +1,132 @@
<?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 Context;
use Db;
use RangePrice;
use RangeWeight;
class CarrierRepository
{
/**
* @var Db
*/
private $db;
/**
* @var Context
*/
private $context;
public function __construct(Db $db, Context $context)
{
$this->db = $db;
$this->context = $context;
}
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,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,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 Currency;
class CurrencyRepository
{
/**
* @var Currency
*/
private $currency;
public function __construct(Currency $currency)
{
$this->currency = $currency;
}
/**
* 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,
];
}
}

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\Repository;
use Language;
class LanguageRepository
{
public function __construct()
{
}
public function getIsoById(int $id)
{
return Language::getIsoById($id);
}
}

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 $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 $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,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\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
class ShopRepository
{
public function getShopDomainsAndConfiguration()
{
$sql = new DbQuery();
$sql->select('su.`id_shop`, `domain`, `domain_ssl`, c.`value` as acces_token_value');
$sql->from('shop_url', 'su');
$sql->leftJoin('configuration', 'c', 'su.id_shop = c.id_shop');
$sql->where('c.name LIKE "' . Config::PSX_MKTG_WITH_GOOGLE_ACCOUNT_IS_LINKED . '"');
return Db::getInstance()->executeS($sql);
}
}

View File

@@ -0,0 +1,78 @@
<?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 StateRepository
{
/**
* @var Db
*/
private $db;
/**
* @var Context
*/
private $context;
private $stateIsoCodeCache = [];
public function __construct(Db $db, Context $context)
{
$this->db = $db;
$this->context = $context;
}
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,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,65 @@
<?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 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 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_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,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,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,17 @@
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:
- '@psxmarketingwithgoogle'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\TabRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler'

View File

@@ -0,0 +1,12 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Provider\CarrierDataProvider:
class: PrestaShop\Module\PsxMarketingWithGoogle\Provider\CarrierDataProvider
public: true
arguments:
- '@PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Builder\CarrierBuilder'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\CarrierRepository'
PrestaShop\Module\PsxMarketingWithGoogle\Provider\GoogleTagProvider:
class: PrestaShop\Module\PsxMarketingWithGoogle\Provider\GoogleTagProvider
public: true

View File

@@ -0,0 +1,6 @@
imports:
- { resource: ../common.yml }
- { resource: accounts.yml }
- { resource: installer.yml }
- { resource: builder.yml }
- { resource: provider.yml }

View File

@@ -0,0 +1,17 @@
imports:
- { resource: common/adapter.yml }
- { resource: common/buffer.yml }
- { resource: common/config.yml }
- { resource: common/context.yml }
- { resource: common/handler.yml }
- { resource: common/provider.yml }
- { resource: common/repository.yml }
- { resource: common/segment.yml }
services:
psxmarketingwithgoogle:
class: 'PsxMarketingWithGoogle'
public: true
factory: ['Module', 'getInstanceByName']
arguments:
- 'psxmarketingwithgoogle'

View File

@@ -0,0 +1,6 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter:
class: PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter
public: true
arguments:
- '@=service("psxmarketingwithgoogle.shop").id'

View File

@@ -0,0 +1,4 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Buffer\TemplateBuffer:
class: PrestaShop\Module\PsxMarketingWithGoogle\Buffer\TemplateBuffer
public: true

View File

@@ -0,0 +1,4 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Config\Env:
class: PrestaShop\Module\PsxMarketingWithGoogle\Config\Env
public: true

View File

@@ -0,0 +1,50 @@
services:
psxmarketingwithgoogle.context:
class: 'Context'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getContext']
psxmarketingwithgoogle.controller:
class: 'Controller'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getController']
psxmarketingwithgoogle.cookie:
class: 'Cookie'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getCookie']
psxmarketingwithgoogle.language:
class: 'Language'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getLanguage']
psxmarketingwithgoogle.currency:
class: 'Currency'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getCurrency']
psxmarketingwithgoogle.smarty:
class: 'Smarty'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getSmarty']
psxmarketingwithgoogle.country:
class: 'Country'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getCountry']
psxmarketingwithgoogle.shop:
class: 'Shop'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getShop']
psxmarketingwithgoogle.link:
class: 'Shop'
public: true
factory: ['PrestaShop\Module\PsxMarketingWithGoogle\Factory\ContextFactory', 'getLink']
psxmarketingwithgoogle.db:
class: Db
public: true
factory: [ 'Db', 'getInstance' ]

View File

@@ -0,0 +1,5 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Factory\ApiClientFactory:
class: PrestaShop\Module\PsxMarketingWithGoogle\Factory\ApiClientFactory
arguments:
- '@PrestaShop\Module\PsxMarketingWithGoogle\Config\Env'

View File

@@ -0,0 +1,13 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler:
class: PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler
public: true
PrestaShop\Module\PsxMarketingWithGoogle\Handler\RemarketingHookHandler:
class: PrestaShop\Module\PsxMarketingWithGoogle\Handler\RemarketingHookHandler
public: true
arguments:
- '@PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Buffer\TemplateBuffer'
- '@psxmarketingwithgoogle.context'
- '@psxmarketingwithgoogle'

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 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Provider\PurchaseEventDataProvider:
class: PrestaShop\Module\PsxMarketingWithGoogle\Provider\PurchaseEventDataProvider
public: true
arguments:
- '@PrestaShop\Module\PsxMarketingWithGoogle\Provider\ProductDataProvider'
- '@psxmarketingwithgoogle.context'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\LanguageRepository'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository'
PrestaShop\Module\PsxMarketingWithGoogle\Provider\CartEventDataProvider:
class: PrestaShop\Module\PsxMarketingWithGoogle\Provider\CartEventDataProvider
public: true
arguments:
- '@psxmarketingwithgoogle.context'
PrestaShop\Module\PsxMarketingWithGoogle\Provider\ProductDataProvider:
class: 'PrestaShop\Module\PsxMarketingWithGoogle\Provider\ProductDataProvider'
public: true
arguments:
- '@psxmarketingwithgoogle.context'
PrestaShop\Module\PsxMarketingWithGoogle\Provider\ConversionEventDataProvider:
class: 'PrestaShop\Module\PsxMarketingWithGoogle\Provider\ConversionEventDataProvider'
public: true
arguments:
- '@psxmarketingwithgoogle.context'
PrestaShop\Module\PsxMarketingWithGoogle\Provider\PageViewEventDataProvider:
class: 'PrestaShop\Module\PsxMarketingWithGoogle\Provider\PageViewEventDataProvider'
public: true
arguments:
- '@psxmarketingwithgoogle.context'

View File

@@ -0,0 +1,55 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Repository\TabRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\TabRepository
public: true
PrestaShop\Module\PsxMarketingWithGoogle\Repository\CarrierRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\CarrierRepository
public: true
arguments:
- '@psxmarketingwithgoogle.db'
- '@psxmarketingwithgoogle.context'
PrestaShop\Module\PsxMarketingWithGoogle\Repository\AttributesRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\AttributesRepository
public: true
arguments:
- '@psxmarketingwithgoogle.context'
PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository
public: true
arguments:
- '@psxmarketingwithgoogle.db'
- '@psxmarketingwithgoogle.context'
- '@psxmarketingwithgoogle.country'
- '@PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter'
PrestaShop\Module\PsxMarketingWithGoogle\Repository\CurrencyRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\CurrencyRepository
public: true
arguments:
- '@psxmarketingwithgoogle.currency'
PrestaShop\Module\PsxMarketingWithGoogle\Repository\LanguageRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\LanguageRepository
public: true
PrestaShop\Module\PsxMarketingWithGoogle\Repository\ProductRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\ProductRepository
public: true
PrestaShop\Module\PsxMarketingWithGoogle\Repository\StateRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\StateRepository
public: true
arguments:
- '@psxmarketingwithgoogle.db'
- '@psxmarketingwithgoogle.context'
PrestaShop\Module\PsxMarketingWithGoogle\Repository\TaxRepository:
class: PrestaShop\Module\PsxMarketingWithGoogle\Repository\TaxRepository
public: true
arguments:
- '@psxmarketingwithgoogle.db'
- '@psxmarketingwithgoogle.context'

View File

@@ -0,0 +1,6 @@
services:
PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment:
class: 'PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment'
public: true
arguments:
- '@psxmarketingwithgoogle.context'

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,2 @@
imports:
- { resource: ../common.yml }

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.28.0]]></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,533 @@
<?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
*/
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler;
use PrestaShop\Module\PsxMarketingWithGoogle\Provider\CarrierDataProvider;
use PrestaShop\Module\PsxMarketingWithGoogle\Provider\GoogleTagProvider;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\AttributesRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CurrencyRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\ModuleRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\ProductRepository;
use PrestaShop\ModuleLibFaq\Faq;
class AdminAjaxPsxMktgWithGoogleController extends ModuleAdminController
{
/** @var PsxMarketingWithGoogle */
public $module;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var CountryRepository
*/
private $countryRepository;
/**
* @var CurrencyRepository
*/
private $currencyRepository;
/**
* @var GoogleTagProvider
*/
private $googleTagProvider;
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var AttributesRepository
*/
protected $attributesRepository;
public function __construct()
{
parent::__construct();
$this->bootstrap = false;
$this->errorHandler = $this->module->getService(ErrorHandler::class);
$this->configurationAdapter = $this->module->getService(ConfigurationAdapter::class);
$this->countryRepository = $this->module->getService(CountryRepository::class);
$this->productRepository = $this->module->getService(ProductRepository::class);
$this->attributesRepository = $this->module->getService(attributesRepository::class);
$this->googleTagProvider = $this->module->getService(GoogleTagProvider::class);
$this->currencyRepository = $this->module->getService(CurrencyRepository::class);
$this->ajax = true;
}
public function initContent()
{
parent::initContent();
}
public function displayAjax()
{
$inputs = json_decode(Tools::file_get_contents('php://input'), true);
$action = isset($inputs['action']) ? $inputs['action'] : null;
switch ($action) {
case 'setWebsiteVerificationMeta':
$this->setWebsiteVerificationMeta($inputs);
break;
case 'getCarrierValues':
$this->getCarrierValues();
break;
case 'getProductsReadyToSync':
$this->getProductsReadyToSync($inputs);
break;
case 'getShopConfigurationForGMC':
$this->getShopConfigurationForGMC();
break;
case 'getWebsiteRequirementStatus':
$this->getWebsiteRequirementStatus();
break;
case 'setWebsiteRequirementStatus':
$this->setWebsiteRequirementStatus($inputs);
break;
case 'retrieveFaq':
$this->retrieveFaq();
break;
case 'getShopConfigurationForAds':
$this->getShopConfigurationForAds();
break;
case 'getRemarketingTagsStatus':
$this->getRemarketingTagsStatus();
break;
case 'toggleRemarketingTags':
$this->toggleRemarketingTags($inputs);
break;
case 'checkRemarketingTagExists':
$this->checkRemarketingTagExists($inputs);
break;
case 'setConversionActionLabel':
$this->setConversionActionLabel($inputs);
break;
case 'getConversionActionLabels':
$this->getConversionActionLabels();
break;
case 'getDebugData':
$this->getDebugData();
break;
case 'setGMCInformations':
$this->setGMCInformations($inputs);
break;
case 'getShopAttributes':
$this->getShopAttributes();
break;
case 'getModuleStatus':
$this->getModuleStatus($inputs);
break;
default:
http_response_code(400);
$this->ajaxDie(json_encode(['success' => false, 'message' => $this->l('Action is missing or incorrect.')]));
}
}
private function setWebsiteVerificationMeta(array $inputs)
{
if (!isset($inputs['websiteVerificationMeta'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing Meta key',
]));
}
$websiteVerificationMeta = $inputs['websiteVerificationMeta'];
if ($websiteVerificationMeta === false) {
$this->configurationAdapter->deleteByName(Config::PSX_MKTG_WITH_GOOGLE_WEBSITE_VERIFICATION_META);
$this->ajaxDie(json_encode(['success' => true, 'method' => 'delete']));
} else {
// base64 encoded to avoid prestashop sanitization
$this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_WEBSITE_VERIFICATION_META,
base64_encode($websiteVerificationMeta)
);
$this->ajaxDie(json_encode(['success' => true, 'method' => 'insert']));
}
}
private function setGMCInformations(array $inputs)
{
if (!isset($inputs['gmcInformations'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'missing gmc informations',
]));
}
$informations = $inputs['gmcInformations'];
$this->configurationAdapter->updateValue(
Config::REMARKETING_CONVERSION_MERCHANT_GMC_ID,
$informations['id']
);
$this->ajaxDie(json_encode(['success' => true]));
}
private function getProductsReadyToSync(array $inputs)
{
$this->ajaxDie(json_encode([
'total' => $this->productRepository->getProductsTotal(
$this->context->shop->id,
['onlyActive' => true]
),
]));
}
private function getShopConfigurationForGMC()
{
$data = [
'shop' => [
'name' => $this->configurationAdapter->get('PS_SHOP_NAME'),
'url' => $this->context->link->getBaseLink($this->context->shop->id),
],
'store' => [
/*
* Based on structure available on Google documentation
* @see https://developers.google.com/shopping-content/reference/rest/v2.1/accounts#AccountAddress
*/
'streetAddress' => trim($this->configurationAdapter->get('PS_SHOP_ADDR1')
. ' '
. $this->configurationAdapter->get('PS_SHOP_ADDR2')),
'locality' => $this->configurationAdapter->get('PS_SHOP_CITY'),
'postalCode' => $this->configurationAdapter->get('PS_SHOP_CODE'),
'country' => $this->countryRepository->getShopContactCountry(),
'phone' => $this->configurationAdapter->get('PS_SHOP_PHONE'),
],
];
if ($this->countryRepository->countryNeedState((int) $this->configurationAdapter->get('PS_SHOP_COUNTRY_ID')) === true) {
$data['store']['region'] = State::getNameById($this->configurationAdapter->get('PS_SHOP_STATE_ID'));
}
$this->ajaxDie(json_encode($data));
}
private function getCarrierValues()
{
/** @var CarrierDataProvider $carrierDataProvider */
$carrierDataProvider = $this->module->getService(CarrierDataProvider::class);
$carrierLines = $carrierDataProvider->getFormattedData();
$this->ajaxDie(json_encode($carrierLines));
}
private function getWebsiteRequirementStatus()
{
$requirements = json_decode($this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_WEBSITE_REQUIREMENTS_STATUS))
?: [];
$this->ajaxDie(json_encode([
'requirements' => $requirements,
]));
}
private function setWebsiteRequirementStatus(array $inputs)
{
if (!isset($inputs['requirements']) || !is_array($inputs['requirements'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing requirements key or value must be an array',
]));
}
$requirements = $inputs['requirements'];
$allowedKeys = [
'shoppingAdsPolicies',
'accurateContactInformation',
'secureCheckoutProcess',
'returnPolicy',
'billingTerms',
'completeCheckoutProcess',
];
foreach ($requirements as $value) {
if (!in_array($value, $allowedKeys)) {
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Unknown requirement key ' . $value,
]));
}
}
$this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_WEBSITE_REQUIREMENTS_STATUS,
json_encode($requirements)
);
$this->ajaxDie(json_encode(['success' => true]));
}
public function getShopConfigurationForAds()
{
$defaultTimeZone = date_default_timezone_get();
$timeZone = new DateTime('now', new DateTimeZone($defaultTimeZone));
$this->ajaxDie(json_encode([
'timezone' => [
'offset' => $timeZone->format('P'),
'text' => $defaultTimeZone,
],
'currency' => $this->currencyRepository->getShopCurrency()['isoCode'],
]));
}
private function getRemarketingTagsStatus()
{
$this->ajaxDie(json_encode([
'remarketingTagsStatus' => (bool) $this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS),
]));
}
private function toggleRemarketingTags(array $inputs)
{
if (!isset($inputs['isRemarketingEnabled']) || !isset($inputs['tagSnippet'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing isRemarketingEnabled or tagSnippet key',
]));
}
if ((bool) $inputs['isRemarketingEnabled']) {
$this->configurationAdapter->updateValue(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS, true);
$this->configurationAdapter->updateValue(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG, base64_encode($inputs['tagSnippet']));
} else {
$this->configurationAdapter->deleteByName(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS);
$this->configurationAdapter->deleteByName(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_TAG);
}
$this->ajaxDie(json_encode(['success' => true]));
}
private function checkRemarketingTagExists(array $inputs)
{
if (!isset($inputs['tag'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing tag key',
]));
}
$googleRemarketingStatus = $this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS);
if ($googleRemarketingStatus) {
$this->configurationAdapter->updateValue(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS, false);
}
$googleTag = $this->googleTagProvider->checkGoogleTagAlreadyExists($inputs['tag'], $this->context->shop->id);
if (false === $googleTag && $googleRemarketingStatus) {
$this->configurationAdapter->updateValue(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS, true);
}
$this->ajaxDie(json_encode(['tagAlreadyExists' => $googleTag]));
}
private function setConversionActionLabel(array $inputs)
{
if (!isset($inputs['conversionActions'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing conversionActions key',
]));
}
$newTags = [];
foreach ($inputs['conversionActions'] as $index => $conversionAction) {
if (!isset($conversionAction['category']) || !isset($conversionAction['tag'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing category or tag key at index ' . $index,
]));
}
if (!in_array($conversionAction['category'], Config::REMARKETING_CONVERSION_LABELS)) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Unhandled conversion category at index ' . $index,
]));
}
$newTags[$conversionAction['category']] = $conversionAction['tag'];
}
$this->configurationAdapter->updateValue(
Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_CONVERSION_LABELS,
json_encode(
array_merge(
json_decode($this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_CONVERSION_LABELS), true) ?: [],
$newTags
)
)
);
$this->ajaxDie(json_encode(['success' => true]));
}
private function getConversionActionLabels()
{
$labels = [];
$labelsFromConfig = json_decode($this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_CONVERSION_LABELS), true) ?: [];
foreach ($labelsFromConfig as $conversionCategory => $tag) {
$labels[] = [
'category' => $conversionCategory,
'tag' => $tag,
];
}
$this->ajaxDie(json_encode([
'conversionActionLabels' => $labels,
]));
}
private function getDebugData()
{
$typesOfSync = [];
try {
$sql = new DbQuery();
$sql->select('ets.type, ets.lang_iso, ets.full_sync_finished, ets.last_sync_date');
$sql->from('eventbus_type_sync', 'ets');
$sql->where('ets.id_shop = ' . (int) $this->context->shop->id);
$sql->orderBy('ets.last_sync_date DESC');
$typesOfSync = \Db::getInstance()->executeS($sql);
} catch (Exception $e) {
$this->errorHandler->handle(
$e,
$e->getCode(),
false
);
}
$this->ajaxDie(json_encode([
'urlEventBusHealthCheck' => $this->context->link->getModuleLink(
'ps_eventbus',
'apiHealthCheck'
),
'typesOfSync' => $typesOfSync,
]));
}
public function getShopAttributes()
{
$this->ajaxDie(
json_encode(
$this->attributesRepository->getAllAttributes()
)
);
}
private function getModuleStatus(array $inputs)
{
if (!isset($inputs['moduleName'])) {
http_response_code(400);
$this->ajaxDie(json_encode([
'success' => false,
'message' => 'Missing moduleName key',
]));
}
$this->ajaxDie(
json_encode(
(new ModuleRepository($inputs['moduleName']))->getInformationsAboutModule()
)
);
}
/**
* {@inheritdoc}
*/
protected function ajaxDie($value = null, $controller = null, $method = null)
{
header('Content-Type: application/json');
parent::ajaxDie($value, $controller, $method);
}
/**
* Retrieve the faq
*/
public function retrieveFaq()
{
$faq = new Faq($this->module->module_key, _PS_VERSION_, $this->context->language->iso_code);
$this->ajaxDie(
json_encode(
[
'faq' => $faq->getFaq(),
'doc' => $this->getUserDocumentation(),
'contactUs' => 'support-google@prestashop.com',
]
)
);
}
/**
* Get the documentation url depending on the current language
*
* @return string
*/
private function getUserDocumentation()
{
$isoCode = $this->context->language->iso_code;
$baseUrl = 'https://storage.googleapis.com/psessentials-documentation/' . $this->module->name;
if (!$this->checkFileExist($baseUrl . '/user_guide_' . $isoCode . '.pdf')) {
$isoCode = 'en';
}
return $baseUrl . '/user_guide_' . $isoCode . '.pdf';
}
/**
* Use cUrl to get HTTP headers and detect any HTTP 404
*
* @param string $docUrl
*
* @return bool
*/
private function checkFileExist($docUrl)
{
$ch = curl_init($docUrl);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $retcode < 400;
}
}

View File

@@ -0,0 +1,171 @@
<?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
*/
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Env;
use PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CountryRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\CurrencyRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\ModuleRepository;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class AdminPsxMktgWithGoogleModuleController extends ModuleAdminController
{
/** @var PsxMarketingWithGoogle */
public $module;
/**
* @var Env
*/
private $env;
/**
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var CountryRepository
*/
private $countryRepository;
/**
* @var CurrencyRepository
*/
private $currencyRepository;
/**
* @var ModuleRepository
*/
private $moduleRepository;
public function __construct()
{
parent::__construct();
$this->bootstrap = false;
$this->module->getService(ErrorHandler::class);
$this->env = $this->module->getService(Env::class);
$this->configurationAdapter = $this->module->getService(ConfigurationAdapter::class);
$this->countryRepository = $this->module->getService(CountryRepository::class);
$this->currencyRepository = $this->module->getService(CurrencyRepository::class);
$this->moduleRepository = new ModuleRepository($this->module->name);
}
public function initContent()
{
// from google response
if (Tools::getValue('message') !== false || Tools::getValue('from') !== false) {
$this->ajax = true;
$this->content = $this->context->smarty->fetch('module:psxmarketingwithgoogle/views/templates/admin/googlePopin.tpl');
return;
}
$this->context->smarty->assign([
'pathApp' => (bool) $this->env->get('USE_LOCAL_VUE_APP') ? $this->module->getPathUri() . 'views/js/app.js' : $this->env->get('PSX_MKTG_WITH_GOOGLE_CDN_URL') . 'app.js',
'chunkVendor' => (bool) $this->env->get('USE_LOCAL_VUE_APP') ? $this->module->getPathUri() . 'views/js/chunk-vendors.js' : $this->env->get('PSX_MKTG_WITH_GOOGLE_CDN_URL') . 'chunk-vendors.js',
'psxMktgWithGoogleControllerLink' => $this->context->link->getAdminLink('AdminAjaxPsxMktgWithGoogle'),
]);
try {
$psAccountsService = $this->module->getService(PsAccounts::class)->getPsAccountsService();
$shopIdPsAccounts = $psAccountsService->getShopUuidV4();
$tokenPsAccounts = $psAccountsService->getOrRefreshToken();
} catch (Exception $e) {
$shopIdPsAccounts = null;
$tokenPsAccounts = null;
}
Media::addJsDef([
'contextPsAccounts' => (object) $this->module->getService(PsAccounts::class)
->getPsAccountsPresenter()
->present($this->module->name),
'i18nSettings' => [
'isoCode' => $this->context->language->iso_code,
'languageLocale' => $this->context->language->language_code,
],
'psGoogleRetrieveFaq' => $this->context->link->getAdminLink(
'AdminAjaxPsxMktgWithGoogle',
true,
[],
[
'action' => 'RetrieveFaq',
'ajax' => 1,
]
),
'psGoogleCallEventBus' => $this->context->link->getAdminLink(
'AdminAjaxPsxMktgWithGoogle',
true,
[],
[
'ajax' => 1,
]
),
'shopIdPsAccounts' => $shopIdPsAccounts,
'tokenPsAccounts' => $tokenPsAccounts,
'psVersion' => _PS_VERSION_,
'phpVersion' => phpversion(),
'psxMktgWithGoogleModuleVersion' => $this->module->version,
'psxMktgWithGoogleOnProductionEnvironment' => $this->env->get('PSX_MKTG_WITH_GOOGLE_API_URL') === Config::PSX_MKTG_WITH_GOOGLE_API_URL,
'psxMktgWithGoogleSegmentId' => $this->env->get('PSX_MKTG_WITH_GOOGLE_SEGMENT_API_KEY'),
'psxMktgWithGoogleDsnSentry' => $this->env->get('PSX_MKTG_WITH_GOOGLE_SENTRY_CREDENTIALS_VUE'),
'psxMktgWithGoogleApiUrl' => $this->env->get('PSX_MKTG_WITH_GOOGLE_API_URL'),
'psxMktgWithGoogleAdminUrl' => $this->context->link->getAdminLink('AdminPsxMktgWithGoogleModule'),
'psxMktgWithGoogleAdminAjaxUrl' => $this->context->link->getAdminLink(
'AdminAjaxPsxMktgWithGoogle',
true,
[],
[
'ajax' => 1,
]
),
'psxMktgWithGoogleMaintenanceSettingsUrl' => Tools::getShopDomainSsl(true) . $this->context->link->getAdminLink(
'AdminMaintenance'
),
'psxMktgWithGoogleCarriersUrl' => $this->context->link->getAdminLink('AdminCarriers'),
'psxMktgWithGoogleAttributesUrl' => $this->context->link->getAdminLink('AdminAttributesGroups'),
'psxMktgWithGoogleStoreSettingsUrl' => $this->context->link->getAdminLink('AdminStores'),
'psxMktgWithGoogleProductDetailUrl' => $this->context->link->getAdminLink(
'AdminProducts',
true,
['id_product' => 1, 'updateproduct' => '1']
),
'psxMktgWithGoogleEnableLink' => $this->moduleRepository->getEnableLink(),
'psxMktgWithGoogleModuleIsEnabled' => $this->moduleRepository->moduleIsEnabled(),
'isCountryMemberOfEuropeanUnion' => $this->countryRepository->isCompatibleForCSS(),
'psxMktgWithGoogleShopUrl' => $this->context->link->getBaseLink($this->context->shop->id),
'psxMktgWithGoogleActiveCountries' => $this->countryRepository->getActiveCountries(),
'psxMtgWithGoogleDefaultShopCountry' => $this->countryRepository->getShopDefaultCountry()['iso_code'],
'psxMktgWithGoogleShopCurrency' => $this->currencyRepository->getShopCurrency(),
'psxMktgWithGoogleRemarketingTagsStatus' => (bool) $this->configurationAdapter->get(Config::PSX_MKTG_WITH_GOOGLE_REMARKETING_STATUS),
]);
$this->content = $this->context->smarty->fetch($this->module->getLocalPath() . '/views/templates/admin/app.tpl');
parent::initContent();
}
public function postProcess()
{
}
}

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,7 @@
base_path: /_dev/src/assets/json/translations
preserve_hierarchy: false
files:
- source: /en/**/ui.json
translation: /%two_letters_code%/**/%original_file_name%
skip_untranslated_strings: true
skip_untranslated_files: true

View File

@@ -0,0 +1,35 @@
version: '2'
services:
mysql:
image: mysql:5.7
container_name: ps17_mysql
ports:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: psreference
reference-release:
image: prestashop/prestashop:1.7
container_name: ps17_php
volumes:
- ./:/var/www/html/modules/psxmarketingwithgoogle
environment:
DB_SERVER: mysql
DB_PASSWD: root
DB_NAME: psreference
PS_DOMAIN: localhost:8001
PS_DEV_MODE: 1
PS_INSTALL_AUTO: 1
PS_ERASE_DB: 1
PS_INSTALL_DB: 1
PS_FOLDER_ADMIN: admin-dev
PS_FOLDER_INSTALL: install-dev
PS_LANGUAGE: fr
PS_COUNTRY: fr
ADMIN_MAIL: demo@prestashop.com
ADMIN_PASSWD: prestashop_demo
depends_on:
- mysql
ports:
- "8001:80"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,247 @@
<?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
*/
use Dotenv\Dotenv;
use PrestaShop\Module\PsxMarketingWithGoogle\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PsxMarketingWithGoogle\Config\Config;
use PrestaShop\Module\PsxMarketingWithGoogle\Database\Installer;
use PrestaShop\Module\PsxMarketingWithGoogle\Database\Uninstaller;
use PrestaShop\Module\PsxMarketingWithGoogle\Handler\ErrorHandler;
use PrestaShop\Module\PsxMarketingWithGoogle\Handler\RemarketingHookHandler;
use PrestaShop\Module\PsxMarketingWithGoogle\Repository\TabRepository;
use PrestaShop\Module\PsxMarketingWithGoogle\Tracker\Segment;
use PrestaShop\ModuleLibServiceContainer\DependencyInjection\ServiceContainer;
if (!defined('_PS_VERSION_')) {
exit;
}
class PsxMarketingWithGoogle extends Module
{
/**
* @var ServiceContainer
*/
private $serviceContainer;
/**
* @var string
*/
public $controllerAdmin;
/**
* @var bool
*/
public $psVersionIs17;
/**
* @var string
*/
public $css_path;
/**
* @var string
*/
public $docs_path;
/**
* @var string
*/
public $js_path;
public $front_controller = null;
public function __construct()
{
$this->name = 'psxmarketingwithgoogle';
$this->tab = 'advertising_marketing';
$this->version = '1.28.0';
$this->author = 'PrestaShop';
$this->need_instance = 0;
$this->module_key = '16b273e77e02c0cc36cd006463951593';
$this->controllerAdmin = 'AdminAjaxPsxMktgWithGoogle';
$this->bootstrap = false;
parent::__construct();
$this->displayName = $this->l('Marketing with Google');
$this->description = $this->l('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.');
$this->psVersionIs17 = (bool) version_compare(_PS_VERSION_, '1.7', '>=');
$this->css_path = $this->_path . 'views/css/';
$this->js_path = $this->_path . 'views/js/';
$this->docs_path = $this->_path . 'docs/';
$this->confirmUninstall = $this->l('Are you sure you want to uninstall this module?');
$this->ps_versions_compliancy = ['min' => '1.7.5.0', 'max' => _PS_VERSION_];
// If PHP is not compliant, we will not load composer and the autoloader
if (!$this->isPhpVersionCompliant()) {
return;
}
require_once __DIR__ . '/vendor/autoload.php';
if ($this->serviceContainer === null) {
$this->serviceContainer = new ServiceContainer($this->name, $this->getLocalPath());
}
$this->loadEnv();
}
/**
* @param string $serviceName
*
* @return mixed
*/
public function getService($serviceName)
{
return $this->serviceContainer->getService($serviceName);
}
public function install()
{
if (!$this->isPhpVersionCompliant()) {
$this->_errors[] = $this->l('This requires PHP 7.2 to work properly. Please upgrade your server configuration.');
// We return true during the installation of PrestaShop to not stop the whole process,
// Otherwise we warn properly the installation failed.
return defined('PS_INSTALLATION_IN_PROGRESS');
}
// We can't init the Uninstaller in CLI, as it has been declared in the admin container and PrestaShop
// does not have the _PS_ADMIN_DIR_ in this environment.
// prestashop/module-lib-service-container:1.3.1 is known as incompatible
// $installer = $this->getService(Installer::class);
$installer = new Installer(
$this,
$this->getService(Segment::class),
$this->getService(ErrorHandler::class)
);
if (!$installer->install()) {
$this->_errors = $installer->getErrors();
return false;
}
if (!parent::install()) {
$this->_errors[] = $this->l('Unable to install module');
return false;
}
/* @phpstan-ignore-next-line */
$this->registerHook(Config::HOOK_LIST);
return true;
}
public function uninstall()
{
// If PHP is not compliant, we try our best to uninstall the module
if (!$this->isPhpVersionCompliant()) {
return parent::uninstall();
}
// We can't init the Uninstaller in CLI, as it has been declared in the admin container and PrestaShop
// does not have the _PS_ADMIN_DIR_ in this environment.
// prestashop/module-lib-service-container:1.3.1 is known as incompatible
// $uninstaller = $this->getService(Uninstaller::class);
$uninstaller = new Uninstaller(
$this,
$this->getService(TabRepository::class),
$this->getService(Segment::class),
$this->getService(ErrorHandler::class)
);
return $uninstaller->uninstall()
&& parent::uninstall();
}
public function getContent()
{
// With the version prestashop/prestashop-accounts-auth:2.1.9, a successful login will redirect
// to the module configuration page with extra parameters.
// We filter the default parameters so the extra ones remain present on the controller we redirect to.
unset($_GET['controller'], $_GET['configure'], $_GET['token'], $_GET['controllerUri']);
Tools::redirectAdmin($this->context->link->getAdminLink('AdminPsxMktgWithGoogleModule') . '&' . http_build_query($_GET));
}
public function hookDisplayBackOfficeHeader()
{
$getConfValue = Tools::getValue('conf');
if (!empty($getConfValue) && $getConfValue === '4' && $this->context->controller->controller_name === 'AdminCarriers') {
Media::addJsDef([
'transitWarningMsg' => $this->l('You have updated one or many of your carriers, do not forget to update your shipping settings on your Google Module.'),
'redirectMsg' => $this->l('Take me there.'),
'moduleLink' => $this->context->link->getAdminLink('AdminPsxMktgWithGoogleModule'),
]);
$this->context->controller->addJs($this->getPathUri() . 'views/js/hook/shippingWarning.js');
}
$this->context->controller->addCSS($this->getPathUri() . 'views/css/admin/menu.css');
}
public function hookDisplayHeader()
{
$configuration = $this->getService(ConfigurationAdapter::class);
return base64_decode($configuration->get(Config::PSX_MKTG_WITH_GOOGLE_WEBSITE_VERIFICATION_META))
. $this->getService(RemarketingHookHandler::class)->handleHook(__FUNCTION__);
}
public function hookDisplayTop()
{
return $this->getService(RemarketingHookHandler::class)->handleHook(__FUNCTION__);
}
public function hookDisplayOrderConfirmation($params)
{
return $this->getService(RemarketingHookHandler::class)->handleHook(__FUNCTION__, $params);
}
public function hookActionCartUpdateQuantityBefore($params)
{
return $this->getService(RemarketingHookHandler::class)->handleHook(__FUNCTION__, $params);
}
/**
* return __FILE__
*
* @return string
*/
public function getFilePath()
{
return __FILE__;
}
private function loadEnv()
{
if (file_exists(__DIR__ . '/.env')) {
$dotenv = Dotenv::create(__DIR__);
$dotenv->load();
}
}
private function isPhpVersionCompliant()
{
return 70200 <= PHP_VERSION_ID;
}
}

View File

@@ -0,0 +1,28 @@
<?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
*/
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,28 @@
<?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
*/
$sql = [];
foreach ($sql as $query) {
if (Db::getInstance()->execute($query) == false) {
return false;
}
}
return true;

View File

@@ -0,0 +1,28 @@
<?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
*/
$sql = [];
foreach ($sql as $query) {
if (Db::getInstance()->execute($query) == false) {
return false;
}
}
return true;

View File

@@ -0,0 +1,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'PrestaShop Marketing macht es Ihnen leicht, Ihren Store mit Google zu verbinden und Ihre Produkte in verschiedenen Netzwerken wie Google Search, YouTube oder Gmail Millionen von Käufern zugänglich zu machen. Erstellen Sie Smart-Shopping-Kampagnen ohne Ihr PrestaShop-Dashboard zu verlassen und steigern Sie die Besucherzahlen.';

View File

@@ -0,0 +1,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'PrestaShop Marketing facilita la conexión de tu tienda con Google y la promoción de tus productos a millones de compradores a través de diferentes redes como Google Search, YouTube o Gmail. Crea Campañas de Shopping inteligentes sin salir de tu panel de control de PrestaShop y consigue más tráfico.';

View File

@@ -0,0 +1,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'PrestaShop Marketing permet de connecter facilement votre boutique avec Google et de promouvoir vos produits auprès de millions d\'acheteurs sur différents réseaux comme Google Search, YouTube ou Gmail. Créez des Campagnes Shopping intelligentes sans quitter votre tableau de bord PrestaShop et augmentez le trafic.';

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,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'PrestaShop Marketing ti permette di collegare facilmente il tuo negozio con Google e di promuovere i tuoi prodotti a milioni di shoppers attraverso diversi network come Google Search, YouTube o Gmail. Crea Campagne Shopping intelligenti senza lasciare il back office PrestaShop e aumenta il tuo traffico.';

View File

@@ -0,0 +1,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'PrestaShop Marketing maakt het gemakkelijk om uw winkel te verbinden met Google en uw producten te promoten bij miljoenen shoppers via verschillende netwerken zoals Google Search, YouTube of Gmail. Creëer Smart Shopping campagnes zonder uw PrestaShop dashboard te verlaten en zorg voor meer verkeer.';

View File

@@ -0,0 +1,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'PrestaShop Marketing umożliwia łatwe połączenie Twojego sklepu z Google i promowanie produktów wśród milionów kupujących w różnych przestrzeniach, takich jak wyszukiwarka Google, YouTube czy Gmail. Stwórz inteligentne kampanie produktowe bez opuszczania swojego panelu zarządzania PrestaShop i wygeneruj więcej ruchu na stronie.';

View File

@@ -0,0 +1,24 @@
<?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
*/
global $_MODULE;
$_MODULE = array();
$_MODULE['<{psxmarketingwithgoogle}prestashop>psxmarketingwithgoogle_82a70332ee3efccca1bdc9751e2e88b3'] = 'O Marketing PrestaShop facilita a ligação da sua loja com o Google e a promoção dos seus produtos a milhões de compradores em diferentes redes como o Google Search, o YouTube ou o Gmail. Crie campanhas inteligentes do Shopping sem sair do seu painel de controlo PrestaShop e aumente o seu tráfego.';

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 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit317101808f5c66283ce0976762c81441::getLoader();

View File

@@ -0,0 +1,120 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../segmentio/analytics-php/bin/analytics)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/segmentio/analytics-php/bin/analytics');
exit(0);
}
}
include __DIR__ . '/..'.'/segmentio/analytics-php/bin/analytics';

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;

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