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,18 @@
2007-2021 PrestaShop and Contributors
NOTICE OF LICENSE
This source file is subject to the Academic Free License 3.0 (AFL-3.0)
that is bundled with this package in the file LICENSE.txt.
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 <contact@prestashop.com>
@copyright 2007-2021 PrestaShop SA and Contributors
@license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
International Registered Trademark & Property of PrestaShop SA

View File

@@ -0,0 +1,141 @@
![PrestaShop Facebook logo](views/img/logo-wordmark.png)
# PrestaShop Facebook (ps_facebook)
![PHP tests](https://github.com/PrestaShopCorp/ps_facebook/workflows/PHP%20tests/badge.svg)
![JS tests](https://github.com/PrestaShopCorp/ps_facebook/workflows/JS%20tests/badge.svg)
## Installation
Use `make build` to install dependencies (or `make docker-build` to run it within docker).
Check other commands with `make help`.
## Requirements
This module is compliant with PHP 5.6+ and PrestaShop 1.7, (tested with PS 1.7.2+ before each release).
You need a facebook developper account added to the PrestaShop Social Media app (ID:726899634800479) to manage its settings.
## CDN usage
If you want to use local vue app, set on your .env USE_LOCAL_VUE_APP at 1.
```
USE_LOCAL_VUE_APP=1
```
## Usage
Install module and connect to FBE in module BO
## Delivery
### Automatic
This package should be automatically delivered by the CI/CD, see the [github workflows](./github/workflows).
Zips should be available for each [releases](./releases).
### Manual
1. Fill up `.env.inte` and `.env.prod` files
2. Use `make bundle` to build up deliverable zips for integration and production purpose.
3. Find zips within the `./dist` directory
## About
### Compliancy with PrestaShop 1.6
This module is not compliant with PS 1.6 as some Pixel events could not be implemented properly on this version (i.e `CustomizeProduct`).
This avoids potential misunderstanding about mismatching behavior of the module with different versions of PrestaShop.
### Facebook Pixel
* **Pixel & GDPR**
Based of the [Facebook documentation about GDPR](https://developers.facebook.com/docs/facebook-pixel/implementation/gdpr/),
a user may revoke his consent to use Pixel. This can be notified to Facebook by calling `fbq('consent', 'revoke');`.
Cookies management modules are available on the PrestaShop marketplace to allow the management of Facebook features
to each user.
For third-party module developers, this module will revoke the consent to use Pixel if the proper JS variable is
set in the page content before the initialization of this module:
```js
window.doNotConsentToPixel = true;
```
* **Using Pixel event in other modules**
You can call custom Pixel event by using hook: actionFacebookCallPixel
You also need to add some params in hook call
*Required:*
+ eventName
+ module
*Optional:*
+ id_product
+ id_product_attribute
Example:
```
Hook::exec('actionFacebookCallPixel' ,['eventName' => 'AddToWishlist', 'module' => 'wishlist', 'id_product' => $productId, 'id_product_attribute' => $idProductAttribute]);
```
* **Documentation**
- [List of standard Pixel events](https://developers.facebook.com/docs/facebook-pixel/reference/)
### Development
The main branch receiving all kind of contributions (bug fixes, improvements & new features) is the `master` branch.
In the future we may maintain several branches at the same time, for instance to fix the current version in production while we prepare new features for the next release.
These branches would be defined as `[1-9]*.[1-9]*.x` (for instance `1.4.x`).
* **Running with dev dependencies**
```
composer install --dev
```
* **Working with VueJS app**
To set the build of the VueJS app in development mode and watching your changes:
```bash
cd _dev
npm run dev
```
* **Replacing config values of the project**
Some values of the Config class can be overwriten by having your own environment variables.
You can for instance have your own `.env` at the root of this project to replace the Facebook App ID
or switch the API URLs to another domain.
### Tests
This module follows [recommandations of the PrestaShop devdocs](https://devdocs.prestashop.com/1.7/modules/testing/) and is checked by PHP-CS-Fixer, PHPStan and PHPUnit before each release.
Two sets of tests have been implemented in this module:
- **Unit tests**
```
vendor/bin/phpunit tests/unit/
```
- **Integration tests**
These tests run the calls to Facebook API to make sure the data the module relies on is still valid.
It requires preliminary configuration, by setting your FBE configuration in a JSON config file.
```bash
cp tests/integration/config.json.dist tests/integration/config.json
# Edit your config.json, then
vendor/bin/phpunit tests/integration/ -v
```

View File

@@ -0,0 +1,110 @@
<?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\PrestashopFacebook\API\Client;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
use Psr\Http\Client\ClientInterface;
class FacebookCategoryClient
{
/**
* @var ClientInterface
*/
private $client;
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
/**
* @var ResponseListener
*/
private $responseListener;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
GoogleCategoryRepository $googleCategoryRepository,
ResponseListener $responseListener
) {
$this->client = $apiClientFactory->createClient();
$this->googleCategoryRepository = $googleCategoryRepository;
$this->responseListener = $responseListener;
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId)
{
$googleCategoryId = $this->googleCategoryRepository->getGoogleCategoryIdByCategoryId($categoryId, $shopId);
if (empty($googleCategoryId)) {
return null;
}
$googleCategory = $this->get('taxonomy/' . $googleCategoryId);
if (!is_array($googleCategory)) {
return null;
}
return reset($googleCategory);
}
protected function get($id, array $fields = [], array $query = [])
{
$query = array_merge(
[
'fields' => implode(',', $fields),
],
$query
);
$request = new Request(
'GET',
"/{$id}",
[
'query' => $query,
]
);
$response = $this->responseListener->handleResponse(
$this->client->sendRequest($request),
[
'exceptionClass' => FacebookClientException::class,
]
);
if (!$response->isSuccessful()) {
return false;
}
return $response->getBody();
}
}

View File

@@ -0,0 +1,419 @@
<?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\PrestashopFacebook\API\Client;
use Exception;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Ad;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\FacebookBusinessManager;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Page;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Pixel;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\User;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Handler\ConfigurationHandler;
use PrestaShop\Module\PrestashopFacebook\Provider\AccessTokenProvider;
use Psr\Http\Client\ClientInterface;
class FacebookClient
{
/**
* @var string
*/
private $accessToken;
/**
* @var string
*/
private $sdkVersion;
/**
* @var ClientInterface
*/
private $client;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ConfigurationHandler
*/
private $configurationHandler;
/**
* @var ResponseListener
*/
private $responseListener;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
AccessTokenProvider $accessTokenProvider,
ConfigurationAdapter $configurationAdapter,
ConfigurationHandler $configurationHandler,
ResponseListener $responseListener
) {
$this->accessToken = $accessTokenProvider->getUserAccessToken();
$this->sdkVersion = Config::API_VERSION;
$this->client = $apiClientFactory->createClient();
$this->configurationAdapter = $configurationAdapter;
$this->configurationHandler = $configurationHandler;
$this->responseListener = $responseListener;
}
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}
/**
* @return bool
*/
public function hasAccessToken()
{
return (bool) $this->accessToken;
}
public function getUserEmail()
{
$responseContent = $this->get('me', __FUNCTION__, ['email']);
return new User(
isset($responseContent['email']) ? $responseContent['email'] : null
);
}
/**
* @param string $businessManagerId
*
* @return FacebookBusinessManager
*/
public function getBusinessManager($businessManagerId)
{
$responseContent = $this->get($businessManagerId, __FUNCTION__, ['name', 'created_time']);
return new FacebookBusinessManager(
isset($responseContent['id']) ? $responseContent['id'] : $businessManagerId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
/**
* @param string $adId
* @param string $pixelId
*
* @see https://developers.facebook.com/docs/marketing-api/reference/ad-account/adspixels/?locale=en_US
*
* @return Pixel
*/
public function getPixel($adId, $pixelId)
{
$name = $lastFiredTime = null;
$isUnavailable = false;
if (!empty($adId)) {
$responseContent = $this->get('act_' . $adId . '/adspixels', __FUNCTION__, ['name', 'last_fired_time', 'is_unavailable']);
if (isset($responseContent['data'])) {
foreach ($responseContent['data'] as $adPixel) {
if ($adPixel['id'] !== $pixelId) {
continue;
}
$name = isset($adPixel['name']) ? $adPixel['name'] : null;
$lastFiredTime = isset($adPixel['last_fired_time']) ? $adPixel['last_fired_time'] : null;
$isUnavailable = isset($adPixel['is_unavailable']) ? $adPixel['is_unavailable'] : null;
}
}
}
return new Pixel(
$pixelId,
$name,
$lastFiredTime,
$isUnavailable,
(bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PIXEL_ENABLED)
);
}
/**
* @param array $pageIds
*
* @return Page
*/
public function getPage(array $pageIds)
{
$pageId = reset($pageIds);
$responseContent = $this->get($pageId, __FUNCTION__, ['name', 'fan_count']);
$logoResponse = $this->get($pageId . '/photos', __FUNCTION__ . 'Photo', ['picture']);
$logo = null;
if (is_array($logoResponse)) {
$logo = reset($logoResponse['data'])['picture'];
}
return new Page(
isset($responseContent['id']) ? $responseContent['id'] : $pageIds,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['fan_count']) ? $responseContent['fan_count'] : null,
$logo
);
}
/**
* @param string $adId
*
* @return Ad
*/
public function getAd($adId)
{
$responseContent = $this->get('act_' . $adId, __FUNCTION__, ['name', 'created_time']);
return new Ad(
isset($responseContent['id']) ? $responseContent['id'] : $adId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
public function getFbeAttribute($externalBusinessId)
{
$responseContent = $this->get(
'fbe_business/fbe_installs',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
return reset($responseContent['data']);
}
public function getFbeFeatures($externalBusinessId)
{
$response = $this->get(
'fbe_business',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
if (!is_array($response)) {
return [];
}
return $response;
}
public function updateFeature($externalBusinessId, $configuration)
{
$body = [
'fbe_external_business_id' => $externalBusinessId,
'business_config' => $configuration,
];
return $this->post(
'fbe_business',
[],
$body
);
}
/**
* @see https://developers.facebook.com/docs/marketing-api/fbe/fbe2/guides/uninstall?locale=en_US#uninstall-fbe--v2-for-businesses
*
* @return false|array
*/
public function uninstallFbe()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$accessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$this->configurationHandler->cleanOnboardingConfiguration();
$this->accessToken = '';
$body = [
'fbe_external_business_id' => $externalBusinessId,
'access_token' => $accessToken,
];
return $this->delete(
'fbe_business/fbe_installs',
[],
$body
);
}
/**
* @param int $catalogId
*
* @return array|false
*/
public function getProductsInCatalogCount($catalogId)
{
$body = [
'fields' => 'product_count',
];
return $this->post(
$catalogId,
[],
$body
);
}
public function disconnectFromFacebook()
{
$this->uninstallFbe();
$this->configurationHandler->cleanOnboardingConfiguration();
}
public function addFbeAttributeIfMissing(array &$onboardingParams)
{
if (!empty($onboardingParams['fbe']) && !isset($onboardingParams['fbe']['error'])) {
return;
}
$this->setAccessToken($onboardingParams['access_token']);
$onboardingParams['fbe'] = $this->getFbeAttribute($this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID));
}
/**
* @param string $id
* @param string $callerFunction
* @param array $fields
* @param array $query
*
* @return false|array
*
* @throws Exception
*/
private function get($id, $callerFunction, array $fields = [], array $query = [])
{
$query = array_merge(
[
'access_token' => $this->accessToken,
'fields' => implode(',', $fields),
],
$query
);
$request = new Request(
'GET',
"/{$this->sdkVersion}/{$id}?" . http_build_query($query)
);
$response = $this->responseListener->handleResponse(
$this->client->sendRequest($request),
[
'exceptionClass' => FacebookClientException::class,
]
);
$responseContent = $response->getBody();
if (!$response->isSuccessful()) {
$exceptionCode = false;
if (!empty($responseContent['error']['code'])) {
$exceptionCode = $responseContent['error']['code'];
}
if ($exceptionCode && in_array($exceptionCode, Config::OAUTH_EXCEPTION_CODE)) {
$this->disconnectFromFacebook();
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_FORCED_DISCONNECT, true);
}
return false;
}
return $responseContent;
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function post($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'POST');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function delete($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'DELETE');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
* @param string $method
*
* @return false|array
*/
private function sendRequest($id, array $headers, array $body, $method)
{
$body = array_merge(
[
'access_token' => $this->accessToken,
],
$body
);
$request = new Request(
$method,
"/{$this->sdkVersion}/{$id}",
$headers,
json_encode($body)
);
$response = $this->responseListener->handleResponse(
$this->client->sendRequest($request),
[
'exceptionClass' => FacebookClientException::class,
]
);
if (!$response->isSuccessful()) {
return false;
}
return $response->getBody();
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API\EventSubscriber;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ParsedResponse;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class AccountSuspendedSubscriber implements SubscriberInterface
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(ConfigurationAdapter $configurationAdapter)
{
$this->configurationAdapter = $configurationAdapter;
}
public function onParsedResponse(ParsedResponse $response, array $options): void
{
$suspension = $response->getResponse()->getHeader('X-Account-Suspended') ?: $response->getResponse()->getHeader('x-account-suspended');
if (!empty($suspension)) {
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_SUSPENSION_REASON, $suspension);
}
}
}

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\PrestashopFacebook\API\EventSubscriber;
use Exception;
use PrestaShop\Module\PrestashopFacebook\API\ParsedResponse;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
class ApiErrorSubscriber implements SubscriberInterface
{
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(ErrorHandler $errorHandler)
{
$this->errorHandler = $errorHandler;
}
public function onParsedResponse(ParsedResponse $response, array $options): void
{
if ($response->isSuccessful()) {
return;
}
$class = $options['exceptionClass'] ?: Exception::class;
// TODO: Error sent to the error handler can be improved from the response content
$this->errorHandler->handle(
new $class(
$this->getMessage($response)
),
$response->getResponse()->getStatusCode(),
false,
[
'extra' => $response->getBody(),
]
);
}
private function getMessage(ParsedResponse $response)
{
$body = $response->getBody();
// If there is a error object returned by the Facebook API, use their codes
if (!empty($body['code']) && !empty($body['error_subcode']) && !empty($body['type'])) {
return 'Facebook API errored with ' . $body['type'] . ' (' . $body['code'] . ' / ' . $body['error_subcode'] . ')';
}
if (!empty($body['code']) && !empty($body['type'])) {
return 'Facebook API errored with ' . $body['type'] . ' (' . $body['code'] . ')';
}
return 'API errored with HTTP ' . $response->getResponse()->getStatusCode();
}
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\API\EventSubscriber;
use PrestaShop\Module\PrestashopFacebook\API\ParsedResponse;
interface SubscriberInterface
{
public function onParsedResponse(ParsedResponse $response, array $options): void;
}

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,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\PrestashopFacebook\API;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class FacebookCategoryClient
{
/**
* @var Client
*/
private $client;
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
GoogleCategoryRepository $googleCategoryRepository,
ErrorHandler $errorHandler
) {
$this->client = $apiClientFactory->createClient();
$this->googleCategoryRepository = $googleCategoryRepository;
$this->errorHandler = $errorHandler;
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId)
{
$googleCategoryId = $this->googleCategoryRepository->getGoogleCategoryIdByCategoryId($categoryId, $shopId);
if (empty($googleCategoryId)) {
return null;
}
$googleCategory = $this->get('taxonomy/' . $googleCategoryId);
if (!is_array($googleCategory)) {
return null;
}
return reset($googleCategory);
}
protected function get($id, array $fields = [], array $query = [])
{
$query = array_merge(
[
'fields' => implode(',', $fields),
],
$query
);
try {
$request = $this->client->createRequest(
'GET',
"/{$id}",
[
'query' => $query,
]
);
$response = $this->client->send($request);
} catch (ClientException $e) {
$exceptionContent = json_decode($e->getResponse()->getBody()->getContents(), true);
$this->errorHandler->handle(
new FacebookClientException(
'Facebook category client failed when creating get request.',
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false,
[
'extra' => $exceptionContent,
]
);
return false;
} catch (Exception $e) {
$this->errorHandler->handle(
new FacebookClientException(
'Facebook category client failed when creating get request.',
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return json_decode($response->getBody()->getContents(), true);
}
}

View File

@@ -0,0 +1,476 @@
<?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\PrestashopFacebook\API;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Ad;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\FacebookBusinessManager;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Page;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Pixel;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\User;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Handler\ConfigurationHandler;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
use PrestaShop\Module\PrestashopFacebook\Provider\AccessTokenProvider;
class FacebookClient
{
/**
* @var string
*/
private $accessToken;
/**
* @var string
*/
private $sdkVersion;
/**
* @var Client
*/
private $client;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var ConfigurationHandler
*/
private $configurationHandler;
/**
* @param ApiClientFactoryInterface $apiClientFactory
* @param AccessTokenProvider $accessTokenProvider
* @param ConfigurationAdapter $configurationAdapter
* @param ErrorHandler $errorHandler
* @param ConfigurationHandler $configurationHandler
*/
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
AccessTokenProvider $accessTokenProvider,
ConfigurationAdapter $configurationAdapter,
ErrorHandler $errorHandler,
ConfigurationHandler $configurationHandler
) {
$this->accessToken = $accessTokenProvider->getUserAccessToken();
$this->sdkVersion = Config::API_VERSION;
$this->client = $apiClientFactory->createClient();
$this->configurationAdapter = $configurationAdapter;
$this->errorHandler = $errorHandler;
$this->configurationHandler = $configurationHandler;
}
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}
/**
* @return bool
*/
public function hasAccessToken()
{
return (bool) $this->accessToken;
}
public function getUserEmail()
{
$responseContent = $this->get('me', __FUNCTION__, ['email']);
return new User(
isset($responseContent['email']) ? $responseContent['email'] : null
);
}
/**
* @param string $businessManagerId
*
* @return FacebookBusinessManager
*/
public function getBusinessManager($businessManagerId)
{
$responseContent = $this->get($businessManagerId, __FUNCTION__, ['name', 'created_time']);
return new FacebookBusinessManager(
isset($responseContent['id']) ? $responseContent['id'] : $businessManagerId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
/**
* @param string $adId
* @param string $pixelId
*
* @see https://developers.facebook.com/docs/marketing-api/reference/ad-account/adspixels/?locale=en_US
*
* @return Pixel
*/
public function getPixel($adId, $pixelId)
{
$name = $lastFiredTime = null;
$isUnavailable = false;
if (!empty($adId)) {
$responseContent = $this->get('act_' . $adId . '/adspixels', __FUNCTION__, ['name', 'last_fired_time', 'is_unavailable']);
if (isset($responseContent['data'])) {
foreach ($responseContent['data'] as $adPixel) {
if ($adPixel['id'] !== $pixelId) {
continue;
}
$name = isset($adPixel['name']) ? $adPixel['name'] : null;
$lastFiredTime = isset($adPixel['last_fired_time']) ? $adPixel['last_fired_time'] : null;
$isUnavailable = isset($adPixel['is_unavailable']) ? $adPixel['is_unavailable'] : null;
}
}
}
return new Pixel(
$pixelId,
$name,
$lastFiredTime,
$isUnavailable,
(bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PIXEL_ENABLED)
);
}
/**
* @param array $pageIds
*
* @return Page
*/
public function getPage(array $pageIds)
{
$pageId = reset($pageIds);
$responseContent = $this->get($pageId, __FUNCTION__, ['name', 'fan_count']);
$logoResponse = $this->get($pageId . '/photos', __FUNCTION__ . 'Photo', ['picture']);
$logo = null;
if (is_array($logoResponse)) {
$logo = reset($logoResponse['data'])['picture'];
}
return new Page(
isset($responseContent['id']) ? $responseContent['id'] : $pageIds,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['fan_count']) ? $responseContent['fan_count'] : null,
$logo
);
}
/**
* @param string $adId
*
* @return Ad
*/
public function getAd($adId)
{
$responseContent = $this->get('act_' . $adId, __FUNCTION__, ['name', 'created_time']);
return new Ad(
isset($responseContent['id']) ? $responseContent['id'] : $adId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
public function getFbeAttribute($externalBusinessId)
{
$responseContent = $this->get(
'fbe_business/fbe_installs',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
return reset($responseContent['data']);
}
public function getFbeFeatures($externalBusinessId)
{
$response = $this->get(
'fbe_business',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
if (!is_array($response)) {
return [];
}
return $response;
}
public function updateFeature($externalBusinessId, $configuration)
{
$body = [
'fbe_external_business_id' => $externalBusinessId,
'business_config' => $configuration,
];
return $this->post(
'fbe_business',
[],
$body
);
}
/**
* @see https://developers.facebook.com/docs/marketing-api/fbe/fbe2/guides/uninstall?locale=en_US#uninstall-fbe--v2-for-businesses
*
* @return false|array
*/
public function uninstallFbe()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$accessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$this->configurationHandler->cleanOnboardingConfiguration();
$this->accessToken = '';
$body = [
'fbe_external_business_id' => $externalBusinessId,
'access_token' => $accessToken,
];
return $this->delete(
'fbe_business/fbe_installs',
[],
$body
);
}
/**
* @param int $catalogId
*
* @return array|false
*/
public function getProductsInCatalogCount($catalogId)
{
$body = [
'fields' => 'product_count',
];
return $this->post(
$catalogId,
[],
$body
);
}
public function disconnectFromFacebook()
{
$this->uninstallFbe();
$this->configurationHandler->cleanOnboardingConfiguration();
}
public function addFbeAttributeIfMissing(array &$onboardingParams)
{
if (!empty($onboardingParams['fbe']) && !isset($onboardingParams['fbe']['error'])) {
return;
}
$this->setAccessToken($onboardingParams['access_token']);
$onboardingParams['fbe'] = $this->getFbeAttribute($this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID));
}
/**
* @param string $id
* @param string $method
* @param array $fields
* @param array $query
*
* @return false|array
*
* @throws Exception
*/
private function get($id, $method, array $fields = [], array $query = [])
{
$query = array_merge(
[
'access_token' => $this->accessToken,
'fields' => implode(',', $fields),
],
$query
);
try {
$request = $this->client->createRequest(
'GET',
"/{$this->sdkVersion}/{$id}",
[
'query' => $query,
]
);
$response = $this->client->send($request);
} catch (ClientException $e) {
$exceptionContent = json_decode($e->getResponse()->getBody()->getContents(), true);
$message = "Facebook client failed when creating get request. Method: {$method}.";
$exceptionCode = false;
if (!empty($exceptionContent['error']['code'])) {
$exceptionCode = $exceptionContent['error']['code'];
$message .= " Code: {$exceptionCode}";
}
if ($exceptionCode && in_array($exceptionCode, Config::OAUTH_EXCEPTION_CODE)) {
$this->disconnectFromFacebook();
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_FORCED_DISCONNECT, true);
return false;
}
$this->errorHandler->handle(
new FacebookClientException(
$message,
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false,
[
'extra' => $exceptionContent,
]
);
return false;
} catch (Exception $e) {
$this->errorHandler->handle(
new FacebookClientException(
'Facebook client failed when creating get request. Method: ' . $method,
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return json_decode($response->getBody()->getContents(), true);
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function post($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'POST');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function delete($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'DELETE');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
* @param string $method
*
* @return false|array
*/
private function sendRequest($id, array $headers, array $body, $method)
{
$options = [
'headers' => $headers,
'body' => array_merge(
[
'access_token' => $this->accessToken,
],
$body
),
];
try {
$request = $this->client->createRequest(
$method,
"/{$this->sdkVersion}/{$id}",
$options
);
$response = $this->client->send($request);
} catch (ClientException $e) {
$exceptionContent = json_decode($e->getResponse()->getBody()->getContents(), true);
$this->errorHandler->handle(
new FacebookClientException(
'Facebook client failed when creating post request.',
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false,
[
'extra' => $exceptionContent,
]
);
return false;
} catch (Exception $e) {
$this->errorHandler->handle(
new FacebookClientException(
'Facebook client failed when creating post request.',
FacebookClientException::FACEBOOK_CLIENT_POST_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return json_decode($response->getBody()->getContents(), true);
}
}

View File

@@ -0,0 +1,79 @@
<?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\PrestashopFacebook\API;
use Psr\Http\Message\ResponseInterface;
class ParsedResponse
{
/**
* @var ResponseInterface
*/
private $response;
private $body;
public function __construct(ResponseInterface $response)
{
$this->body = json_decode($response->getBody()->getContents(), true);
$this->response = $response;
}
/**
* @return mixed
*/
public function getBody()
{
return $this->body;
}
public function getResponse(): ResponseInterface
{
return $this->response;
}
public function isSuccessful(): bool
{
return $this->responseIsSuccessful($this->response->getStatusCode());
}
public function toArray(): array
{
$responseContents = $this->body;
return [
'isSuccessful' => $this->isSuccessful(),
'httpCode' => $this->response->getStatusCode(),
'body' => $responseContents,
];
}
/**
* Check if the response is successful or not (response code 200 to 299).
*
* @param int $httpStatusCode
*
* @return bool
*/
private function responseIsSuccessful($httpStatusCode)
{
return '2' === substr((string) $httpStatusCode, 0, 1);
}
}

View File

@@ -0,0 +1,56 @@
<?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\PrestashopFacebook\API;
use PrestaShop\Module\PrestashopFacebook\API\EventSubscriber\SubscriberInterface;
use Psr\Http\Message\ResponseInterface;
class ResponseListener
{
/**
* @var array<SubscriberInterface>
*/
private $subscribers;
public function __construct(array $subscribers)
{
$this->subscribers = $subscribers;
}
/**
* Format api response.
*
* @return ParsedResponse
*/
public function handleResponse(ResponseInterface $response, array $options = [])
{
$parsedResponse = new ParsedResponse($response);
/*
* @var SubscriberInterface
*/
foreach ($this->subscribers as $subscriber) {
$subscriber->onParsedResponse($parsedResponse, $options);
}
return $parsedResponse;
}
}

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,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\PrestashopFacebook\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,36 @@
<?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\PrestashopFacebook\Adapter;
use Tools;
class ToolsAdapter
{
public function getValue($id)
{
return Tools::getValue($id);
}
public function isSubmit($id)
{
return Tools::isSubmit($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,64 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Buffer;
class TemplateBuffer
{
/**
* @var string
*/
private $data;
/**
* add data to the buffer
*
* @param string $data
*
* @return void
*/
public function add($data)
{
$this->data .= $data;
}
/**
* reset buffer content
*
* @return void
*/
public function clean()
{
$this->data = '';
}
/**
* return buffer content and reset it
*
* @return string
*/
public function flush()
{
$returnedData = $this->data;
$this->clean();
return !empty($returnedData) ? $returnedData : '';
}
}

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,71 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Config;
class Config
{
public const API_VERSION = 'v14.0';
public const COMPLIANT_PS_ACCOUNTS_VERSION = '3.0.0';
public const REQUIRED_PS_ACCOUNTS_VERSION = '4.0.0';
public const REQUIRED_PS_EVENTBUS_VERSION = '1.3.3';
public const USE_LOCAL_VUE_APP = false;
public const PSX_FACEBOOK_CDN_URL = 'https://storage.googleapis.com/psxfacebook/v1.x.x/js/';
public const PS_PIXEL_ID = 'PS_FACEBOOK_PIXEL_ID';
public const PS_FACEBOOK_USER_ACCESS_TOKEN = 'PS_FACEBOOK_ACCESS_TOKEN';
public const PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE = 'PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE';
public const PS_FACEBOOK_SYSTEM_ACCESS_TOKEN = 'PS_FACEBOOK_SYSTEM_ACCESS_TOKEN';
public const PS_FACEBOOK_PROFILES = 'PS_FACEBOOK_PROFILES';
public const PS_FACEBOOK_PAGES = 'PS_FACEBOOK_PAGES';
public const PS_FACEBOOK_BUSINESS_MANAGER_ID = 'PS_FACEBOOK_BUSINESS_MANAGER_ID';
public const PS_FACEBOOK_AD_ACCOUNT_ID = 'PS_FACEBOOK_AD_ACCOUNT_ID';
public const PS_FACEBOOK_CATALOG_ID = 'PS_FACEBOOK_CATALOG_ID';
public const PS_FACEBOOK_EXTERNAL_BUSINESS_ID = 'PS_FACEBOOK_EXTERNAL_BUSINESS_ID';
public const PS_FACEBOOK_PIXEL_ENABLED = 'PS_FACEBOOK_PIXEL_ENABLED';
public const PS_FACEBOOK_CAPI_TEST_EVENT_CODE = 'PS_FACEBOOK_CAPI_TEST_EVENT_CODE';
public const PS_FACEBOOK_PRODUCT_SYNC_FIRST_START = 'PS_FACEBOOK_PRODUCT_SYNC_FIRST_START';
public const PS_FACEBOOK_PRODUCT_SYNC_ON = 'PS_FACEBOOK_PRODUCT_SYNC_ON';
public const AVAILABLE_FBE_FEATURES = ['messenger_chat', 'page_cta', 'page_shop'/*, 'ig_shopping'*/];
public const FBE_FEATURES_REQUIRING_PRODUCT_SYNC = ['page_shop', 'ig_shopping'];
public const FBE_FEATURE_CONFIGURATION = 'PS_FACEBOOK_FBE_FEATURE_CONFIG_';
public const CATEGORIES_PER_PAGE = 50;
public const MAX_CATEGORY_DEPTH = 3;
public const REPORTS_PER_PAGE = 1000;
// Data that can be overwritten by .env file if using the Env class
public const PSX_FACEBOOK_API_URL = 'https://facebook-api.psessentials.net';
public const PSX_FACEBOOK_UI_URL = 'https://facebook.psessentials.net';
public const PSX_FACEBOOK_APP_ID = '726899634800479';
public const PSX_FACEBOOK_SENTRY_CREDENTIALS = 'https://4252ed38f42f4f7285c7932337fe77a2@o298402.ingest.sentry.io/5531852';
public const PSX_FACEBOOK_SEGMENT_API_KEY = 'vgBkyeNDK7tQwgxrxoVUGRMNGTUATiPw';
/** @see https://developers.facebook.com/docs/marketing-api/error-reference */
public const OAUTH_EXCEPTION_CODE = [33, 190];
public const PS_FACEBOOK_CAPI_PARTNER_AGENT = 'prestashop';
public const PS_FACEBOOK_FORCED_DISCONNECT = 'PS_FACEBOOK_FORCED_DISCONNECT';
public const PS_FACEBOOK_SUSPENSION_REASON = 'PS_FACEBOOK_SUSPENSION_REASON';
}

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\PrestashopFacebook\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,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,346 @@
<?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\PrestashopFacebook\DTO;
use JsonSerializable;
class ConfigurationData implements JsonSerializable
{
/**
* @var array
*/
private $contextPsAccounts;
/**
* @var ContextPsFacebook
*/
private $contextPsFacebook;
/**
* @var string
*/
private $psFacebookExternalBusinessId;
/**
* @var string
*/
private $psAccountsToken;
/**
* @var string
*/
private $psFacebookCurrency;
/**
* @var string
*/
private $psFacebookTimezone;
/**
* @var string
*/
private $psFacebookLocale;
/**
* @var string
*/
private $psFacebookPixelActivationRoute;
/**
* @var string
*/
private $psFacebookFbeOnboardingSaveRoute;
/**
* @var string
*/
private $psFacebookFbeUiUrl;
/**
* @var string
*/
private $isoCode;
/**
* @var string
*/
private $languageCode;
/**
* @return array
*/
public function getContextPsAccounts()
{
return $this->contextPsAccounts;
}
/**
* @param array $contextPsAccounts
*
* @return ConfigurationData
*/
public function setContextPsAccounts($contextPsAccounts)
{
$this->contextPsAccounts = $contextPsAccounts;
return $this;
}
/**
* @return ContextPsFacebook
*/
public function getContextPsFacebook()
{
return $this->contextPsFacebook;
}
/**
* @param ContextPsFacebook $contextPsFacebook
*
* @return ConfigurationData
*/
public function setContextPsFacebook($contextPsFacebook)
{
$this->contextPsFacebook = $contextPsFacebook;
return $this;
}
/**
* @return string
*/
public function getPsFacebookExternalBusinessId()
{
return $this->psFacebookExternalBusinessId;
}
/**
* @param string $psFacebookExternalBusinessId
*
* @return ConfigurationData
*/
public function setPsFacebookExternalBusinessId($psFacebookExternalBusinessId)
{
$this->psFacebookExternalBusinessId = $psFacebookExternalBusinessId;
return $this;
}
/**
* @return string
*/
public function getPsAccountsToken()
{
return $this->psAccountsToken;
}
/**
* @param string $psAccountsToken
*
* @return ConfigurationData
*/
public function setPsAccountsToken($psAccountsToken)
{
$this->psAccountsToken = $psAccountsToken;
return $this;
}
/**
* @return string
*/
public function getPsFacebookCurrency()
{
return $this->psFacebookCurrency;
}
/**
* @param string $psFacebookCurrency
*
* @return ConfigurationData
*/
public function setPsFacebookCurrency($psFacebookCurrency)
{
$this->psFacebookCurrency = $psFacebookCurrency;
return $this;
}
/**
* @return string
*/
public function getPsFacebookTimezone()
{
return $this->psFacebookTimezone;
}
/**
* @param string $psFacebookTimezone
*
* @return ConfigurationData
*/
public function setPsFacebookTimezone($psFacebookTimezone)
{
$this->psFacebookTimezone = $psFacebookTimezone;
return $this;
}
/**
* @return string
*/
public function getPsFacebookLocale()
{
return $this->psFacebookLocale;
}
/**
* @param string $psFacebookLocale
*
* @return ConfigurationData
*/
public function setPsFacebookLocale($psFacebookLocale)
{
$this->psFacebookLocale = $psFacebookLocale;
return $this;
}
/**
* @return string
*/
public function getPsFacebookPixelActivationRoute()
{
return $this->psFacebookPixelActivationRoute;
}
/**
* @param string $psFacebookPixelActivationRoute
*
* @return ConfigurationData
*/
public function setPsFacebookPixelActivationRoute($psFacebookPixelActivationRoute)
{
$this->psFacebookPixelActivationRoute = $psFacebookPixelActivationRoute;
return $this;
}
/**
* @return string
*/
public function getPsFacebookFbeOnboardingSaveRoute()
{
return $this->psFacebookFbeOnboardingSaveRoute;
}
/**
* @param string $psFacebookFbeOnboardingSaveRoute
*
* @return ConfigurationData
*/
public function setPsFacebookFbeOnboardingSaveRoute($psFacebookFbeOnboardingSaveRoute)
{
$this->psFacebookFbeOnboardingSaveRoute = $psFacebookFbeOnboardingSaveRoute;
return $this;
}
/**
* @return string
*/
public function getPsFacebookFbeUiUrl()
{
return $this->psFacebookFbeUiUrl;
}
/**
* @param string $psFacebookFbeUiUrl
*
* @return ConfigurationData
*/
public function setPsFacebookFbeUiUrl($psFacebookFbeUiUrl)
{
$this->psFacebookFbeUiUrl = $psFacebookFbeUiUrl;
return $this;
}
/**
* @return string
*/
public function getIsoCode()
{
return $this->isoCode;
}
/**
* @param string $isoCode
*
* @return ConfigurationData
*/
public function setIsoCode($isoCode)
{
$this->isoCode = $isoCode;
return $this;
}
/**
* @return string
*/
public function getLanguageCode()
{
return $this->languageCode;
}
/**
* @param string $languageCode
*
* @return ConfigurationData
*/
public function setLanguageCode($languageCode)
{
$this->languageCode = $languageCode;
return $this;
}
public function jsonSerialize()
{
return [
'contextPsAccounts' => $this->getContextPsAccounts(),
'contextPsFacebook' => $this->getContextPsFacebook(),
'psFacebookExternalBusinessId' => $this->getPsFacebookExternalBusinessId(),
'psAccountsToken' => $this->getPsAccountsToken(),
'psFacebookCurrency' => $this->getPsFacebookCurrency(),
'psFacebookTimezone' => $this->getPsFacebookTimezone(),
'psFacebookLocale' => $this->getPsFacebookLocale(),
'psFacebookPixelActivationRoute' => $this->getPsFacebookPixelActivationRoute(),
'psFacebookFbeOnboardingSaveRoute' => $this->getPsFacebookFbeOnboardingSaveRoute(),
'psFacebookFbeUiUrl' => $this->getPsFacebookFbeUiUrl(),
'i18nSettings' => [
'isoCode' => $this->getIsoCode(),
'languageLocale' => $this->getLanguageCode(),
],
];
}
}

View File

@@ -0,0 +1,214 @@
<?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\PrestashopFacebook\DTO;
use JsonSerializable;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Ad;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Catalog;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\FacebookBusinessManager;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Page;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Pixel;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\User;
class ContextPsFacebook implements JsonSerializable
{
/**
* @var User
*/
private $user;
/**
* @var FacebookBusinessManager|null
*/
private $facebookBusinessManager;
/**
* @var Pixel|null
*/
private $pixel;
/**
* @var Page|null
*/
private $page;
/**
* @var Ad|null
*/
private $ad;
/**
* @var Catalog|null
*/
private $catalog;
/**
* ContextPsFacebook constructor.
*
* @param User $user
* @param FacebookBusinessManager|null $facebookBusinessManager
* @param Pixel|null $pixel
* @param Page|null $page
* @param Ad|null $ad
* @param Catalog|null $catalog
*/
public function __construct($user, $facebookBusinessManager, $pixel, $page, $ad, $catalog)
{
$this->user = $user;
$this->facebookBusinessManager = $facebookBusinessManager;
$this->pixel = $pixel;
$this->page = $page;
$this->ad = $ad;
$this->catalog = $catalog;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param User $user
*
* @return ContextPsFacebook
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* @return FacebookBusinessManager|null
*/
public function getFacebookBusinessManager()
{
return $this->facebookBusinessManager;
}
/**
* @param FacebookBusinessManager|null $facebookBusinessManager
*
* @return ContextPsFacebook
*/
public function setFacebookBusinessManager($facebookBusinessManager)
{
$this->facebookBusinessManager = $facebookBusinessManager;
return $this;
}
/**
* @return Pixel|null
*/
public function getPixel()
{
return $this->pixel;
}
/**
* @param Pixel|null $pixel
*
* @return ContextPsFacebook
*/
public function setPixel($pixel)
{
$this->pixel = $pixel;
return $this;
}
/**
* @return Page|null
*/
public function getPage()
{
return $this->page;
}
/**
* @param Page|null $page
*
* @return ContextPsFacebook
*/
public function setPage($page)
{
$this->page = $page;
return $this;
}
/**
* @return Ad|null
*/
public function getAd()
{
return $this->ad;
}
/**
* @param Ad|null $ad
*
* @return ContextPsFacebook
*/
public function setAd($ad)
{
$this->ad = $ad;
return $this;
}
/**
* @return Catalog|null
*/
public function getCatalog()
{
return $this->catalog;
}
/**
* @param Catalog|null $catalog
*
* @return ContextPsFacebook
*/
public function setCatalog($catalog)
{
$this->catalog = $catalog;
return $this;
}
public function jsonSerialize()
{
return [
'user' => $this->getUser(),
'pixel' => $this->getPixel(),
'facebookBusinessManager' => $this->getFacebookBusinessManager(),
'page' => $this->getPage(),
'ads' => $this->getAd(),
'catalog' => $this->getCatalog(),
];
}
}

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\PrestashopFacebook\DTO;
class EventBusProduct
{
public const POSITION_PRODUCT_ID = 0;
public const POSITION_PRODUCT_ATTRIBUTE_ID = 1;
/**
* @var int
*/
private $productId;
/**
* @var int
*/
private $productAttributeId;
/**
* @return int
*/
public function getProductId()
{
return $this->productId;
}
/**
* @param int $productId
*
* @return EventBusProduct
*/
public function setProductId($productId)
{
$this->productId = $productId;
return $this;
}
/**
* @return int
*/
public function getProductAttributeId()
{
return $this->productAttributeId;
}
/**
* @param int $productAttributeId
*
* @return EventBusProduct
*/
public function setProductAttributeId($productAttributeId)
{
$this->productAttributeId = $productAttributeId;
return $this;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\DTO\Object;
use JsonSerializable;
class Ad implements JsonSerializable
{
/**
* @var string
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $createdAt;
/**
* @param string $id
* @param string $name
* @param string $createdAt
*/
public function __construct($id, $name, $createdAt)
{
$this->id = $id;
$this->name = $name;
$this->createdAt = $createdAt;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return string
*/
public function getCreatedAt()
{
return $this->createdAt;
}
public function jsonSerialize()
{
return [
'id' => $this->getId(),
'name' => $this->getName(),
'createdAt' => $this->getCreatedAt(),
];
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\DTO\Object;
use JsonSerializable;
class Catalog implements JsonSerializable
{
/**
* @var string
*/
private $id;
/**
* @var bool
*/
private $productSyncStarted;
/**
* @var bool
*/
private $categoryMatchingStarted;
/**
* Page constructor.
*
* @param string $id
*/
public function __construct($id, $productSyncStarted, $categoryMatchingStarted)
{
$this->id = $id;
$this->productSyncStarted = $productSyncStarted;
$this->categoryMatchingStarted = $categoryMatchingStarted;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return bool
*/
public function getProductSyncStarted()
{
return $this->productSyncStarted;
}
/**
* @return bool
*/
public function getCategoryMatchingStarted()
{
return $this->categoryMatchingStarted;
}
public function jsonSerialize()
{
return [
'id' => $this->getId(),
'productSyncStarted' => $this->getProductSyncStarted(),
'categoryMatchingStarted' => $this->getCategoryMatchingStarted(),
];
}
}

View File

@@ -0,0 +1,88 @@
<?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\PrestashopFacebook\DTO\Object;
use JsonSerializable;
class FacebookBusinessManager implements JsonSerializable
{
/**
* @var string
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var int
*/
private $createdAt;
/**
* FacebookBusinessManager constructor.
*
* @param string $id
* @param string $name
* @param int $createdAt
*/
public function __construct($id, $name, $createdAt)
{
$this->id = $id;
$this->name = $name;
$this->createdAt = $createdAt;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return int
*/
public function getCreatedAt()
{
return $this->createdAt;
}
public function jsonSerialize()
{
return [
'id' => $this->getId(),
'name' => $this->getName(),
'createDate' => $this->getCreatedAt(),
];
}
}

View File

@@ -0,0 +1,103 @@
<?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\PrestashopFacebook\DTO\Object;
use JsonSerializable;
class Page implements JsonSerializable
{
/**
* @var string
*/
private $id;
/**
* @var string
*/
private $page;
/**
* @var int|null
*/
private $likes;
/**
* @var string|null
*/
private $logo;
/**
* Page constructor.
*
* @param string $page
* @param int|null $likes
* @param string|null $logo
*/
public function __construct($id, $page, $likes, $logo)
{
$this->id = $id;
$this->page = $page;
$this->likes = $likes;
$this->logo = $logo;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getPage()
{
return $this->page;
}
/**
* @return int|null
*/
public function getLikes()
{
return $this->likes;
}
/**
* @return string|null
*/
public function getLogo()
{
return $this->logo;
}
public function jsonSerialize()
{
return [
'id' => $this->getId(),
'page' => $this->getPage(),
'likes' => $this->getLikes(),
'logo' => $this->getLogo(),
];
}
}

View File

@@ -0,0 +1,120 @@
<?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\PrestashopFacebook\DTO\Object;
use JsonSerializable;
class Pixel implements JsonSerializable
{
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $id;
/**
* @var string
*/
private $lastActive;
/**
* @var bool
*/
private $isUnavailable;
/**
* @var bool
*/
private $isActive;
/**
* Pixel constructor.
*
* @param string $id
* @param string $name
* @param string $lastActive
* @param bool $isUnavailable
* @param bool $isActive
*/
public function __construct($id, $name, $lastActive, $isUnavailable, $isActive)
{
$this->id = $id;
$this->name = $name;
$this->lastActive = $lastActive;
$this->isUnavailable = $isUnavailable;
$this->isActive = $isActive;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getLastActive()
{
return $this->lastActive;
}
/**
* @return bool
*/
public function isUnavailable()
{
return $this->isUnavailable;
}
/**
* @return bool
*/
public function isActive()
{
return $this->isActive;
}
public function jsonSerialize()
{
return [
'id' => $this->getId(),
'name' => $this->getName(),
'lastActive' => $this->getLastActive(),
'isUnavailable' => $this->isUnavailable(),
'isActive' => $this->isActive(),
];
}
}

View File

@@ -0,0 +1,51 @@
<?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\PrestashopFacebook\DTO\Object;
use JsonSerializable;
class User implements JsonSerializable
{
/**
* @var string|null
*/
private $email;
public function __construct($email)
{
$this->email = $email;
}
/**
* @return string|null
*/
public function getEmail()
{
return $this->email;
}
public function jsonSerialize()
{
return [
'email' => $this->getEmail(),
];
}
}

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
*/
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,237 @@
<?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\PrestashopFacebook\Database;
use Exception;
use Language;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookInstallerException;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
use PrestaShop\Module\Ps_facebook\Tracker\Segment;
use Tab;
class Installer
{
public const CLASS_NAME = 'Installer';
public const CONFIGURATION_LIST = [
Config::PS_PIXEL_ID,
Config::PS_FACEBOOK_USER_ACCESS_TOKEN,
Config::PS_FACEBOOK_PROFILES,
Config::PS_FACEBOOK_PAGES,
Config::PS_FACEBOOK_BUSINESS_MANAGER_ID,
Config::PS_FACEBOOK_AD_ACCOUNT_ID,
Config::PS_FACEBOOK_CATALOG_ID,
Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID,
Config::PS_FACEBOOK_PIXEL_ENABLED,
Config::PS_FACEBOOK_PRODUCT_SYNC_FIRST_START,
Config::PS_FACEBOOK_PRODUCT_SYNC_ON,
];
private $module;
/**
* @var array
*/
private $errors = [];
/**
* @var Segment
*/
private $segment;
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(\Ps_facebook $module, Segment $segment, ErrorHandler $errorHandler)
{
$this->module = $module;
$this->segment = $segment;
$this->errorHandler = $errorHandler;
}
/**
* @return bool
*/
public function install()
{
$this->segment->setMessage('PS Facebook 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) {
foreach (self::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 FacebookInstallerException(
'Failed to install module tabs',
FacebookInstallerException::FACEBOOK_INSTALL_EXCEPTION,
$e
),
FacebookInstallerException::FACEBOOK_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 FacebookInstallerException(
'Failed to install database tables',
FacebookInstallerException::FACEBOOK_INSTALL_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' => 'AdminPsfacebookModule',
'parent' => 'Marketing',
'name' => 'Facebook',
'module' => $this->module->name,
'active' => true,
'icon' => '',
],
[
'className' => 'AdminAjaxPsfacebook',
'parent' => -1,
'name' => $this->module->name,
'module' => $this->module->name,
'active' => true,
'icon' => '',
],
];
}
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Database;
use Exception;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookInstallerException;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
use PrestaShop\Module\PrestashopFacebook\Repository\TabRepository;
use PrestaShop\Module\Ps_facebook\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;
/**
* @var FacebookClient
*/
private $facebookClient;
public function __construct(
\Ps_facebook $module,
TabRepository $tabRepository,
Segment $segment,
ErrorHandler $errorHandler,
FacebookClient $facebookClient
) {
$this->module = $module;
$this->tabRepository = $tabRepository;
$this->segment = $segment;
$this->errorHandler = $errorHandler;
$this->facebookClient = $facebookClient;
}
/**
* @return bool
*
* @throws Exception
*/
public function uninstall()
{
$this->segment->setMessage('PS Facebook uninstalled');
$this->segment->track();
foreach (array_keys(Installer::CONFIGURATION_LIST) as $name) {
\Configuration::deleteByName((string) $name);
}
$this->facebookClient->uninstallFbe();
return $this->uninstallTabs() && $this->uninstallTables();
}
/**
* @return bool
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException|Exception
*/
private function uninstallTabs()
{
$uninstallTabCompleted = true;
try {
foreach (\Ps_facebook::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 FacebookInstallerException(
'Failed to uninstall module tabs',
FacebookInstallerException::FACEBOOK_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 FacebookInstallerException(
'Failed to uninstall database tables',
FacebookInstallerException::FACEBOOK_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,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,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\PrestashopFacebook\Dispatcher;
use Context;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Handler\ApiConversionHandler;
use PrestaShop\Module\PrestashopFacebook\Handler\PixelHandler;
use PrestaShop\Module\PrestashopFacebook\Provider\EventDataProvider;
class EventDispatcher
{
/**
* @var ApiConversionHandler
*/
private $conversionHandler;
/**
* @var PixelHandler
*/
private $pixelHandler;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var EventDataProvider
*/
private $eventDataProvider;
/**
* @var Context
*/
private $context;
public function __construct(
ApiConversionHandler $apiConversionHandler,
PixelHandler $pixelHandler,
ConfigurationAdapter $configurationAdapter,
EventDataProvider $eventDataProvider,
Context $context
) {
$this->conversionHandler = $apiConversionHandler;
$this->pixelHandler = $pixelHandler;
$this->configurationAdapter = $configurationAdapter;
$this->eventDataProvider = $eventDataProvider;
$this->context = $context;
}
/**
* @param string $name
* @param array $params
*
* @return void
*/
public function dispatch($name, array $params)
{
// Events are related to actions on the shop, not the back office
/** @var \Controller|null $controller */
$controller = $this->context->controller;
if (!$controller || !in_array($controller->controller_type, ['front', 'modulefront'])) {
return;
}
if (false === (bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PIXEL_ENABLED)) {
return;
}
$eventData = $this->eventDataProvider->generateEventData($name, $params);
if ($eventData) {
$this->conversionHandler->handleEvent($eventData);
}
$this->pixelHandler->handleEvent($eventData);
}
}

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,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\PrestashopFacebook\Exception;
use Exception;
class AccessTokenException extends Exception
{
public const ACCESS_TOKEN_REFRESH_EXCEPTION = 1;
public const ACCESS_TOKEN_RETRIEVE_EXCEPTION = 2;
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Exception;
use Exception;
class FacebookAccountException extends Exception
{
public const FACEBOOK_ACCOUNT_PRODUCT_SYNC_REPORTING_EXCEPTION = 1;
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Exception;
use Exception;
class FacebookCatalogExportException extends Exception
{
public const FACEBOOK_WHOLE_CATALOG_EXPORT_EXCEPTION = 1;
}

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\PrestashopFacebook\Exception;
use Exception;
class FacebookClientException extends Exception
{
public const FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION = 1;
public const FACEBOOK_CLIENT_POST_FUNCTION_EXCEPTION = 2;
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Exception;
use Exception;
class FacebookConversionAPIException extends Exception
{
public const SEND_EVENT_EXCEPTION = 1;
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Exception;
use Exception;
class FacebookDependencyUpdateException extends Exception
{
public const FACEBOOK_DEPENDENCY_UPGRADE_EXCEPTION = 1;
}

View File

@@ -0,0 +1,32 @@
<?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\PrestashopFacebook\Exception;
use Exception;
class FacebookInstallerException extends Exception
{
public const FACEBOOK_INSTALL_EXCEPTION = 1;
public const FACEBOOK_UNINSTALL_EXCEPTION = 2;
public const PS_ACCOUNTS_UPGRADE_EXCEPTION = 2;
}

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\PrestashopFacebook\Exception;
use Exception;
class FacebookOnboardException extends Exception
{
public const FACEBOOK_RETRIEVE_EXTERNAL_BUSINESS_ID_EXCEPTION = 1;
public const FACEBOOK_ONBOARD_EXCEPTION = 2;
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Exception;
use Exception;
class FacebookPrevalidationScanException extends Exception
{
public const FACEBOOK_PRE_VALIDATION_SCAN_UPDATE_EXCEPTION = 1;
}

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
*/
namespace PrestaShop\Module\PrestashopFacebook\Exception;
use Exception;
class FacebookProductSyncException extends Exception
{
public const FACEBOOK_PRODUCT_SYNC = 1;
}

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,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\PrestashopFacebook\Factory;
use Psr\Http\Client\ClientInterface;
interface ApiClientFactoryInterface
{
/**
* @return ClientInterface
*/
public function createClient();
}

View File

@@ -0,0 +1,40 @@
<?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\PrestashopFacebook\Factory;
use PrestaShop\ModuleLibCacheDirectoryProvider\Cache\CacheDirectoryProvider;
class CacheFactory
{
/**
* @return string
*/
public static function getCachePath()
{
$cacheDirectoryProvider = new CacheDirectoryProvider(
_PS_VERSION_,
_PS_ROOT_DIR_,
_PS_MODE_DEV_
);
return $cacheDirectoryProvider->getPath();
}
}

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\PrestashopFacebook\Factory;
use Context;
class ContextFactory
{
public static function getContext()
{
return Context::getContext();
}
public static function getLanguage()
{
return Context::getContext()->language;
}
public static function getCurrency()
{
return Context::getContext()->currency;
}
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;
}
}

View File

@@ -0,0 +1,49 @@
<?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\PrestashopFacebook\Factory;
use Prestashop\ModuleLibGuzzleAdapter\ClientFactory;
class FacebookEssentialsApiClientFactory implements ApiClientFactoryInterface
{
public const API_URL = 'https://graph.facebook.com';
/**
* @var ClientFactory
*/
private $clientFactory;
public function __construct(ClientFactory $clientFactory)
{
$this->clientFactory = $clientFactory;
}
public function createClient()
{
return $this->clientFactory->getClient([
'base_url' => self::API_URL,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]);
}
}

View File

@@ -0,0 +1,33 @@
<?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\PrestashopFacebook\Factory;
use GuzzleHttp\Client;
class GoogleCategoryEssentialsApiClientFactory implements ApiClientFactoryInterface
{
const API_URL = 'https://facebook-api.psessentials.net';
public function createClient()
{
return new Client(['base_url' => self::API_URL]);
}
}

View File

@@ -0,0 +1,72 @@
<?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\PrestashopFacebook\Factory;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
use Prestashop\ModuleLibGuzzleAdapter\ClientFactory;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class PsApiClientFactory implements ApiClientFactoryInterface
{
/**
* @var string
*/
private $baseUrl;
/**
* @var PsAccounts
*/
private $psAccountsFacade;
/**
* @var ClientFactory
*/
private $clientFactory;
public function __construct(
Env $env,
PsAccounts $psAccountsFacade,
ClientFactory $clientFactory
) {
$this->baseUrl = $env->get('PSX_FACEBOOK_API_URL');
$this->psAccountsFacade = $psAccountsFacade;
$this->clientFactory = $clientFactory;
}
/**
* {@inheritdoc}
*/
public function createClient()
{
$client = $this->clientFactory->getClient([
'base_url' => $this->baseUrl,
'timeout' => 10,
'verify' => false,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $this->psAccountsFacade->getPsAccountsService()->getOrRefreshToken(),
],
]);
return $client;
}
}

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,260 @@
<?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\PrestashopFacebook\Handler;
use FacebookAds\Api;
use FacebookAds\Http\Exception\AuthorizationException;
use FacebookAds\Object\ServerSide\ActionSource;
use FacebookAds\Object\ServerSide\Content;
use FacebookAds\Object\ServerSide\CustomData;
use FacebookAds\Object\ServerSide\Event;
use FacebookAds\Object\ServerSide\EventRequest;
use FacebookAds\Object\ServerSide\UserData;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookConversionAPIException;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
class ApiConversionHandler
{
/**
* @var false|string
*/
private $pixelId;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var FacebookClient
*/
private $facebookClient;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ErrorHandler $errorHandler,
FacebookClient $facebookClient
) {
$this->configurationAdapter = $configurationAdapter;
$this->errorHandler = $errorHandler;
$this->pixelId = $this->configurationAdapter->get(Config::PS_PIXEL_ID);
Api::init(
null, // app_id
null, // app_secret
$this->configurationAdapter->get(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN),
false
);
$this->facebookClient = $facebookClient;
}
public function handleEvent($params)
{
if (empty($this->pixelId)) {
return;
}
if (isset($params['event_type'])) {
$eventType = $params['event_type'];
}
if (isset($params['event_time'])) {
$eventTime = $params['event_time'];
}
if (isset($params['user'])) {
$userData = $params['user'];
}
if (isset($params['custom_data'])) {
$customData = $params['custom_data'];
}
if (isset($params['event_source_url'])) {
$eventSourceUrl = $params['event_source_url'];
}
if (isset($customData) && isset($customData['contents'])) {
$contentsData = $customData['contents'];
}
if (isset($contentsData)) {
$contents = [];
foreach ($contentsData as $contentData) {
$content = new Content();
if (isset($contentData['id'])) {
$content->setProductId($contentData['id']);
}
if (isset($contentData['title'])) {
$content->setTitle($contentData['title']);
}
if (isset($contentData['category'])) {
$content->setCategory($contentData['category']);
}
if (isset($contentData['item_price'])) {
$content->setItemPrice($contentData['item_price']);
}
if (isset($contentData['brand'])) {
$content->setBrand($contentData['brand']);
}
if (isset($contentData['quantity'])) {
$content->setQuantity($contentData['quantity']);
}
$contents[] = $content;
}
}
if (isset($userData)) {
$user = $this->createSdkUserData($userData);
}
if (isset($customData)) {
$customDataObj = new CustomData();
if (isset($customData['currency'])) {
$customDataObj->setCurrency($customData['currency']);
}
/* more about value here: https://www.facebook.com/business/help/392174274295227?id=1205376682832142 */
if (isset($customData['value'])) {
$customDataObj->setValue($customData['value']);
}
if (isset($contents)) {
$customDataObj->setContents($contents);
}
if (isset($customData['content_type'])) {
$customDataObj->setContentType($customData['content_type']);
}
if (isset($customData['content_name'])) {
$customDataObj->setContentName($customData['content_name']);
}
if (isset($customData['content_category'])) {
$customDataObj->setContentCategory($customData['content_category']);
}
if (isset($customData['content_type'])) {
$customDataObj->setContentType($customData['content_type']);
}
if (isset($customData['content_ids'])) {
$customDataObj->setContentIds($customData['content_ids']);
}
if (isset($customData['num_items'])) {
$customDataObj->setNumItems($customData['num_items']);
}
if (isset($customData['order_id'])) {
$customDataObj->setOrderId($customData['order_id']);
}
if (isset($customData['search_string'])) {
$customDataObj->setSearchString($customData['search_string']);
}
if (isset($customData['custom_properties'])) {
$customDataObj->setCustomProperties($customData['custom_properties']);
}
}
$event = new Event();
if (isset($eventType)) {
$event->setEventName($eventType);
}
if (isset($eventTime)) {
$event->setEventTime($eventTime);
}
if (isset($user)) {
$event->setUserData($user);
}
if (isset($customDataObj)) {
$event->setCustomData($customDataObj);
}
if (isset($eventSourceUrl)) {
$event->setEventSourceUrl($eventSourceUrl);
}
if (isset($params['eventID'])) {
$event->setEventId($params['eventID']);
}
$event->setActionSource(ActionSource::WEBSITE);
$this->sendEvents([$event]);
}
/**
* @return UserData
*/
protected function createSdkUserData($customerInformation)
{
// \Context::getContext()->cookie doesn't have fbp and fbc
$fbp = isset($_COOKIE['_fbp']) ? $_COOKIE['_fbp'] : '';
$fbc = isset($_COOKIE['_fbc']) ? $_COOKIE['_fbc'] : '';
$httpUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
$remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
return (new UserData())
->setFbp($fbp)
->setFbc($fbc)
->setClientIpAddress($remoteAddr)
->setClientUserAgent($httpUserAgent)
->setEmail($customerInformation['email'])
->setFirstName($customerInformation['firstname'])
->setLastName($customerInformation['lastname'])
->setPhone($customerInformation['phone'])
->setDateOfBirth($customerInformation['birthday'])
->setCity($customerInformation['city'])
->setState($customerInformation['stateIso'])
->setZipCode($customerInformation['postCode'])
->setCountryCode($customerInformation['countryIso'])
->setGender($customerInformation['gender']);
}
protected function sendEvents(array $events)
{
$request = (new EventRequest($this->pixelId))
->setEvents($events)
->setPartnerAgent(Config::PS_FACEBOOK_CAPI_PARTNER_AGENT);
// A test event code can be set to check the events are properly sent to Facebook
$testEventCode = $this->configurationAdapter->get(Config::PS_FACEBOOK_CAPI_TEST_EVENT_CODE);
if (!empty($testEventCode)) {
$request->setTestEventCode($testEventCode);
}
try {
$request->execute();
} catch (AuthorizationException $e) {
if (in_array($e->getCode(), Config::OAUTH_EXCEPTION_CODE)) {
$this->facebookClient->disconnectFromFacebook();
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_FORCED_DISCONNECT, true);
return false;
}
} catch (\Exception $e) {
$this->errorHandler->handle(
new FacebookConversionAPIException(
'Failed to send conversion API event',
FacebookConversionAPIException::SEND_EVENT_EXCEPTION,
$e
),
$e->getCode(),
false
);
}
}
}

View File

@@ -0,0 +1,113 @@
<?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\PrestashopFacebook\Handler;
use Category;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class CategoryMatchHandler
{
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
public function __construct(GoogleCategoryRepository $googleCategoryRepository)
{
$this->googleCategoryRepository = $googleCategoryRepository;
}
/**
* @param int $categoryId
* @param int|null $googleCategoryId
* @param string $googleCategoryName
* @param int $googleCategoryParentId
* @param string $googleCategoryParentName
* @param bool $updateChildren
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function updateCategoryMatch(
$categoryId,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$updateChildren,
$shopId
) {
if ($googleCategoryId === null) {
return $this->unsetCategoryMatch($categoryId, $updateChildren, $shopId);
}
if ($updateChildren === true) {
$category = new Category($categoryId);
$categoryChildrenIds = $category->getAllChildren();
$this->googleCategoryRepository->updateCategoryChildrenMatch(
$categoryChildrenIds,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId
);
}
$this->googleCategoryRepository->updateCategoryMatch(
$categoryId,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId,
$updateChildren
);
}
/**
* @param int $categoryId
* @param bool $updateChildren
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function unsetCategoryMatch(
$categoryId,
$updateChildren,
$shopId
) {
if ($updateChildren === true) {
$category = new Category($categoryId);
$categoryChildrenIds = $category->getAllChildren();
$this->googleCategoryRepository->unsetCategoryChildrenMatch(
$categoryChildrenIds,
$shopId
);
}
$this->googleCategoryRepository->unsetCategoryMatch(
$categoryId,
$shopId
);
}
}

View File

@@ -0,0 +1,84 @@
<?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\PrestashopFacebook\Handler;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class ConfigurationHandler
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(
ConfigurationAdapter $configurationAdapter
) {
$this->configurationAdapter = $configurationAdapter;
}
public function handle($onboardingInputs)
{
$this->saveOnboardingConfiguration($onboardingInputs);
}
private function saveOnboardingConfiguration(array $onboardingParams)
{
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_USER_ACCESS_TOKEN, $onboardingParams['access_token']);
$this->configurationAdapter->updateValue(Config::PS_PIXEL_ID, isset($onboardingParams['fbe']['pixel_id']) ? $onboardingParams['fbe']['pixel_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_PROFILES, isset($onboardingParams['fbe']['profiles']) ? implode(',', $onboardingParams['fbe']['profiles']) : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_PAGES, isset($onboardingParams['fbe']['pages']) ? implode(',', $onboardingParams['fbe']['pages']) : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID, isset($onboardingParams['fbe']['business_manager_id']) ? $onboardingParams['fbe']['business_manager_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_AD_ACCOUNT_ID, isset($onboardingParams['fbe']['ad_account_id']) ? $onboardingParams['fbe']['ad_account_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_CATALOG_ID, isset($onboardingParams['fbe']['catalog_id']) ? $onboardingParams['fbe']['catalog_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_PIXEL_ENABLED, true);
$this->configurationAdapter->deleteByName(Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE);
$this->configurationAdapter->deleteByName(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN);
$this->configurationAdapter->deleteByName(Config::PS_FACEBOOK_CAPI_TEST_EVENT_CODE);
}
public function cleanOnboardingConfiguration()
{
$dataConfigurationKeys = [
Config::PS_FACEBOOK_USER_ACCESS_TOKEN,
Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE,
Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN,
Config::PS_PIXEL_ID,
Config::PS_FACEBOOK_PROFILES,
Config::PS_FACEBOOK_PAGES,
Config::PS_FACEBOOK_BUSINESS_MANAGER_ID,
Config::PS_FACEBOOK_AD_ACCOUNT_ID,
Config::PS_FACEBOOK_CATALOG_ID,
Config::PS_FACEBOOK_PIXEL_ENABLED,
Config::PS_FACEBOOK_CAPI_TEST_EVENT_CODE,
Config::PS_FACEBOOK_PRODUCT_SYNC_FIRST_START,
Config::PS_FACEBOOK_PRODUCT_SYNC_ON,
Config::PS_FACEBOOK_FORCED_DISCONNECT,
Config::PS_FACEBOOK_SUSPENSION_REASON,
];
foreach ($dataConfigurationKeys as $key) {
$this->configurationAdapter->deleteByName($key);
}
}
}

View File

@@ -0,0 +1,104 @@
<?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\PrestashopFacebook\Handler\ErrorHandler;
use Module;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
/**
* Handle Error.
*/
class ErrorHandler
{
/**
* @var ModuleFilteredRavenClient
*/
protected $client;
public function __construct(Module $module, Env $env)
{
$this->client = new ModuleFilteredRavenClient(
$env->get('PSX_FACEBOOK_SENTRY_CREDENTIALS'),
[
'level' => 'warning',
'tags' => [
'php_version' => phpversion(),
'ps_facebook_version' => $module->version,
'prestashop_version' => _PS_VERSION_,
'ps_facebook_is_enabled' => Module::isEnabled($module->name),
'ps_facebook_is_installed' => Module::isInstalled($module->name),
'facebook_app_id' => Config::PSX_FACEBOOK_APP_ID,
],
'error_types' => E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED & ~E_NOTICE & ~E_USER_NOTICE,
]
);
// 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']);
// Other conditions can be done here to prevent the full installation of the client:
// - PHP versions,
// - PS versions,
// - Integration environment,
// - ...
if ($env->get('PSX_FACEBOOK_APP_ID') !== Config::PSX_FACEBOOK_APP_ID) {
return;
}
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 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\PrestashopFacebook\Handler\ErrorHandler;
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,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,93 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use PrestaShop\Module\PrestashopFacebook\Repository\ProductRepository;
use PrestaShop\Module\Ps_facebook\Utility\EventBusProductUtility;
class EventBusProductHandler
{
/**
* @var ProductRepository
*/
private $productRepository;
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* @param array $eventBusProducts
* @param int $shopId
* @param string $isoCode
*
* @return array
*
* @throws \PrestaShopDatabaseException
*/
public function getInformationAboutEventBusProductsWithErrors(array $eventBusProducts, $shopId, $isoCode)
{
$eventBusProductsInformation = [];
foreach ($eventBusProducts as $eventBusProductId => $messages) {
$eventBusProductObj = eventBusProductUtility::eventBusProductToObject($eventBusProductId);
$eventBusProductInfo = $this->productRepository->getInformationAboutEventBusProduct(
$eventBusProductObj,
$shopId,
$isoCode
);
$eventBusProductsInformation[$eventBusProductId] = $eventBusProductInfo ? $eventBusProductInfo[0] : [];
$eventBusProductsInformation[$eventBusProductId]['messages'] = $messages;
}
return $eventBusProductsInformation;
}
/**
* @param array $eventBusProducts
* @param string $lastSyncDate
* @param int $shopId
*
* @return array
*
* @throws \PrestaShopDatabaseException
*/
public function getFilteredInformationAboutEventBusProducts(
array $eventBusProducts,
$lastSyncDate,
$shopId
) {
$formattedSyncTimeDate = date('Y-m-d H:i:s', strtotime($lastSyncDate));
$productsWithErrors = array_keys($eventBusProducts);
$eventBusProductsInfo = $this->productRepository->getInformationAboutEventBusProducts(
$formattedSyncTimeDate,
$shopId,
$productsWithErrors
);
foreach ($eventBusProducts as $eventBusProductId => $messages) {
$eventBusProductsInfo[$eventBusProductId]['messages'] = $messages;
}
return $eventBusProductsInfo;
}
}

View File

@@ -0,0 +1,32 @@
<?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\PrestashopFacebook\Handler;
interface HandlerInterface
{
/**
* @param string $eventName
* @param array $event
*
* @return void
*/
public function handleEvent($eventName, array $event);
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use Language;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
class MessengerHandler
{
/**
* @var string
*/
private $pageId;
/**
* @var Language
*/
private $lang;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var Env
*/
private $env;
public function __construct(
Language $lang,
ConfigurationAdapter $configurationAdapter,
Env $env
) {
$pageList = explode(',', $configurationAdapter->get('PS_FACEBOOK_PAGES'));
$this->pageId = reset($pageList);
$this->lang = $lang;
$this->configurationAdapter = $configurationAdapter;
$this->env = $env;
}
/**
* @return bool
*/
public function isReady()
{
if (empty($this->pageId)) {
return false;
}
$messengerChatFeature = json_decode($this->configurationAdapter->get(Config::FBE_FEATURE_CONFIGURATION . 'messenger_chat'));
return $messengerChatFeature && $messengerChatFeature->enabled;
}
public function handle()
{
return [
'ps_facebook_messenger_api_version' => Config::API_VERSION,
'ps_facebook_messenger_app_id' => $this->env->get('PSX_FACEBOOK_APP_ID'),
'ps_facebook_messenger_page_id' => $this->pageId,
'ps_facebook_messenger_locale' => $this->getLocale(),
];
}
/**
* Return the current language locale so the messenger is properly localized
*
* @return string
*/
private function getLocale()
{
// PrestaShop 1.7+
if (!empty($this->lang->locale)) {
return str_replace('-', '_', $this->lang->locale);
}
return 'en_US';
}
}

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\PrestashopFacebook\Handler;
use FacebookAds\Object\ServerSide\Normalizer;
use FacebookAds\Object\ServerSide\Util;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Buffer\TemplateBuffer;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class PixelHandler
{
/**
* @var \Context
*/
private $context;
/**
* @var \Ps_facebook
*/
private $module;
/**
* @var TemplateBuffer
*/
private $templateBuffer;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct($module, ConfigurationAdapter $configurationAdapter)
{
$this->context = \Context::getContext();
$this->module = $module;
$this->templateBuffer = $module->templateBuffer;
$this->configurationAdapter = $configurationAdapter;
}
public function handleEvent($params)
{
$pixel_id = $this->configurationAdapter->get(Config::PS_PIXEL_ID);
if (empty($pixel_id)) {
return;
}
$track = 'track';
$eventType = false;
if (isset($params['event_type'])) {
$eventType = $params['event_type'];
}
if (isset($params['user'])) {
$userData = $params['user'];
}
$content = $eventData = [];
if (isset($params['eventID'])) {
$eventData = ['eventID' => $params['eventID']];
}
if (isset($params['custom_data'])) {
$content = $params['custom_data'];
}
$smartyVariables = [
'pixel_fc' => $this->module->front_controller,
'id_pixel' => $pixel_id,
'type' => $eventType,
'content' => $this->formatPixel($content),
'track' => $track,
'eventData' => $this->formatPixel($eventData),
];
if (isset($userData)) {
$smartyVariables['userInfos'] = $this->getCustomerInformation($userData);
}
$this->context->smarty->assign($smartyVariables);
$this->templateBuffer->add($this->module->display($this->module->getfilePath(), 'views/templates/hook/header.tpl'));
}
/**
* formatPixel
*
* @param array $params
*
* @return string|false
*/
protected function formatPixel($params)
{
return json_encode((object) $params);
}
/**
* getCustomerInformation
*
* @param array $customerInformation
*
* @return array
*/
protected function getCustomerInformation($customerInformation)
{
return [
'ct' => Util::hash(Normalizer::normalize('ct', $customerInformation['city'])),
'country' => Util::hash(Normalizer::normalize('country', $customerInformation['countryIso'])),
'zp' => Util::hash(Normalizer::normalize('zp', $customerInformation['postCode'])),
'ph' => Util::hash(Normalizer::normalize('ph', $customerInformation['phone'])),
'gender' => Util::hash(Normalizer::normalize('gender', $customerInformation['gender'])),
'fn' => Util::hash(Normalizer::normalize('fn', $customerInformation['firstname'])),
'ln' => Util::hash(Normalizer::normalize('ln', $customerInformation['lastname'])),
'em' => Util::hash(Normalizer::normalize('em', $customerInformation['email'])),
'bd' => Util::hash(Normalizer::normalize('bd', $customerInformation['birthday'])),
'st' => Util::hash(Normalizer::normalize('st', $customerInformation['stateIso'])),
];
}
}

View File

@@ -0,0 +1,116 @@
<?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\PrestashopFacebook\Handler;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Provider\PrevalidationScanCacheProvider;
use PrestaShop\Module\PrestashopFacebook\Repository\ProductRepository;
class PrevalidationScanRefreshHandler
{
/**
* @var PrevalidationScanCacheProvider
*/
protected $prevalidationScanCacheProvider;
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var int
*/
protected $shopId;
/**
* @param int $shopId
*/
public function __construct(
PrevalidationScanCacheProvider $prevalidationScanCacheProvider,
ProductRepository $productRepository,
$shopId
) {
$this->prevalidationScanCacheProvider = $prevalidationScanCacheProvider;
$this->productRepository = $productRepository;
$this->shopId = $shopId;
}
/**
* @param int $page
*
* @return array
*/
public function run($page = 0)
{
if ($page === 0) {
$this->prevalidationScanCacheProvider->clear();
}
$products = $this->productRepository->getProductsWithErrors($this->shopId, $page);
$this->prevalidationScanCacheProvider->set(
PrevalidationScanCacheProvider::CACHE_KEY_PAGE . $this->shopId . '_' . $page,
json_encode($products)
);
$numberOfProductsWithError = count($products) + Config::REPORTS_PER_PAGE * $page;
if (count($products) === Config::REPORTS_PER_PAGE) {
// We reached the maximum number of results, this is likely meaning
// that we have another page to work with.
return [
'success' => true,
'complete' => false,
'page_done' => $page,
'progress' => $numberOfProductsWithError,
];
}
// This was the last page, we store and return the summary
$summary = $this->generateSummaryData($numberOfProductsWithError);
$this->prevalidationScanCacheProvider->set(
PrevalidationScanCacheProvider::CACHE_KEY_SUMMARY . $this->shopId,
json_encode($summary)
);
return [
'success' => true,
'complete' => true,
'prevalidation' => $summary,
];
}
/**
* @param int $numberOfProductsWithError
*
* @return array
*/
private function generateSummaryData($numberOfProductsWithError)
{
$productsTotal = $this->productRepository->getProductsTotal($this->shopId, ['onlyActive' => true]);
return [
'syncable' => $productsTotal - $numberOfProductsWithError,
'notSyncable' => $numberOfProductsWithError,
'lastScanDate' => date(DATE_ISO8601),
];
}
}

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,74 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Manager;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class FbeFeatureManager
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var FacebookClient
*/
private $facebookClient;
public function __construct(ConfigurationAdapter $configurationAdapter, FacebookClient $facebookClient)
{
$this->configurationAdapter = $configurationAdapter;
$this->facebookClient = $facebookClient;
}
/**
* @param string $featureName
* @param bool $state
*
* @return array|false
*/
public function updateFeature($featureName, $state)
{
$featureConfiguration = $this->configurationAdapter->get(Config::FBE_FEATURE_CONFIGURATION . $featureName);
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
if (!$featureConfiguration) {
return false;
}
$featureConfiguration = json_decode($featureConfiguration);
if ($featureName == 'messenger_chat') {
unset($featureConfiguration->default_locale);
}
$featureConfiguration->enabled = (bool) $state;
$this->configurationAdapter->updateValue(Config::FBE_FEATURE_CONFIGURATION . $featureName, json_encode($featureConfiguration));
$configuration = [
$featureName => $featureConfiguration,
];
return $this->facebookClient->updateFeature($externalBusinessId, $configuration);
}
}

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
*/
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,105 @@
<?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\PrestashopFacebook\Presenter;
use Context;
use Module;
class ModuleUpgradePresenter
{
/**
* @var Context
*/
private $context;
public function __construct($context)
{
$this->context = $context;
}
/**
* Generate the object responsible of displaying the alert when module upgrade is requested
*
* @param string $moduleName
* @param string $versionRequired
*
* @return array
*/
public function generateModuleDependencyVersionCheck($moduleName, $versionRequired)
{
$needsUpgrade = false;
$currentVersion = null;
$moduleInstance = null;
if (Module::isInstalled($moduleName)) {
$moduleInstance = Module::getInstanceByName($moduleName);
if ($moduleInstance !== false) {
$currentVersion = $moduleInstance->version;
$needsUpgrade = version_compare(
$currentVersion,
$versionRequired,
'<'
);
}
}
return [
'needsInstall' => !($moduleInstance && Module::isInstalled($moduleName)),
'needsEnable' => !Module::isEnabled($moduleName),
'needsUpgrade' => $needsUpgrade,
'currentVersion' => $currentVersion,
'requiredVersion' => $versionRequired,
'psFacebookUpgradeRoute' => $this->context->link->getAdminLink(
'AdminAjaxPsfacebook',
true,
[],
[
'action' => 'ManageModule',
'module_action' => 'upgrade',
'module_name' => $moduleName,
'ajax' => 1,
]
),
'psFacebookInstallRoute' => $this->context->link->getAdminLink(
'AdminAjaxPsfacebook',
true,
[],
[
'action' => 'ManageModule',
'module_action' => 'install',
'module_name' => $moduleName,
'ajax' => 1,
]
),
'psFacebookEnableRoute' => $this->context->link->getAdminLink(
'AdminAjaxPsfacebook',
true,
[],
[
'action' => 'ManageModule',
'module_action' => 'enable',
'module_name' => $moduleName,
'ajax' => 1,
]
),
];
}
}

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,200 @@
<?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\PrestashopFacebook\Provider;
use Controller;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\AccessTokenException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
class AccessTokenProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var Controller
*/
private $controller;
/**
* @var ApiClientFactoryInterface
*/
private $psApiClientFactory;
/**
* @var ResponseListener
*/
private $responseListener;
/**
* @var string
*/
private $userAccessToken;
/**
* @var string|null
*/
private $systemAccessToken;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ResponseListener $responseListener,
$controller,
ApiClientFactoryInterface $psApiClientFactory
) {
$this->configurationAdapter = $configurationAdapter;
$this->responseListener = $responseListener;
$this->controller = $controller;
$this->psApiClientFactory = $psApiClientFactory;
}
/**
* @return string
*/
public function getUserAccessToken()
{
if (!$this->userAccessToken) {
$this->getOrRefreshTokens();
}
return $this->userAccessToken;
}
/**
* @return string|null
*/
public function getSystemAccessToken()
{
if (!$this->systemAccessToken) {
$this->getOrRefreshTokens();
}
return $this->systemAccessToken;
}
/**
* Load data from configuration table and request from API them if something is missing
*/
private function getOrRefreshTokens()
{
$this->userAccessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$this->systemAccessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN);
$tokenExpirationDate = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE);
$currentTimestamp = time();
if ((!$this->systemAccessToken
|| !$tokenExpirationDate
|| ($tokenExpirationDate - $currentTimestamp <= 86400))
&& isset($this->controller->controller_type)
&& $this->controller->controller_type === 'moduleadmin'
&& $this->userAccessToken
) {
$this->refreshTokens();
}
}
/**
* Exchange existing tokens with new ones, then store them in the DB + make them available in this class
*
* @return void
*/
public function refreshTokens()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$accessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$managerId = $this->configurationAdapter->get(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID);
if (!$managerId) {
// Force as null, otherwise it gets a falsy value in the API request
$managerId = null;
}
$response = $this->responseListener->handleResponse(
$this->psApiClientFactory->createClient()->sendRequest(
new Request(
'POST',
'/account/' . $externalBusinessId . '/exchange_tokens',
[],
json_encode([
'userAccessToken' => $accessToken,
'businessManagerId' => $managerId,
])
)
),
[
'exceptionClass' => AccessTokenException::class,
]
);
if (!$response->isSuccessful()) {
return;
}
$responseContent = $response->getBody();
if (isset($responseContent['longLived']['access_token'])) {
$tokenExpiresIn = time() + (70 * 365 * 24 * 3600); // never expires
$this->userAccessToken = $responseContent['longLived']['access_token'];
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_USER_ACCESS_TOKEN, $this->userAccessToken);
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE, $tokenExpiresIn);
}
if (isset($responseContent['system']['access_token'])) {
$this->systemAccessToken = $responseContent['system']['access_token'];
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN, $this->systemAccessToken);
}
}
/**
* Exchange existing tokens with new ones, then store them in the DB + make them available in this class
*
* @return array|null
*/
public function retrieveTokens()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$response = $this->responseListener->handleResponse(
$this->psApiClientFactory->createClient()->sendRequest(
new Request(
'GET',
'/account/' . $externalBusinessId . '/app_tokens'
)
),
[
'exceptionClass' => AccessTokenException::class,
]
);
if (!$response->isSuccessful()) {
return null;
}
return $response->getBody();
}
}

View File

@@ -0,0 +1,553 @@
<?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\PrestashopFacebook\Provider;
use Cart;
use Context;
use Order;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Adapter\ToolsAdapter;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
use PrestaShop\Module\PrestashopFacebook\Repository\ProductRepository;
use PrestaShop\Module\Ps_facebook\Utility\CustomerInformationUtility;
use PrestaShop\Module\Ps_facebook\Utility\ProductCatalogUtility;
use PrestaShopException;
use Product;
use Ps_facebook;
class EventDataProvider
{
public const PRODUCT_TYPE = 'product';
public const CATEGORY_TYPE = 'product_group';
/**
* @var Context
*/
private $context;
private $locale;
/**
* @var ToolsAdapter
*/
private $toolsAdapter;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ps_facebook
*/
private $module;
/**
* @var ProductAvailabilityProviderInterface
*/
private $availabilityProvider;
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
/**
* @var GoogleCategoryProvider
*/
private $googleCategoryProvider;
public function __construct(
ToolsAdapter $toolsAdapter,
ConfigurationAdapter $configurationAdapter,
ProductRepository $productRepository,
Context $context,
ps_facebook $module,
ProductAvailabilityProviderInterface $availabilityProvider,
GoogleCategoryRepository $googleCategoryRepository,
GoogleCategoryProvider $googleCategoryProvider
) {
$this->toolsAdapter = $toolsAdapter;
$this->context = $context;
$this->locale = \Tools::strtoupper($this->context->language->iso_code);
$this->configurationAdapter = $configurationAdapter;
$this->productRepository = $productRepository;
$this->module = $module;
$this->availabilityProvider = $availabilityProvider;
$this->googleCategoryRepository = $googleCategoryRepository;
$this->googleCategoryProvider = $googleCategoryProvider;
}
public function generateEventData($name, array $params)
{
switch ($name) {
case 'hookDisplayHeader':
if (true === \Tools::isSubmit('submitCustomizedData')) {
return $this->getCustomEventData();
}
if ($this->context->controller instanceof \ProductControllerCore) {
return $this->getProductPageData();
}
if ($this->context->controller instanceof \CategoryControllerCore) {
return $this->getCategoryPageData();
}
if ($this->context->controller instanceof \CmsControllerCore) {
return $this->getCMSPageData();
}
break;
case 'hookActionSearch':
return $this->getSearchEventData($params);
case 'hookActionObjectCustomerMessageAddAfter':
return $this->getContactEventData();
case 'hookDisplayOrderConfirmation':
return $this->getOrderConfirmationEvent($params);
case 'InitiateCheckout':
return $this->getInitiateCheckoutEvent();
case 'hookActionCartSave':
return $this->getAddToCartEventData();
case 'hookActionNewsletterRegistrationAfter':
return $this->getShopSubscriptionEvent($params);
case 'hookActionCustomerAccountAdd':
return $this->getCompleteRegistrationEventData();
case 'customizeProduct':
return $this->getCustomisationEventData($params);
case 'hookActionFacebookCallPixel':
return $this->getCustomEvent($params);
}
return false;
}
private function getProductPageData()
{
$type = 'ViewContent';
/** @var \ProductControllerCore $controller */
$controller = $this->context->controller;
$product = $controller->getTemplateVarProduct();
$fbProductId = ProductCatalogUtility::makeProductId(
$product['id_product'],
$product['id_product_attribute']
);
$productUrl = $this->context->link->getProductLink($product['id']);
$categoryPath = $this->googleCategoryProvider->getCategoryPaths(
$product['id_category_default'],
$this->context->language->id,
$this->context->shop->id
);
$content = [
'id' => $fbProductId,
'title' => \Tools::replaceAccentedChars($product['name']),
'category' => $categoryPath['category_path'],
'item_price' => $product['price_tax_exc'],
'brand' => (new \Manufacturer($product['id_manufacturer']))->name,
];
$customData = [
'currency' => $this->getCurrency(),
'content_ids' => [$fbProductId],
'contents' => [$content],
'content_type' => self::PRODUCT_TYPE,
'value' => $product['price_tax_exc'],
];
$category = $this->googleCategoryRepository->getGoogleCategoryIdByCategoryId(
$product['id_category_default'],
$this->context->shop->id
) ?: '';
$this->context->smarty->assign(
[
'retailer_item_id' => $fbProductId,
'product_availability' => $this->availabilityProvider->getProductAvailability(
(int) $product['id_product'],
(int) $product['id_product_attribute']
),
'item_group_id' => $category,
]
);
return [
'custom_data' => $customData,
'event_source_url' => $productUrl,
] + $this->getCommonData($type);
}
private function getCategoryPageData()
{
$type = 'ViewCategory';
/** @var \CategoryControllerCore $controller */
$controller = $this->context->controller;
$category = $controller->getCategory();
$page = $this->toolsAdapter->getValue('page');
$resultsPerPage = $this->configurationAdapter->get('PS_PRODUCTS_PER_PAGE');
$prods = $category->getProducts($this->context->language->id, $page, $resultsPerPage);
$categoryUrl = $this->context->link->getCategoryLink($category->id);
$breadcrumbs = $controller->getBreadcrumbLinks();
$breadcrumb = implode(' > ', array_column($breadcrumbs['links'], 'title'));
$contentIds = [];
if ($prods) {
foreach ($prods as $product) {
$contentIds[] = ProductCatalogUtility::makeProductId(
$product['id_product'],
$product['id_product_attribute']
);
}
}
$customData = [
'content_name' => \Tools::replaceAccentedChars($category->name) . ' ' . $this->locale,
'content_category' => \Tools::replaceAccentedChars($breadcrumb),
'content_type' => self::CATEGORY_TYPE,
'content_ids' => $contentIds ?: null,
];
return [
'custom_data' => $customData,
'event_source_url' => $categoryUrl,
] + $this->getCommonData($type);
}
private function getCMSPageData()
{
$type = 'ViewCMS';
$cms = new \CMS((int) $this->toolsAdapter->getValue('id_cms'), $this->context->language->id);
/** @var \CmsControllerCore $controller */
$controller = $this->context->controller;
$breadcrumbs = $controller->getBreadcrumbLinks();
$breadcrumb = implode(' > ', array_column($breadcrumbs['links'], 'title'));
$customData = [
'content_name' => \Tools::replaceAccentedChars($cms->meta_title) . ' ' . $this->locale,
'content_category' => \Tools::replaceAccentedChars($breadcrumb),
'content_type' => self::PRODUCT_TYPE,
];
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getAddToCartEventData()
{
$action = $this->toolsAdapter->getValue('action');
$quantity = $this->toolsAdapter->getValue('qty');
$idProduct = $this->toolsAdapter->getValue('id_product');
$op = $this->toolsAdapter->getValue('op');
$isDelete = $this->toolsAdapter->getValue('delete');
$idProductAttribute = $this->toolsAdapter->getValue('id_product_attribute');
$attributeGroups = $this->toolsAdapter->getValue('group');
if ($attributeGroups) {
try {
$idProductAttribute = $this->productRepository->getIdProductAttributeByIdAttributes(
$idProduct,
$attributeGroups
);
} catch (PrestaShopException $e) {
return false;
}
}
if ($action !== 'update') {
return false;
}
$type = 'AddToCart';
if ($op) {
$type = $op === 'up' ? 'IncreaseProductQuantityInCart' : 'DecreaseProductQuantityInCart';
} elseif ($isDelete) {
//todo: when removing product from cart this hook gets called twice
$type = 'RemoveProductFromCart';
$quantity = null;
}
$productName = Product::getProductName($idProduct, $idProductAttribute);
$customData = [
'content_name' => pSQL($productName),
'content_type' => self::PRODUCT_TYPE,
'content_ids' => [
ProductCatalogUtility::makeProductId(
$idProduct,
$idProductAttribute
),
],
'num_items' => pSQL($quantity),
];
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getCompleteRegistrationEventData()
{
$type = 'CompleteRegistration';
$customData = [
'content_name' => 'authentication',
];
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getContactEventData()
{
return $this->getCommonData('Contact');
}
private function getCustomisationEventData($params)
{
$type = 'CombinationProduct';
$idLang = (int) $this->context->language->id;
$productId = $this->toolsAdapter->getValue('id_product');
$attributeIds = $params['attributeIds'];
$customData = $this->getCustomAttributeData($productId, $idLang, $attributeIds);
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getCustomEventData()
{
return $this->getCommonData('CustomizeProduct');
}
private function getSearchEventData($params)
{
$searchQuery = $params['searched_query'];
$quantity = $params['total'];
$type = 'Search';
$customData = [
'content_name' => 'searchQuery',
'search_string' => $searchQuery,
];
if ($quantity) {
$customData['num_items'] = $quantity;
}
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getOrderConfirmationEvent($params)
{
/** @var Order $order */
$order = $this->module->psVersionIs17 ? $params['order'] : $params['objOrder'];
$productList = [];
foreach ($order->getCartProducts() as $product) {
$productList[] = ProductCatalogUtility::makeProductId(
$product['id_product'],
$product['id_product_attribute']
);
}
$type = 'Purchase';
$customData = [
'content_name' => 'purchased',
'order_id' => $order->id,
'currency' => $this->getCurrency(),
'content_ids' => $productList,
'content_type' => self::PRODUCT_TYPE,
'value' => (float) ($order->total_paid_tax_excl),
];
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getInitiateCheckoutEvent()
{
$type = 'InitiateCheckout';
$cart = $this->context->cart;
$contents = $this->getProductContent($cart);
$customData = [
'contents' => $contents,
'content_type' => 'product',
'currency' => $this->getCurrency(),
'value' => $cart->getOrderTotal(false),
];
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
private function getShopSubscriptionEvent($params)
{
$type = 'Subscribe';
$customData = [
'content_name' => pSQL($params['email']),
];
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
/**
* @param Cart $cart
*
* @return array
*/
private function getProductContent(Cart $cart)
{
$contents = [];
foreach ($cart->getProducts() as $product) {
$categoryPath = $this->googleCategoryProvider->getCategoryPaths(
$product['id_category_default'],
$this->context->language->id,
$this->context->shop->id
);
$content = [
'id' => ProductCatalogUtility::makeProductId($product['id_product'], $product['id_product_attribute']),
'quantity' => $product['quantity'],
'item_price' => $product['price'],
'title' => \Tools::replaceAccentedChars($product['name']),
'brand' => (new \Manufacturer($product['id_manufacturer']))->name,
'category' => $categoryPath['category_path'],
];
$contents[] = $content;
}
return $contents;
}
/**
* @param array $params
*
* @return array|null
*/
private function getCustomEvent($params)
{
if (!isset($params['eventName']) || !isset($params['module'])) {
return null;
}
$type = pSQL($params['eventName']);
$customData = [
'custom_properties' => [
'module' => pSQL($params['module']),
],
];
if (isset($params['id_product'])) {
$fbProductId = ProductCatalogUtility::makeProductId(
$params['id_product'],
isset($params['id_product_attribute']) ? $params['id_product_attribute'] : 0
);
$customData['content_ids']['module'] = $fbProductId;
}
return [
'custom_data' => $customData,
] + $this->getCommonData($type);
}
/**
* @param int $productId
* @param int $idLang
* @param int[] $attributeIds
*
* @return array
*
* @throws \PrestaShopException
*/
private function getCustomAttributeData($productId, $idLang, $attributeIds)
{
$attributes = [];
foreach ($attributeIds as $attributeId) {
$attributes[] = (new \AttributeCore($attributeId, $idLang))->name;
}
try {
$idProductAttribute = $this->productRepository->getIdProductAttributeByIdAttributes(
$productId,
$attributeIds
);
} catch (PrestaShopException $e) {
$idProductAttribute = 0;
}
return [
'content_type' => self::PRODUCT_TYPE,
'content_ids' => [
ProductCatalogUtility::makeProductId($productId, $idProductAttribute),
],
'custom_properties' => [
'custom_attributes' => $attributes,
],
];
}
/**
* Generate the array with data that are used for all events
*
* @see https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events
*
* @param string $eventType
*/
private function getCommonData($eventType)
{
$time = time();
return [
'event_type' => $eventType,
'event_time' => $time,
'user' => CustomerInformationUtility::getCustomerInformationForPixel($this->context->customer),
'eventID' => uniqid($eventType . '_' . $time . '_', true),
];
}
private function getCurrency()
{
return \Tools::strtolower($this->context->currency->iso_code);
}
}

View File

@@ -0,0 +1,92 @@
<?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\PrestashopFacebook\Provider;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\ContextPsFacebook;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Catalog;
class FacebookDataProvider
{
/**
* @var FacebookClient
*/
protected $facebookClient;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(FacebookClient $facebookClient, ConfigurationAdapter $configurationAdapter)
{
$this->facebookClient = $facebookClient;
$this->configurationAdapter = $configurationAdapter;
}
/**
* https://github.com/facebookarchive/php-graph-sdk
* https://developers.facebook.com/docs/graph-api/changelog/version8.0
**
* @param array $fbe
*
* @return ContextPsFacebook|null
*/
public function getContext(array $fbe)
{
if (isset($fbe['error']) || !$this->facebookClient->hasAccessToken()) {
return null;
}
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$hasFbeFeatures = (bool) $this->facebookClient->getFbeFeatures($externalBusinessId);
if (!$hasFbeFeatures) {
return null;
}
$user = $this->facebookClient->getUserEmail();
$businessManager = $this->facebookClient->getBusinessManager($fbe['business_manager_id']);
$pixel = $this->facebookClient->getPixel($fbe['ad_account_id'], $fbe['pixel_id']);
$pages = $this->facebookClient->getPage($fbe['pages']);
$ad = $this->facebookClient->getAd($fbe['ad_account_id']);
$productSyncStarted = (bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PRODUCT_SYNC_FIRST_START);
$categoryMatchingStarted = false; // TODO : must be true only if all parent categories are matched !
$catalog = new Catalog($fbe['catalog_id'], $productSyncStarted, $categoryMatchingStarted);
return new ContextPsFacebook(
$user,
$businessManager,
$pixel,
$pages,
$ad,
$catalog
);
}
public function getProductsInCatalogCount()
{
$catalogId = $this->configurationAdapter->get(Config::PS_FACEBOOK_CATALOG_ID);
return $this->facebookClient->getProductsInCatalogCount($catalogId);
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class FbeDataProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(ConfigurationAdapter $configurationAdapter)
{
$this->configurationAdapter = $configurationAdapter;
}
/**
* @return array
*/
public function getFbeData()
{
return [
'pixel_id' => $this->configurationAdapter->get(Config::PS_PIXEL_ID),
'profiles' => $this->configurationAdapter->get(Config::PS_FACEBOOK_PROFILES),
'pages' => [
$this->configurationAdapter->get(Config::PS_FACEBOOK_PAGES),
],
'business_manager_id' => $this->configurationAdapter->get(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID),
'catalog_id' => $this->configurationAdapter->get(Config::PS_FACEBOOK_CATALOG_ID),
'ad_account_id' => $this->configurationAdapter->get(Config::PS_FACEBOOK_AD_ACCOUNT_ID),
];
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class FbeFeatureDataProvider
{
/**
* @var FacebookClient
*/
private $facebookClient;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(FacebookClient $facebookClient, ConfigurationAdapter $configurationAdapter)
{
$this->facebookClient = $facebookClient;
$this->configurationAdapter = $configurationAdapter;
}
public function getFbeFeatures()
{
if (!$this->facebookClient->hasAccessToken()) {
return false;
}
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$features = $this->facebookClient->getFbeFeatures($externalBusinessId);
$unavailableFeatures = [];
$productsSynced = $this->configurationAdapter->get(Config::PS_FACEBOOK_PRODUCT_SYNC_ON);
$features = array_filter($features, function ($key) {
return in_array($key, Config::AVAILABLE_FBE_FEATURES);
}, ARRAY_FILTER_USE_KEY);
foreach ($features as $featureName => $feature) {
if ($feature['enabled'] || $this->configurationAdapter->get(Config::FBE_FEATURE_CONFIGURATION . $featureName) !== false) {
$this->configurationAdapter->updateValue(Config::FBE_FEATURE_CONFIGURATION . $featureName, json_encode($feature));
}
}
$enabledFeatures = array_filter($features, function ($featureName) {
return $this->configurationAdapter->get(Config::FBE_FEATURE_CONFIGURATION . $featureName) !== false;
}, ARRAY_FILTER_USE_KEY);
$disabledFeatures = array_filter($features, function ($featureName) {
return $this->configurationAdapter->get(Config::FBE_FEATURE_CONFIGURATION . $featureName) === false;
}, ARRAY_FILTER_USE_KEY);
if (!$productsSynced) {
$unavailableFeatures = array_filter($features, function ($key) use ($enabledFeatures) {
return in_array($key, Config::FBE_FEATURES_REQUIRING_PRODUCT_SYNC)
&& in_array($key, $enabledFeatures);
}, ARRAY_FILTER_USE_KEY);
}
return [
'enabledFeatures' => $enabledFeatures,
'disabledFeatures' => $disabledFeatures,
'unavailableFeatures' => $unavailableFeatures,
];
}
}

View File

@@ -0,0 +1,161 @@
<?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\PrestashopFacebook\Provider;
use Category;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class GoogleCategoryProvider implements GoogleCategoryProviderInterface
{
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
public function __construct(
GoogleCategoryRepository $googleCategoryRepository
) {
$this->googleCategoryRepository = $googleCategoryRepository;
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId)
{
$categoryMatch = $this->googleCategoryRepository->getCategoryMatchByCategoryId($categoryId, $shopId);
if (!is_array($categoryMatch)) {
return null;
}
return $categoryMatch;
}
/**
* @param int $categoryId
* @param int $langId
* @param int $shopId
* @param int $page
*
* @return array|null
*/
public function getGoogleCategoryChildren($categoryId, $langId, $shopId, $page = 1)
{
if ($page < 1) {
$page = 1;
}
$googleCategories = $this->googleCategoryRepository->getFilteredCategories(
$categoryId,
$langId,
Config::CATEGORIES_PER_PAGE * ($page - 1),
Config::CATEGORIES_PER_PAGE,
$shopId
);
if (!is_array($googleCategories)) {
return null;
}
return $googleCategories;
}
/**
* @param int $shopId
*
* @return array
*/
public function getInformationAboutCategoryMatches($shopId)
{
$numberOfMatchedCategories = $this->googleCategoryRepository->getNumberOfMatchedCategories($shopId);
$totalCategories = $this->googleCategoryRepository->getNumberOfTotalCategories($shopId);
return [
'matched' => $numberOfMatchedCategories,
'total' => $totalCategories,
];
}
/**
* @param array $categoryIds
* @param int $shopId
*
* @return array|null
*
* @throws \PrestaShopDatabaseException
*/
public function getGoogleCategories(array $categoryIds, $shopId)
{
$categoryMatch = $this->googleCategoryRepository->getCategoryMatchesByCategoryIds($categoryIds, $shopId);
if (!is_array($categoryMatch)) {
return null;
}
return $categoryMatch;
}
public function getCategoryPaths($topCategoryId, $langId, $shopId)
{
if ((int) $topCategoryId === 0) {
return [
'category_path' => '',
'category_id_path' => '',
];
}
$categoryId = $topCategoryId;
$categories = [];
try {
$categoriesWithParentsInfo = $this->googleCategoryRepository->getCategoriesWithParentInfo($langId, $shopId);
} catch (\PrestaShopDatabaseException $e) {
return [
'category_path' => '',
'category_id_path' => '',
];
}
$homeCategory = Category::getTopCategory()->id;
$categoryExists = true;
while ((int) $categoryId != $homeCategory && $categoryExists) {
$categoryExists = false;
foreach ($categoriesWithParentsInfo as $category) {
if ($category['id_category'] == $categoryId) {
$categories[] = $category;
$categoryId = $category['id_parent'];
$categoryExists = true;
break;
}
}
}
$categories = array_reverse($categories);
return [
'category_path' => implode(' > ', array_map(function ($category) {
return $category['name'];
}, $categories)),
'category_id_path' => implode(' > ', array_map(function ($category) {
return $category['id_category'];
}, $categories)),
];
}
}

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\PrestashopFacebook\Provider;
interface GoogleCategoryProviderInterface
{
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId);
/**
* @param int $categoryId
* @param int $langId
* @param int $shopId
* @param int $page
*
* @return array|null
*/
public function getGoogleCategoryChildren($categoryId, $langId, $shopId, $page);
}

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\PrestashopFacebook\Provider;
use PrestaShop\Module\PrestashopFacebook\Repository\ShopRepository;
use PrestaShop\Module\Ps_facebook\Tracker\Segment;
use Shop;
class MultishopDataProvider
{
/**
* @var ShopRepository
*/
private $shopRepository;
/**
* @var Segment
*/
private $segment;
public function __construct(
ShopRepository $shopRepository,
Segment $segment
) {
$this->shopRepository = $shopRepository;
$this->segment = $segment;
}
/**
* It appeared that PS Account is currently incompatible with multistore feature.
* While a new major version is prepared, we display a message if the merchant
* onboarded one other shop.
*
* To revent this, we check if a shop is already onboarded and
* warn the merchant accordingly.
*
* @param Shop $currentShop
*
* @return bool
*/
public function isCurrentShopInConflict(Shop $currentShop)
{
$configurationData = $this->shopRepository->getShopDomainsAndConfiguration();
foreach ($configurationData as $shopData) {
if ((int) $shopData['id_shop'] === (int) $currentShop->id) {
continue;
}
if (empty($shopData['acces_token_value'])) {
continue;
}
$this->segment->setMessage('Error: Warn about multistore incompatibility with PS Account');
$this->segment->track();
return true;
}
return false;
}
}

View File

@@ -0,0 +1,62 @@
<?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\PrestashopFacebook\Provider;
class PrevalidationScanDataProvider
{
/**
* @var PrevalidationScanCacheProvider
*/
protected $preValidationCacheProvider;
public function __construct(PrevalidationScanCacheProvider $preValidationCacheProvider)
{
$this->preValidationCacheProvider = $preValidationCacheProvider;
}
/**
* @return array|null
*/
public function getPrevalidationScanSummary($shopId)
{
return json_decode($this->preValidationCacheProvider->get(
PrevalidationScanCacheProvider::CACHE_KEY_SUMMARY . $shopId
));
}
/**
* @param int $page
* @param int $shopId
*
* @return array
*/
public function getPageOfPrevalidationScan($shopId, $page)
{
$cacheContent = json_decode($this->preValidationCacheProvider->get(
PrevalidationScanCacheProvider::CACHE_KEY_PAGE . $shopId . '_' . $page
));
if (empty($cacheContent)) {
return [];
}
return $cacheContent;
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use Ps_facebook;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
class PrevalidationScanCacheProvider
{
public const CACHE_KEY_SUMMARY = 'summary_';
public const CACHE_KEY_PAGE = 'page_';
/**
* @var string
*/
protected $cachePath;
/**
* @var Filesystem
*/
protected $filesystem;
/**
* @param string $cachePath
*/
public function __construct(Ps_facebook $module, $cachePath)
{
$this->cachePath = $cachePath . '/' . $module->name . '/';
$this->filesystem = new Filesystem();
}
/**
* @param string $cacheKey
*/
public function get($cacheKey)
{
if (!file_exists($this->getCacheFilePath($cacheKey))) {
return null;
}
return file_get_contents($this->getCacheFilePath($cacheKey));
}
/**
* @param string $cacheKey
* @param string $content
*/
public function set($cacheKey, $content)
{
$this->filesystem->dumpFile($this->getCacheFilePath($cacheKey), $content);
}
public function clear()
{
$this->filesystem->mkdir($this->cachePath);
$finder = Finder::create();
$files = $finder->files()->in($this->cachePath)->name('*.json');
foreach ($files as $file) {
$this->filesystem->remove($file);
}
}
/**
* @param string $cacheKey
*
* @return string
*/
private function getCacheFilePath($cacheKey)
{
return $this->cachePath . $cacheKey . '.json';
}
}

View File

@@ -0,0 +1,58 @@
<?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\PrestashopFacebook\Provider;
use FacebookAds\Object\Values\ProductItemAvailabilityValues;
use Product;
use StockAvailable;
class ProductAvailabilityProvider implements ProductAvailabilityProviderInterface
{
/**
* @param int $productId
* @param int $productAttributeId
*
* @return string
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException
*/
public function getProductAvailability($productId, $productAttributeId)
{
$product = new Product($productId);
if ((int) StockAvailable::getQuantityAvailableByProduct($productId, $productAttributeId)) {
return ProductItemAvailabilityValues::IN_STOCK;
}
switch ($product->out_of_stock) {
case 1:
return ProductItemAvailabilityValues::AVAILABLE_FOR_ORDER;
case 2:
$isAvailable = Product::isAvailableWhenOutOfStock($product->out_of_stock);
return $isAvailable ? ProductItemAvailabilityValues::AVAILABLE_FOR_ORDER : ProductItemAvailabilityValues::OUT_OF_STOCK;
case 0:
default:
return ProductItemAvailabilityValues::OUT_OF_STOCK;
}
}
}

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\PrestashopFacebook\Provider;
interface ProductAvailabilityProviderInterface
{
/**
* @param int $productId
*
* @return string
*/
public function getProductAvailability($productId, $productAttributeId);
}

View File

@@ -0,0 +1,107 @@
<?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\PrestashopFacebook\Provider;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookAccountException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use Psr\Http\Client\ClientInterface;
class ProductSyncReportProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ClientInterface
*/
private $psApiClient;
/**
* @var ResponseListener
*/
private $responseListener;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ApiClientFactoryInterface $psApiClientFactory,
ResponseListener $responseListener
) {
$this->configurationAdapter = $configurationAdapter;
$this->responseListener = $responseListener;
$this->psApiClient = $psApiClientFactory->createClient();
}
public function getProductSyncReport()
{
$businessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$response = $this->responseListener->handleResponse(
$this->psApiClient->sendRequest(
new Request(
'GET',
"/account/{$businessId}/reporting"
)
),
[
'exceptionClass' => FacebookAccountException::class,
]
);
$responseContent = $response->getBody();
if (!$response->isSuccessful()) {
$responseContent = [];
}
return $this->fixMissingValues($responseContent);
}
private function fixMissingValues($response)
{
if (!isset($response['errors'])) {
$response['errors'] = [];
}
if (!isset($response['lastFinishedSyncStartedAt'])) {
$response['lastFinishedSyncStartedAt'] = 0;
}
$response['errors'] = array_filter($response['errors'], [$this, 'filterErrorsWithoutMessage']);
return $response;
}
/**
* Hotfix as the Nest API should not return products without message
*
* @return bool
*/
private function filterErrorsWithoutMessage(array $productInError)
{
return !empty($productInError);
}
}

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,368 @@
<?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\PrestashopFacebook\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShopCollection;
class GoogleCategoryRepository
{
public const NO_CHILDREN = 0;
public const HAS_CHILDREN = 1;
/**
* @var int
*/
private $homeCategoryId;
public function __construct(ConfigurationAdapter $configurationAdapter)
{
$this->homeCategoryId = (int) $configurationAdapter->get('PS_HOME_CATEGORY');
}
/**
* @param int $categoryId
* @param int $googleCategoryId
* @param string $googleCategoryName
* @param int $googleCategoryParentId
* @param string $googleCategoryParentName
* @param int $shopId
* @param bool $isParentCategory
*
* @throws \PrestaShopDatabaseException
*/
public function updateCategoryMatch(
$categoryId,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId,
$isParentCategory = false
) {
Db::getInstance()->insert(
'fb_category_match',
[
'id_category' => (int) $categoryId,
'google_category_id' => (int) $googleCategoryId,
'google_category_name' => pSQL($googleCategoryName),
'google_category_parent_id' => (int) $googleCategoryParentId,
'google_category_parent_name' => pSQL($googleCategoryParentName),
'is_parent_category' => $isParentCategory,
'id_shop' => (int) $shopId,
],
false,
true,
DB::REPLACE
);
}
/**
* @param PrestaShopCollection $childCategories
* @param int $googleCategoryId
* @param string $googleCategoryName
* @param int $googleCategoryParentId
* @param string $googleCategoryParentName
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function updateCategoryChildrenMatch(
PrestaShopCollection $childCategories,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId
) {
$data = [];
foreach ($childCategories as $category) {
$data[] = [
'id_category' => (int) $category->id,
'google_category_id' => (int) $googleCategoryId,
'google_category_name' => pSQL($googleCategoryName),
'google_category_parent_id' => (int) $googleCategoryParentId,
'google_category_parent_name' => pSQL($googleCategoryParentName),
'is_parent_category' => 1,
'id_shop' => (int) $shopId,
];
}
Db::getInstance()->insert(
'fb_category_match',
$data,
false,
true,
DB::REPLACE
);
}
/**
* @param int $categoryId
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function unsetCategoryMatch(
$categoryId,
$shopId
) {
Db::getInstance()->delete(
'fb_category_match',
'`id_category` = ' . (int) $categoryId . ' AND `id_shop` = ' . (int) $shopId
);
}
/**
* @param PrestaShopCollection $childCategories
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function unsetCategoryChildrenMatch(
PrestaShopCollection $childCategories,
$shopId
) {
foreach ($childCategories as $category) {
$this->unsetCategoryMatch($category->id, $shopId);
}
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return int
*/
public function getGoogleCategoryIdByCategoryId($categoryId, $shopId)
{
$sql = new DbQuery();
$sql->select('google_category_id');
$sql->from('fb_category_match');
$sql->where('`id_category` = "' . (int) $categoryId . '"');
$sql->where('id_shop = ' . (int) $shopId);
return (int) Db::getInstance()->getValue($sql);
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|false
*/
public function getCategoryMatchByCategoryId($categoryId, $shopId)
{
$sql = new DbQuery();
$sql->select('id_category');
$sql->select('google_category_id');
$sql->select('google_category_name');
$sql->select('google_category_parent_id');
$sql->select('google_category_parent_name');
$sql->select('is_parent_category');
$sql->from('fb_category_match');
$sql->where('`id_category` = "' . (int) $categoryId . '"');
$sql->where('id_shop = ' . (int) $shopId);
return Db::getInstance()->getRow($sql);
}
/**
* @param array $categoryIds
* @param int $shopId
*
* @return array|false
*
* @throws \PrestaShopDatabaseException
*/
public function getGoogleCategoryIdsByCategoryIds(array $categoryIds, $shopId)
{
$sql = new DbQuery();
$sql->select('google_category_id');
$sql->from('fb_category_match');
$sql->where('`id_category` IN ("' . implode('", "', $categoryIds) . '")');
$sql->where('id_shop = ' . (int) $shopId);
return Db::getInstance()->executeS($sql);
}
/**
* @param array $categoryIds
* @param int $shopId
*
* @return array|false
*
* @throws \PrestaShopDatabaseException
*/
public function getCategoryMatchesByCategoryIds(array $categoryIds, $shopId)
{
$sql = new DbQuery();
$sql->select('id_category');
$sql->select('google_category_id');
$sql->select('google_category_parent_id');
$sql->select('is_parent_category');
$sql->from('fb_category_match');
$sql->where('`id_category` IN ("' . implode('", "', $categoryIds) . '")');
$sql->where('id_shop = ' . (int) $shopId);
return Db::getInstance()->executeS($sql);
}
public function getFilteredCategories($parentCategoryId, $langId, $offset, $limit, $shopId)
{
$sql = new DbQuery();
$sql->select('c.id_category as shopCategoryId');
$sql->select('cl.name as shopCategoryName');
$sql->select('cm.google_category_id as googleCategoryId');
$sql->select('cm.google_category_name as googleCategoryName');
$sql->select('cm.google_category_parent_id as googleCategoryParentId');
$sql->select('cm.google_category_parent_name as googleCategoryParentName');
$sql->select('cm.is_parent_category as isParentCategory');
$sql->select('case when c.nleft = c.nright -1 and c.`level_depth` = ' . Config::MAX_CATEGORY_DEPTH .
' then ' . self::NO_CHILDREN . ' else ' . self::HAS_CHILDREN . ' end deploy');
$sql->from('category', 'c');
$sql->innerJoin('category_shop', 'cs', 'cs.id_category = c.id_category');
$sql->innerJoin('category_lang', 'cl', 'c.id_category = cl.id_category AND cl.id_lang = ' . (int) $langId);
$sql->leftJoin(
'fb_category_match',
'cm',
'cm.id_category = c.id_category AND cm.id_shop = ' . (int) $shopId
);
$sql->where('cs.id_shop = ' . (int) $shopId);
$sql->where(
'c.`id_parent` = ' . (int) $parentCategoryId . ' OR
(
c.`nleft` > (SELECT pc.`nleft` from `' . _DB_PREFIX_ . 'category` as pc WHERE pc.id_category = '
. (int) $parentCategoryId . ' AND pc.`level_depth` >= ' . Config::MAX_CATEGORY_DEPTH . ') AND
c.`nright` < (SELECT pc.`nright` from `' . _DB_PREFIX_ . 'category` as pc WHERE pc.id_category = '
. (int) $parentCategoryId . ' AND pc.`level_depth` >= ' . Config::MAX_CATEGORY_DEPTH . ')
)'
);
$sql->groupBy('c.id_category');
$sql->limit($limit, $offset);
return Db::getInstance()->executeS($sql);
}
/**
* @param int $shopId
*
* @return bool
*
* @throws \PrestaShopDatabaseException
*/
public function areParentCategoriesMatched($shopId)
{
$sql = new DbQuery();
$sql->select('c.id_category');
$sql->from('category', 'c');
$sql->innerJoin('category_shop', 'cs', 'cs.id_category = c.id_category');
$sql->leftJoin('fb_category_match', 'cm', 'cm.id_category = c.id_category AND cm.id_shop = cs.id_shop');
$sql->where("c.id_parent = {$this->homeCategoryId} AND cm.google_category_id IS NULL");
$sql->where('cs.id_shop = ' . (int) $shopId);
return (bool) Db::getInstance()->executeS($sql);
}
/**
* @param int $langId
* @param int $shopId
*
* @return array
*
* @throws \PrestaShopDatabaseException
*/
public function getCategoriesWithParentInfo($langId, $shopId)
{
$query = new DbQuery();
$query->select('c.id_category, cl.name, c.id_parent')
->from('category', 'c')
->leftJoin(
'category_lang',
'cl',
'cl.id_category = c.id_category AND cl.id_shop = ' . (int) $shopId
)
->where('cl.id_lang = ' . (int) $langId)
->orderBy('cl.id_category');
$result = Db::getInstance()->executeS($query);
if ($result) {
return $result;
} else {
throw new \PrestaShopDatabaseException('No categories found');
}
}
/**
* @param int $shopId
*
* @return bool
*
* @throws \PrestaShopDatabaseException
*/
public function isMatchingDone($shopId)
{
$sql = new DbQuery();
$sql->select('cm.id_category');
$sql->from('fb_category_match', 'cm');
$sql->where('cm.id_shop = ' . (int) $shopId);
return (bool) Db::getInstance()->executeS($sql);
}
/**
* @param int $shopId
*
* @return int
*/
public function getNumberOfMatchedCategories($shopId)
{
$sql = new DbQuery();
$sql->select('cm.id_category');
$sql->from('fb_category_match', 'cm');
$sql->where('cm.id_shop = ' . (int) $shopId);
Db::getInstance()->execute($sql);
return Db::getInstance()->numRows();
}
/**
* @param int $shopId
*
* @return int
*/
public function getNumberOfTotalCategories($shopId)
{
$sql = new DbQuery();
$sql->select('c.id_category');
$sql->from('category', 'c');
$sql->innerJoin('category_shop', 'cp', 'cp.id_category = c.id_category');
$sql->where('cp.id_shop = ' . (int) $shopId . ' AND c.id_parent >=' . (int) $this->homeCategoryId);
Db::getInstance()->execute($sql);
return Db::getInstance()->numRows();
}
}

View File

@@ -0,0 +1,359 @@
<?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\PrestashopFacebook\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\EventBusProduct;
use PrestaShop\Module\Ps_facebook\Utility\ProductCatalogUtility;
use PrestaShopException;
use Product;
class ProductRepository
{
/**
* @var \Language
*/
private $language;
public function __construct(\Language $language)
{
$this->language = $language;
}
/**
* Copy of prestashop Product::getIdProductAttributeByIdAttributes function
* because old PS versions are missing this function
*
* Get an id_product_attribute by an id_product and one or more
* id_attribute.
*
* e.g: id_product 8 with id_attribute 4 (size medium) and
* id_attribute 5 (color blue) returns id_product_attribute 9 which
* is the dress size medium and color blue.
*
* @param int $idProduct
* @param int|int[] $idAttributes
* @param bool $findBest
*
* @return int
*
* @throws PrestaShopException
*/
public function getIdProductAttributeByIdAttributes($idProduct, $idAttributes, $findBest = false)
{
$idProduct = (int) $idProduct;
if (!is_array($idAttributes) && is_numeric($idAttributes)) {
$idAttributes = [(int) $idAttributes];
}
if (!is_array($idAttributes) || empty($idAttributes)) {
throw new PrestaShopException(sprintf('Invalid parameter $idAttributes with value: "%s"', print_r($idAttributes, true)));
}
$idAttributesImploded = implode(',', array_map('intval', $idAttributes));
$idProductAttribute = Db::getInstance()->getValue(
'
SELECT
pac.`id_product_attribute`
FROM
`' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.id_product_attribute = pac.id_product_attribute
WHERE
pa.id_product = ' . $idProduct . '
AND pac.id_attribute IN (' . $idAttributesImploded . ')
GROUP BY
pac.`id_product_attribute`
HAVING
COUNT(pa.id_product) = ' . count($idAttributes)
);
if ($idProductAttribute === false && $findBest) {
//find the best possible combination
//first we order $idAttributes by the group position
$orderred = [];
$result = Db::getInstance()->executeS(
'
SELECT
a.`id_attribute`
FROM
`' . _DB_PREFIX_ . 'attribute` a
INNER JOIN `' . _DB_PREFIX_ . 'attribute_group` g ON a.`id_attribute_group` = g.`id_attribute_group`
WHERE
a.`id_attribute` IN (' . $idAttributesImploded . ')
ORDER BY
g.`position` ASC'
);
foreach ($result as $row) {
$orderred[] = $row['id_attribute'];
}
while ($idProductAttribute === false && count($orderred) > 0) {
array_pop($orderred);
$idProductAttribute = Db::getInstance()->getValue(
'
SELECT
pac.`id_product_attribute`
FROM
`' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.id_product_attribute = pac.id_product_attribute
WHERE
pa.id_product = ' . (int) $idProduct . '
AND pac.id_attribute IN (' . implode(',', array_map('intval', $orderred)) . ')
GROUP BY
pac.id_product_attribute
HAVING
COUNT(pa.id_product) = ' . count($orderred)
);
}
}
if (empty($idProductAttribute)) {
throw new PrestaShopException('Can not retrieve the id_product_attribute');
}
return (int) $idProductAttribute;
}
public function getProductsWithErrors($shopId, $page = -1)
{
$sql = new DbQuery();
$sql->select('ps.id_product');
$sql->select('IF(pas.id_product_attribute IS NULL, 0, id_product_attribute) as id_product_attribute');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
$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 . ' AND ps.active = 1');
$result = Db::getInstance()->executeS($sql);
$productIdsWithInvalidSalePrice = [0];
$productAttributeIdsWithInvalidSalePrice = [0];
foreach ($result as $product) {
$salePriceTaxExcluded = $this->getSalePriceTaxExcluded($product['id_product'], $product['id_product_attribute']);
if ($salePriceTaxExcluded <= 0) {
$productIdsWithInvalidSalePrice[] = $product['id_product'];
$productAttributeIdsWithInvalidSalePrice[] = $product['id_product_attribute'];
}
}
$sql = new DbQuery();
$sql->select('ps.id_product, pas.id_product_attribute, pl.name');
$sql->select('pl.id_lang, l.iso_code as language');
$sql->select('
IF((m.name = "" OR m.name IS NULL) AND p.ean13 = "" AND p.upc = "" AND p.isbn = "", false, true) as has_manufacturer_or_ean_or_upc_or_isbn
');
$sql->select('IF(is.id_image IS NOT NULL, true, false) as has_cover');
$sql->select('IF(pl.link_rewrite = "" OR pl.link_rewrite is NULL, false, true) as has_link');
$sql->select('IF(ps.price + IFNULL(pas.price, 0) > 0, true, false) as has_price_tax_excl');
$sql->select('IF((pl.description_short = "" OR pl.description_short IS NULL) AND (pl.description = "" OR pl.description IS NULL), false, true) as has_description_or_short_description');
$sql->select('true as correct_sales_price');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = ps.id_product AND pl.id_shop = ps.id_shop');
$sql->innerJoin('lang', 'l', 'l.id_lang = pl.id_lang');
$sql->leftJoin('product_attribute_shop', 'pas', 'pas.id_product = ps.id_product AND pas.id_shop = ps.id_shop');
$sql->leftJoin('manufacturer', 'm', 'm.id_manufacturer = p.id_manufacturer');
$sql->leftJoin('image_shop', 'is', 'is.id_product = ps.id_product AND is.id_shop = ps.id_shop AND is.cover = 1');
$sql->where('ps.id_shop = ' . (int) $shopId . ' AND ps.active = 1');
$sql->where('
(m.name = "" OR m.name IS NULL) AND p.ean13 = "" AND p.upc = "" AND p.isbn = ""
OR ((pl.description_short = "" OR pl.description_short IS NULL) AND (pl.description = "" OR pl.description IS NULL))
OR is.id_image is NULL
OR pl.link_rewrite = "" OR pl.link_rewrite is NULL
OR ps.price + IFNULL(pas.price, 0) <= 0
OR pl.name = "" OR pl.name is NULL
OR
(
ps.id_product in (' . implode(',', $productIdsWithInvalidSalePrice) . ') AND
(
pas.id_product_attribute in (' . implode(',', $productAttributeIdsWithInvalidSalePrice) . ') OR
pas.id_product_attribute IS NULL
)
)
');
$sql->orderBy('p.id_product ASC, pas.id_product_attribute ASC, language ASC');
if ($page > -1) {
$sql->limit(Config::REPORTS_PER_PAGE, Config::REPORTS_PER_PAGE * ($page));
}
$result = Db::getInstance()->executeS($sql);
foreach ($result as $key => &$value) {
if (!in_array($value['id_product'], $productIdsWithInvalidSalePrice)) {
continue;
}
if (in_array($value['id_product_attribute'], $productAttributeIdsWithInvalidSalePrice)
|| $value['id_product_attribute'] === null) {
$value['correct_sales_price'] = false;
}
}
return $result;
}
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');
$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'];
}
/**
* @param EventBusProduct $eventBusProduct
* @param int $shopId
* @param string $isoCode
*
* @return array|bool|\mysqli_result|\PDOStatement|resource|null
*
* @throws \PrestaShopDatabaseException
*/
public function getInformationAboutEventBusProduct(EventBusProduct $eventBusProduct, $shopId, $isoCode)
{
$sql = new DbQuery();
$sql->select('pa.id_product, pa.id_product_attribute, pl.name');
$sql->select('l.iso_code');
$sql->from('product_attribute', 'pa');
$sql->innerJoin('lang', 'l', 'l.iso_code = "' . pSQL($isoCode) . '"');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = pa.id_product AND pl.id_lang = l.id_lang');
$sql->where('pa.id_product = ' . (int) $eventBusProduct->getProductId());
$sql->where('pa.id_product_attribute = ' . (int) $eventBusProduct->getProductAttributeId());
$sql->where('pl.id_shop = ' . (int) $shopId);
return Db::getInstance()->executeS($sql);
}
/**
* @param string $syncUpdateDate
* @param int $shopId
* @param array $productsWithErrors
* @param int|false $page
* @param string|null $status
* @param string|null $sortBy
* @param string $sortTo
* @param int|bool $searchById
* @param string|bool $searchByName
* @param string|bool $searchByMessage
*
* @return array|bool|\mysqli_result|\PDOStatement|resource|null
*
* @throws \PrestaShopDatabaseException
*/
public function getInformationAboutEventBusProducts(
$syncUpdateDate,
$shopId,
$productsWithErrors,
$page = false,
$status = null,
$sortBy = null,
$sortTo = 'ASC',
$searchById = false,
$searchByName = false,
$searchByMessage = false
) {
$sql = new DbQuery();
$sql->select('ps.id_product, pa.id_product_attribute, pl.name, ps.date_upd');
$sql->select('
IF(CONCAT_WS("-", ps.id_product, IFNULL(pa.id_product_attribute, "0")) IN ( "' . implode('","', $productsWithErrors) . '"), "disapproved",
IF(ps.date_upd <= "' . pSQL($syncUpdateDate) . '", "approved", "pending" )
) as status
');
$sql->from('product_shop', 'ps');
$sql->leftJoin('product_attribute', 'pa', 'pa.id_product = ps.id_product');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = ps.id_product');
$sql->where('pl.id_shop = ' . (int) $shopId);
$sql->where('CONCAT_WS("-", ps.id_product, IFNULL(pa.id_product_attribute, 0)) IN ( "' . implode('","', $productsWithErrors) . '")');
// GROUP BY Id product AND ID combination of attributes
$sql->groupBy('ps.id_product');
$sql->groupBy('pa.id_product_attribute');
if ($page !== false) {
$sql->limit(Config::REPORTS_PER_PAGE, Config::REPORTS_PER_PAGE * ($page - 1));
}
if ($sortBy) {
$sql->orderBy(pSQL($sortBy) . ' ' . pSQL($sortTo));
}
if ($searchById) {
$sql->where('ps.id_product LIKE "%' . (int) $searchById . '%"');
}
if ($searchByName) {
$sql->where('pl.name LIKE "%' . pSQL($searchByName) . '%"');
}
if ($searchByMessage) {
$sql->where('ps.id_product LIKE "%' . (int) $searchByMessage . '%"');
}
if ($status) {
$sql->having('ps.id_product LIKE "%' . pSQL($status) . '%"');
}
$result = Db::getInstance()->executeS($sql);
$products = [];
foreach ($result as $product) {
$eventBusProductId = ProductCatalogUtility::makeProductId(
$product['id_product'],
$product['id_product_attribute']
);
$products[$eventBusProductId] = $product;
}
return $products;
}
/**
* @param int $productId
* @param int $attributeId
*
* @return float
*/
public function getSalePriceTaxExcluded($productId, $attributeId)
{
return Product::getPriceStatic($productId, false, $attributeId, 6);
}
}

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\PrestashopFacebook\Repository;
use Exception;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class ServerInformationRepository
{
/**
* @var bool
*/
private $isPsAccountsOnboarded;
public function __construct(PsAccounts $psAccountsFacade)
{
try {
$this->isPsAccountsOnboarded = (bool) $psAccountsFacade->getPsAccountsService()->getOrRefreshToken();
} catch (Exception $e) {
$this->isPsAccountsOnboarded = false;
}
}
/**
* @return array
*/
public function getHealthCheckData()
{
$isFacebookSystemTokenSet = false;
if (\Configuration::get(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN)) {
$isFacebookSystemTokenSet = true;
}
return [
'ps_accounts' => \Module::isInstalled('ps_accounts'),
'ps_accounts_onboarded' => $this->isPsAccountsOnboarded,
'ps_eventbus' => \Module::isInstalled('ps_eventbus'),
'ps_facebook_system_token_set' => $isFacebookSystemTokenSet,
'pixel_enabled' => (bool) \Configuration::get(Config::PS_FACEBOOK_PIXEL_ENABLED),
'pixel_id' => (bool) \Configuration::get(Config::PS_PIXEL_ID),
'profile_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_PROFILES),
'page_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_PAGES),
'business_manager_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID),
'ad_account_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_AD_ACCOUNT_ID),
'catalog_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_CATALOG_ID),
'env' => [
'PSX_FACEBOOK_API_URL' => isset($_ENV['PSX_FACEBOOK_API_URL']) ? $_ENV['PSX_FACEBOOK_API_URL'] : null,
'ACCOUNTS_SVC_API_URL' => isset($_ENV['ACCOUNTS_SVC_API_URL']) ? $_ENV['ACCOUNTS_SVC_API_URL'] : null,
'EVENT_BUS_PROXY_API_URL' => isset($_ENV['EVENT_BUS_PROXY_API_URL']) ? $_ENV['EVENT_BUS_PROXY_API_URL'] : null,
'EVENT_BUS_SYNC_API_URL' => isset($_ENV['EVENT_BUS_SYNC_API_URL']) ? $_ENV['EVENT_BUS_SYNC_API_URL'] : null,
],
];
}
}

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\PrestashopFacebook\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PrestashopFacebook\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::PS_FACEBOOK_USER_ACCESS_TOKEN . '"');
return Db::getInstance()->executeS($sql);
}
public function getDefaultCategoryShop()
{
$sql = new DbQuery();
$sql->select('id_category');
$sql->from('shop');
return Db::getInstance()->executeS($sql)[0];
}
}

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\PrestashopFacebook\Repository;
use Db;
use DbQuery;
class TabRepository
{
public function hasChildren($tabId)
{
$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,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,221 @@
<?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\Ps_facebook\Tracker;
use Context;
use Exception;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class Segment implements TrackerInterface
{
/**
* @var string
*/
private $message = '';
/**
* @var array
*/
private $options = [];
/**
* @var Context
*/
private $context;
/**
* @var Env
*/
private $env;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var string
*/
private $userId;
public function __construct(Context $context, Env $env, ConfigurationAdapter $configurationAdapter, PsAccounts $psAccountsFacade)
{
$this->context = $context;
$this->env = $env;
$this->init();
$this->configurationAdapter = $configurationAdapter;
try {
$this->userId = $psAccountsFacade->getPsAccountsService()->getShopUuidV4();
} catch (Exception $e) {
}
}
/**
* Init segment client with the api key
*/
private function init()
{
\Segment::init($this->env->get('PSX_FACEBOOK_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($domainName)
{
if (empty($this->userId)) {
return;
}
$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]";
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
\Segment::track([
'userId' => $this->userId,
'event' => $this->message,
'channel' => 'browser',
'context' => [
'ip' => $ip,
'userAgent' => $userAgent,
'locale' => $this->context->language->iso_code,
'page' => [
'referrer' => $referer,
'url' => $url,
],
'externalBusinessId' => $externalBusinessId,
'name' => $domainName,
],
'properties' => array_merge([
'module' => 'ps_facebook',
], $this->options),
]);
\Segment::flush();
}
/**
* Handle tracking differently depending on the shop context
*
* @return mixed
*/
private function dispatchTrack()
{
$dictionary = [
\Shop::CONTEXT_SHOP => function () {
return self::trackShop();
},
\Shop::CONTEXT_GROUP => function () {
return self::trackShopGroup();
},
\Shop::CONTEXT_ALL => function () {
return self::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\Ps_facebook\Tracker;
interface TrackerInterface
{
/**
* @return void
*/
public function track();
}

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,76 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\Ps_facebook\Utility;
use Customer;
use FacebookAds\Object\ServerSide\Gender;
use Tools;
class CustomerInformationUtility
{
public static function getCustomerInformationForPixel(Customer $customer)
{
$simpleAddresses = $customer->getSimpleAddresses();
$arrayReturned = [];
if (count($simpleAddresses) > 0) {
$address = reset($simpleAddresses);
$arrayReturned['city'] = $address['city'] ? Tools::strtolower($address['city']) : null;
$arrayReturned['countryIso'] = $address['country_iso'] ? Tools::strtolower($address['country_iso']) : null;
$arrayReturned['postCode'] = $address['postcode'] ? Tools::strtolower($address['postcode']) : null;
$arrayReturned['phone'] = $address['phone'] ?
preg_replace('/[^0-9.]+/', '', $address['phone'])
: null;
$arrayReturned['stateIso'] = $address['state_iso'] ? Tools::strtolower($address['state_iso']) : null;
} else {
$arrayReturned['city'] = null;
$arrayReturned['countryIso'] = null;
$arrayReturned['postCode'] = null;
$arrayReturned['phone'] = null;
$arrayReturned['stateIso'] = null;
}
$gender = null;
if ($customer->id_gender !== 0) {
$genderObj = new \Gender($customer->id_gender);
if ($genderObj->type !== 2) {
$gender = (int) $genderObj->type === 0 ? Gender::MALE : Gender::FEMALE;
}
}
$arrayReturned['gender'] = $gender;
$birthDate = \DateTime::createFromFormat('Y-m-d', $customer->birthday);
if ($birthDate instanceof \DateTime) {
$arrayReturned['birthday'] = $birthDate->format('Ymd');
} else {
$arrayReturned['birthday'] = null;
}
$arrayReturned['firstname'] = $customer->firstname ? Tools::strtolower($customer->firstname) : null;
$arrayReturned['lastname'] = $customer->firstname ? Tools::strtolower($customer->lastname) : null;
$arrayReturned['email'] = $customer->firstname ? Tools::strtolower($customer->email) : null;
return $arrayReturned;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\Ps_facebook\Utility;
use PrestaShop\Module\PrestashopFacebook\DTO\EventBusProduct;
class EventBusProductUtility
{
/**
* @param string $eventBusProduct
*
* @return EventBusProduct
*/
public static function eventBusProductToObject($eventBusProduct)
{
$eventBusProductSplitted = explode('-', $eventBusProduct);
$eventBusProductObj = new EventBusProduct();
$eventBusProductObj->setProductId((int) $eventBusProductSplitted[EventBusProduct::POSITION_PRODUCT_ID]);
$eventBusProductObj->setProductAttributeId((int) $eventBusProductSplitted[EventBusProduct::POSITION_PRODUCT_ATTRIBUTE_ID]);
return $eventBusProductObj;
}
}

View File

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

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
*/
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