Subida del módulo y tema de PrestaShop

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

View File

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

View File

@@ -0,0 +1,89 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API\Client;
use PrestaShop\Module\PrestashopFacebook\API\EventSubscriber\ApiErrorSubscriber;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Http\HttpClient;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class FacebookCategoryClient
{
/**
* @var HttpClient
*/
private $client;
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
GoogleCategoryRepository $googleCategoryRepository
) {
$this->client = $apiClientFactory->createClient();
$this->googleCategoryRepository = $googleCategoryRepository;
}
/**
* @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
);
$response = $this->client->get("/{$id}" . http_build_query($query));
if (!$response->isSuccessful()) {
(new ApiErrorSubscriber())->onParsedResponse($response, ['exceptionClass' => FacebookClientException::class]);
}
return $response->getBody();
}
}

View File

@@ -0,0 +1,399 @@
<?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 PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\EventSubscriber\ApiErrorSubscriber;
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\Http\HttpClient;
use PrestaShop\Module\PrestashopFacebook\Provider\AccessTokenProvider;
class FacebookClient
{
/**
* @var string
*/
private $accessToken;
/**
* @var string
*/
private $systemToken;
/**
* @var string
*/
private $sdkVersion;
/**
* @var HttpClient
*/
private $client;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ConfigurationHandler
*/
private $configurationHandler;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
AccessTokenProvider $accessTokenProvider,
ConfigurationAdapter $configurationAdapter,
ConfigurationHandler $configurationHandler
) {
$this->accessToken = $accessTokenProvider->getUserAccessToken();
$this->systemToken = $accessTokenProvider->getSystemAccessToken();
$this->sdkVersion = Config::API_VERSION;
$this->client = $apiClientFactory->createClient();
$this->configurationAdapter = $configurationAdapter;
$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,
]
);
if (!is_array($responseContent)) {
return [];
}
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 array
*
* @throws Exception
*/
private function get($id, $callerFunction, array $fields = [], array $query = [])
{
$query = array_merge(
[
'access_token' => $this->accessToken,
'fields' => implode(',', $fields),
],
$query
);
$response = $this->client->get("/{$this->sdkVersion}/{$id}", $query);
$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);
}
(new ApiErrorSubscriber())->onParsedResponse($response, ['exceptionClass' => FacebookClientException::class]);
}
return $responseContent;
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return 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 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 array
*/
private function sendRequest($id, array $headers, array $body, $method)
{
$body = array_merge(
[
'access_token' => $this->systemToken,
],
$body
);
$this->client->setHeaders($headers);
$response = $this->client->request($method, "/{$this->sdkVersion}/{$id}", $body);
if (!$response->isSuccessful()) {
(new ApiErrorSubscriber())->onParsedResponse($response, ['exceptionClass' => FacebookClientException::class]);
}
return $response->getBody();
}
}

View File

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

View File

@@ -0,0 +1,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\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Domain\Http\Response;
class AccountSuspendedSubscriber
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(ConfigurationAdapter $configurationAdapter)
{
$this->configurationAdapter = $configurationAdapter;
}
public function onParsedResponse(Response $response): void
{
$suspension = $response->getHeader('X-Account-Suspended') ?: $response->getHeader('x-account-suspended');
if (!empty($suspension)) {
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_SUSPENSION_REASON, $suspension);
}
}
}

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\API\EventSubscriber;
use Exception;
use PrestaShop\Module\PrestashopFacebook\Domain\Http\Response;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
class ApiErrorSubscriber
{
public function onParsedResponse(Response $response, array $options): void
{
$class = $options['exceptionClass'] ?: Exception::class;
(new ErrorHandler())->handle(
new $class(
$this->getMessage($response)
),
$response->getStatusCode(),
false,
[
'extra' => $response->getBody(),
]
);
}
private function getMessage(Response $response)
{
$body = $response->getBody();
// If there is a error object returned by the Facebook API, use their codes
if (!empty($body['error']['code']) && !empty($body['error']['error_subcode']) && !empty($body['error']['type'])) {
return 'Facebook API errored with ' . $body['error']['type'] . ' (' . $body['error']['code'] . ' / ' . $body['error']['error_subcode'] . ')';
}
if (!empty($body['error']['code']) && !empty($body['error']['type'])) {
return 'Facebook API errored with ' . $body['error']['type'] . ' (' . $body['error']['code'] . ')';
}
return 'API errored with HTTP ' . $response->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
*/
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,63 @@
<?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 PrestaShop\Module\PrestashopFacebook\Http\HttpClient;
class BillingAdapter
{
private const BILLING_URL = 'https://billing-api.distribution.prestashop.net/v1/';
/**
* @var string
*/
private $jwt;
/**
* @var bool
*/
private $isSandbox;
public function __construct($jwt, $isSandbox)
{
$this->jwt = $jwt;
$this->isSandbox = $isSandbox;
}
public function getCurrentSubscription($shopId, $productId)
{
$httpClient = new HttpClient(self::BILLING_URL);
$headers = [
'Accept: application/json',
'Authorization: Bearer ' . $this->jwt,
'Content-Type: application/json',
'User-Agent : module-lib-billing v3 (' . $productId . ')',
];
if ($this->isSandbox === true) {
$headers[] = 'sandbox: true';
}
$httpClient->setHeaders($headers);
return $httpClient->get('/customers/' . $shopId . '/subscriptions/' . $productId);
}
}

View File

@@ -0,0 +1,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,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
*/
declare(strict_types=1);
namespace PrestaShop\Module\PrestashopFacebook\Buffer;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;
class TemplateBuffer
{
/**
* @var Session
*/
private $session;
/**
* @param string $userId
*/
public function init($userId)
{
$this->session = new Session(
new MockFileSessionStorage(
\_PS_CACHE_DIR_ . '/ps_facebook_sessions',
'pixel'
)
);
$this->session->setId($userId);
$this->session->start();
register_shutdown_function([$this, 'save']);
}
/**
* add data to the buffer
*
* @param string $data
*
* @return void
*/
public function add($data)
{
$this->session->getFlashBag()->add('pixel_events', $data);
}
/**
* reset buffer content
*
* @return void
*/
public function clean()
{
$this->session->getFlashBag()->get('pixel_events', []);
}
/**
* return buffer content and reset it
*
* @return string
*/
public function flush()
{
$data = '';
foreach ($this->session->getFlashBag()->get('pixel_events', []) as $message) {
$data .= $message;
}
return $data;
}
public function save(): void
{
$this->session->save();
}
}

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,89 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Config;
class Config
{
public const API_VERSION = 'v19.0';
public const COMPLIANT_PS_ACCOUNTS_VERSION = '3.0.0';
public const REQUIRED_PS_ACCOUNTS_VERSION = '4.0.0';
public const REQUIRED_PS_CLOUDSYNC_VERSION = '1.9.4';
public const USE_LOCAL_VUE_APP = false;
public const USE_LIVE_VUE_APP = false;
public const USE_BILLING_SANDBOX = false;
public const PSX_FACEBOOK_CDN_URL = 'https://storage.googleapis.com/psxfacebook/v1.x.x/js/';
public const HOOK_LIST = [
'displayHeader',
'actionCustomerAccountAdd',
'actionCartSave',
'actionSearch',
'displayOrderConfirmation',
'actionAjaxDieProductControllerDisplayAjaxQuickviewAfter',
'actionObjectCustomerMessageAddAfter',
'displayFooter',
'actionNewsletterRegistrationAfter',
'displayBackOfficeHeader',
'actionFrontControllerSetMedia',
'actionFacebookCallPixel',
];
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 = ['page_cta', 'page_shop'/*, 'ig_shopping'*/];
public const CONFIGURABLE_FBE_FEATURES = [];
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://c5dacaa8aca74c458179b113b646774c@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('[FBK] PS Social with Facebook & Instagram 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 & Instagram',
'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,160 @@
<?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 TabRepository
*/
private $tabRepository;
/**
* @var Segment
*/
private $segment;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var FacebookClient
*/
private $facebookClient;
public function __construct(
TabRepository $tabRepository,
Segment $segment,
ErrorHandler $errorHandler,
FacebookClient $facebookClient
) {
$this->tabRepository = $tabRepository;
$this->segment = $segment;
$this->errorHandler = $errorHandler;
$this->facebookClient = $facebookClient;
}
/**
* @return bool
*
* @throws Exception
*/
public function uninstall()
{
$this->segment->setMessage('[FBK] PS Social with Facebook & Instagram 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
);
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
);
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,98 @@
<?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 string
*/
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);
}
return $this->pixelHandler->handleEvent($eventData, $name);
}
}

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

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 PrestaShop\Module\PrestashopFacebook\Http\HttpClient;
interface ApiClientFactoryInterface
{
/**
* @return HttpClient
*/
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,39 @@
<?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\Http\HttpClient;
class FacebookEssentialsApiClientFactory implements ApiClientFactoryInterface
{
public const API_URL = 'https://graph.facebook.com';
public function createClient()
{
$httpClient = new HttpClient(self::API_URL);
$httpClient->setHeaders([
'Accept: application/json',
'Content-Type: application/json',
]);
return $httpClient;
}
}

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 PrestaShop\Module\PrestashopFacebook\Config\Env;
class ParametersFactory
{
public static function getBillingEnv()
{
return (bool) (new Env())->get('USE_BILLING_SANDBOX');
}
}

View File

@@ -0,0 +1,61 @@
<?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\Module\PrestashopFacebook\Http\HttpClient;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class PsApiClientFactory implements ApiClientFactoryInterface
{
/**
* @var string
*/
private $baseUrl;
/**
* @var PsAccounts
*/
private $psAccountsFacade;
public function __construct(
Env $env,
PsAccounts $psAccountsFacade
) {
$this->baseUrl = $env->get('PSX_FACEBOOK_API_URL');
$this->psAccountsFacade = $psAccountsFacade;
}
/**
* {@inheritdoc}
*/
public function createClient()
{
$client = new HttpClient($this->baseUrl);
$client->setHeaders([
'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,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\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 (Config::AVAILABLE_FBE_FEATURES as $featureName) {
$dataConfigurationKeys[] = Config::FBE_FEATURE_CONFIGURATION . $featureName;
}
foreach ($dataConfigurationKeys as $key) {
$this->configurationAdapter->deleteByName($key);
}
}
}

View File

@@ -0,0 +1,146 @@
<?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 Context;
use Exception;
use Module;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
use Ps_facebook;
/**
* Handle Error.
*/
class ErrorHandler
{
/**
* @var ModuleFilteredRavenClient
*/
protected $client;
public function __construct()
{
/** @var Ps_facebook $module */
$module = Module::getInstanceByName('ps_facebook');
$env = new 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,
],
'release' => "v{$module->version}",
'error_types' => E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED & ~E_NOTICE & ~E_USER_NOTICE,
'sample_rate' => $this->isContextInFrontOffice($module->getContext()) ? 0.2 : 1,
]
);
try {
$psAccountsService = $module->getService(PsAccounts::class)->getPsAccountsService();
$this->client->user_context([
'id' => $psAccountsService->getShopUuidV4(),
]);
} catch (Exception $e) {
// Do nothing
}
// We use realpath to get errors even if module is behind a symbolic link
$this->client->setAppPath(realpath(_PS_MODULE_DIR_ . $module->name . '/'));
// - Do no not add the shop root folder, it will exclude everything even if specified in the app path.
// - Excluding vendor/ avoids errors comming from one of your libraries library when called by another module.
$this->client->setExcludedAppPaths([
realpath(_PS_MODULE_DIR_ . $module->name . '/vendor/'),
]);
$this->client->setExcludedDomains(['127.0.0.1', 'localhost', '.local']);
// 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()
{
}
/**
* @return bool
*/
private function isContextInFrontOffice(Context $context = null)
{
/*
Some shops have trouble to refresh the cache of the service container.
To avoid issues on production after an upgrade, context has been made optional.
ToDo: Remove the nullable later.
*/
if (!$context) {
return false;
}
/** @var \Controller|null $controller */
$controller = $context->controller;
if (!$controller) {
return false;
}
return in_array($controller->controller_type, ['front', 'modulefront']);
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\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)
{
$lastFrame = end($data['stacktrace']['frames']);
$lastFrameIsInApp = (isset($lastFrame['in_app']) && $lastFrame['in_app']);
return $lastFrameIsInApp;
}
/**
* 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,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,197 @@
<?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 Context;
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;
$this->templateBuffer->init($this->findIdentifierFromContext($this->context));
}
/**
* @param array|bool $params
* @param string $hookName
*
* @return string
*/
public function handleEvent($params, $hookName)
{
$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);
}
$content = '';
if ($hookName === 'hookDisplayHeader') {
$this->context->smarty->assign($smartyVariables);
$content .= $this->module->display($this->module->getfilePath(), 'views/templates/hook/header.tpl');
}
$this->context->smarty->assign($smartyVariables);
$this->templateBuffer->add($this->module->display($this->module->getfilePath(), 'views/templates/hook/fbTrack.tpl'));
// Return the existing content in case we have a display hook
if (strpos($hookName, 'Display') === 4 && !$this->isCurrentRequestAnAjax()) {
$content .= $this->templateBuffer->flush();
}
return $content;
}
/**
* 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'])),
];
}
/**
* @return bool
*/
private function isCurrentRequestAnAjax()
{
/*
* An ajax property is available in controllers
* preventing the whole page template to be generated.
*/
if ($this->context->controller->ajax) {
return true;
}
/*
* In case the ajax property is not properly set, there is
* another check available.
*/
if ($this->context->controller->isXmlHttpRequest()) {
return true;
}
return false;
}
/**
* @return string
*/
private function findIdentifierFromContext(Context $context)
{
if (!empty($context->customer->id_guest)) {
return 'guest_' . $context->customer->id_guest;
}
if (!empty($context->cart->id)) {
return 'cart_' . $context->cart->id;
}
return '';
}
}

View File

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

View File

@@ -0,0 +1,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
*/
declare(strict_types=1);
namespace PrestaShop\Module\PrestashopFacebook\Domain\Http;
class Response
{
/** @var int */
private $statusCode;
/** @var string */
private $body;
/** @var array<string,string> */
private $headers;
/**
* @param int $statusCode
* @param string $body
* @param array<string,string> $headers
**/
public function __construct($statusCode, $body, $headers = [])
{
$this->statusCode = $statusCode;
$this->body = $body;
$this->headers = $headers;
}
/**
* @return int
*/
public function getStatusCode()
{
return $this->statusCode;
}
/**
* @return array<string,string>
*/
public function getHeaders()
{
return $this->headers;
}
public function getHeader($headerName)
{
return $this->headers[$headerName] ?? null;
}
/**
* @return array
*/
public function getBody()
{
return json_decode($this->body, true);
}
public function isSuccessful()
{
return substr((string) $this->statusCode, 0, 1) == '2';
}
}

View File

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

View File

@@ -0,0 +1,83 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Manager;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use stdClass;
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 && !in_array($featureName, Config::CONFIGURABLE_FBE_FEATURES)) {
return false;
}
$featureConfiguration = json_decode($featureConfiguration);
if ($featureConfiguration === null) {
$featureConfiguration = new stdClass();
}
if ($featureName == 'messenger_chat') {
unset($featureConfiguration->default_locale);
/* @see https://developers.facebook.com/docs/facebook-business-extension/fbe/reference#FBEMessengerChatConfigData */
$featureConfiguration->domains = [
\Tools::getShopDomainSsl(true),
];
}
$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,168 @@
<?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 PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
class AccessTokenProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var Controller|null
*/
private $controller;
/**
* @var ApiClientFactoryInterface
*/
private $psApiClientFactory;
/**
* @var string
*/
private $userAccessToken;
/**
* @var string|null
*/
private $systemAccessToken;
public function __construct(
ConfigurationAdapter $configurationAdapter,
$controller,
ApiClientFactoryInterface $psApiClientFactory
) {
$this->configurationAdapter = $configurationAdapter;
$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->psApiClientFactory->createClient()->post('/account/' . $externalBusinessId . '/exchange_tokens', json_encode([
'userAccessToken' => $accessToken,
'businessManagerId' => $managerId,
]));
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->psApiClientFactory->createClient()->get('/account/' . $externalBusinessId . '/app_tokens');
if (!$response->isSuccessful()) {
return null;
}
return $response->getBody();
}
}

View File

@@ -0,0 +1,572 @@
<?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 Currency;
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');
$changesDiscount = $this->toolsAdapter->getValue('addDiscount')
|| $this->toolsAdapter->getValue('deleteDiscount');
if ($attributeGroups) {
try {
$idProductAttribute = $this->productRepository->getIdProductAttributeByIdAttributes(
$idProduct,
$attributeGroups
);
} catch (PrestaShopException $e) {
return false;
}
}
if ($action !== 'update' || $changesDiscount) {
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';
}
$productName = Product::getProductName($idProduct, $idProductAttribute);
$cartId = $this->context->cookie->id_cart ?? null;
$customData = [
'content_name' => pSQL($productName),
'content_type' => self::PRODUCT_TYPE,
'content_ids' => [
ProductCatalogUtility::makeProductId(
$idProduct,
$idProductAttribute
),
],
'currency' => $this->getCurrency(),
'value' => $this->productRepository->getSalePrice($idProduct, $idProductAttribute, $cartId),
];
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);
$numberOfItems = array_sum(array_column($contents, 'quantity'));
$customData = [
'contents' => $contents,
'content_type' => 'product',
'currency' => $this->getCurrency(),
'value' => $cart->getOrderTotal(false),
'num_items' => $numberOfItems,
];
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) {
if (class_exists('\ProductAttribute')) {
$attributes[] = (new \ProductAttribute($attributeId, $idLang))->name;
} elseif (class_exists('\AttributeCore')) {
$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(): string
{
if (!empty($this->context->currency->iso_code)) {
return \Tools::strtolower($this->context->currency->iso_code);
}
if (!empty($this->context->cookie->id_currency)) {
return \Tools::strtolower((new Currency($this->context->cookie->id_currency))->iso_code);
}
return \Tools::strtolower(Currency::getDefaultCurrency()->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,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;
class FbeFeatureDataProvider
{
const RETURN_STATUS_FROM_DATABASE_INSTEAD_OF_API = true;
/**
* @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 = [];
$disabledFeatures = [];
$enabledFeatures = [];
$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->updateValue(Config::FBE_FEATURE_CONFIGURATION . $featureName, json_encode($feature));
}
$featureDetailsInDatabase = $this->configurationAdapter->get(Config::FBE_FEATURE_CONFIGURATION . $featureName);
if ($featureDetailsInDatabase !== false) {
// @phpstan-ignore-next-line
$enabledFeatures[$featureName] = self::RETURN_STATUS_FROM_DATABASE_INSTEAD_OF_API
? json_decode($featureDetailsInDatabase, true)
: $feature;
} else {
$disabledFeatures[$featureName] = $feature;
}
}
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('[FBK] 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,87 @@
<?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;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Http\HttpClient;
class ProductSyncReportProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var HttpClient
*/
private $psApiClient;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ApiClientFactoryInterface $psApiClientFactory
) {
$this->configurationAdapter = $configurationAdapter;
$this->psApiClient = $psApiClientFactory->createClient();
}
public function getProductSyncReport()
{
$businessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$response = $this->psApiClient->get("/account/{$businessId}/reporting");
$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' => (bool) $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('", "', array_map('intval', $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('", "', array_map('intval', $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 + 1 = c.nright 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 = ' . (int) $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,121 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Repository;
use Context;
use Module;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
class ModuleRepository
{
/**
* @var string
*/
private $moduleName;
public function __construct(string $moduleName)
{
$this->moduleName = $moduleName;
}
/**
* @return string|null
*/
public function getModuleVersion()
{
/** @var Module|null $module */
$module = Module::getInstanceByName($this->moduleName);
if (!empty($module)) {
return $module->version;
}
return null;
}
/**
* @return string
*/
public function getUpgradeLink()
{
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'upgrade',
'module_name' => $this->moduleName,
]);
}
/**
* @return string
*/
public function getEnableLink()
{
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'enable',
'module_name' => $this->moduleName,
]);
}
/**
* @return array
*/
public function getInformationsAboutModule(): array
{
return [
'version' => $this->getModuleVersion(),
'upgradeLink' => $this->getUpgradeLink(),
'hooks' => $this->getActiveHooks(),
];
}
/**
* @return bool
*/
public function moduleIsEnabled(): bool
{
return Module::isEnabled($this->moduleName);
}
/**
* @return array
*/
public function getActiveHooks(): array
{
$context = Context::getContext();
$hooks = [];
/** @var Module|null $moduleInstance */
$moduleInstance = Module::getInstanceByName($this->moduleName);
if (empty($moduleInstance)) {
return $hooks;
}
foreach (Config::HOOK_LIST as $hook) {
$hooks[$hook] = \Hook::isModuleRegisteredOnHook($moduleInstance, $hook, $context->shop->id);
}
return $hooks;
}
}

View File

@@ -0,0 +1,376 @@
<?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;
use Validate;
class ProductRepository
{
/**
* 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 AND l.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->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->where('ps.id_shop = ' . (int) $shopId);
$sql->where('l.active = 1');
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('","', array_map('pSQL', $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('","', array_map('pSQL', $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 && Validate::isOrderBy($sortBy) && Validate::isOrderWay($sortTo)) {
$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);
}
/**
* @param int $productId
* @param int $attributeId
* @param int|null $id_cart Needed to avoid a Fatal Error from PrestaShop
*
* @return float
*/
public function getSalePrice($productId, $attributeId, $id_cart = null)
{
return Product::getPriceStatic(
$productId,
true,
$attributeId,
6,
null,
false,
true,
1,
false,
null,
$id_cart
);
}
}

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->lastname ? Tools::strtolower($customer->lastname) : null;
$arrayReturned['email'] = $customer->email ? 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;

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;