first commit

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

View File

@@ -0,0 +1,110 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API\Client;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
use Psr\Http\Client\ClientInterface;
class FacebookCategoryClient
{
/**
* @var ClientInterface
*/
private $client;
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
/**
* @var ResponseListener
*/
private $responseListener;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
GoogleCategoryRepository $googleCategoryRepository,
ResponseListener $responseListener
) {
$this->client = $apiClientFactory->createClient();
$this->googleCategoryRepository = $googleCategoryRepository;
$this->responseListener = $responseListener;
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId)
{
$googleCategoryId = $this->googleCategoryRepository->getGoogleCategoryIdByCategoryId($categoryId, $shopId);
if (empty($googleCategoryId)) {
return null;
}
$googleCategory = $this->get('taxonomy/' . $googleCategoryId);
if (!is_array($googleCategory)) {
return null;
}
return reset($googleCategory);
}
protected function get($id, array $fields = [], array $query = [])
{
$query = array_merge(
[
'fields' => implode(',', $fields),
],
$query
);
$request = new Request(
'GET',
"/{$id}",
[
'query' => $query,
]
);
$response = $this->responseListener->handleResponse(
$this->client->sendRequest($request),
[
'exceptionClass' => FacebookClientException::class,
]
);
if (!$response->isSuccessful()) {
return false;
}
return $response->getBody();
}
}

View File

@@ -0,0 +1,419 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API\Client;
use Exception;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Ad;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\FacebookBusinessManager;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Page;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Pixel;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\User;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Handler\ConfigurationHandler;
use PrestaShop\Module\PrestashopFacebook\Provider\AccessTokenProvider;
use Psr\Http\Client\ClientInterface;
class FacebookClient
{
/**
* @var string
*/
private $accessToken;
/**
* @var string
*/
private $sdkVersion;
/**
* @var ClientInterface
*/
private $client;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ConfigurationHandler
*/
private $configurationHandler;
/**
* @var ResponseListener
*/
private $responseListener;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
AccessTokenProvider $accessTokenProvider,
ConfigurationAdapter $configurationAdapter,
ConfigurationHandler $configurationHandler,
ResponseListener $responseListener
) {
$this->accessToken = $accessTokenProvider->getUserAccessToken();
$this->sdkVersion = Config::API_VERSION;
$this->client = $apiClientFactory->createClient();
$this->configurationAdapter = $configurationAdapter;
$this->configurationHandler = $configurationHandler;
$this->responseListener = $responseListener;
}
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}
/**
* @return bool
*/
public function hasAccessToken()
{
return (bool) $this->accessToken;
}
public function getUserEmail()
{
$responseContent = $this->get('me', __FUNCTION__, ['email']);
return new User(
isset($responseContent['email']) ? $responseContent['email'] : null
);
}
/**
* @param string $businessManagerId
*
* @return FacebookBusinessManager
*/
public function getBusinessManager($businessManagerId)
{
$responseContent = $this->get($businessManagerId, __FUNCTION__, ['name', 'created_time']);
return new FacebookBusinessManager(
isset($responseContent['id']) ? $responseContent['id'] : $businessManagerId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
/**
* @param string $adId
* @param string $pixelId
*
* @see https://developers.facebook.com/docs/marketing-api/reference/ad-account/adspixels/?locale=en_US
*
* @return Pixel
*/
public function getPixel($adId, $pixelId)
{
$name = $lastFiredTime = null;
$isUnavailable = false;
if (!empty($adId)) {
$responseContent = $this->get('act_' . $adId . '/adspixels', __FUNCTION__, ['name', 'last_fired_time', 'is_unavailable']);
if (isset($responseContent['data'])) {
foreach ($responseContent['data'] as $adPixel) {
if ($adPixel['id'] !== $pixelId) {
continue;
}
$name = isset($adPixel['name']) ? $adPixel['name'] : null;
$lastFiredTime = isset($adPixel['last_fired_time']) ? $adPixel['last_fired_time'] : null;
$isUnavailable = isset($adPixel['is_unavailable']) ? $adPixel['is_unavailable'] : null;
}
}
}
return new Pixel(
$pixelId,
$name,
$lastFiredTime,
$isUnavailable,
(bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PIXEL_ENABLED)
);
}
/**
* @param array $pageIds
*
* @return Page
*/
public function getPage(array $pageIds)
{
$pageId = reset($pageIds);
$responseContent = $this->get($pageId, __FUNCTION__, ['name', 'fan_count']);
$logoResponse = $this->get($pageId . '/photos', __FUNCTION__ . 'Photo', ['picture']);
$logo = null;
if (is_array($logoResponse)) {
$logo = reset($logoResponse['data'])['picture'];
}
return new Page(
isset($responseContent['id']) ? $responseContent['id'] : $pageIds,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['fan_count']) ? $responseContent['fan_count'] : null,
$logo
);
}
/**
* @param string $adId
*
* @return Ad
*/
public function getAd($adId)
{
$responseContent = $this->get('act_' . $adId, __FUNCTION__, ['name', 'created_time']);
return new Ad(
isset($responseContent['id']) ? $responseContent['id'] : $adId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
public function getFbeAttribute($externalBusinessId)
{
$responseContent = $this->get(
'fbe_business/fbe_installs',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
return reset($responseContent['data']);
}
public function getFbeFeatures($externalBusinessId)
{
$response = $this->get(
'fbe_business',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
if (!is_array($response)) {
return [];
}
return $response;
}
public function updateFeature($externalBusinessId, $configuration)
{
$body = [
'fbe_external_business_id' => $externalBusinessId,
'business_config' => $configuration,
];
return $this->post(
'fbe_business',
[],
$body
);
}
/**
* @see https://developers.facebook.com/docs/marketing-api/fbe/fbe2/guides/uninstall?locale=en_US#uninstall-fbe--v2-for-businesses
*
* @return false|array
*/
public function uninstallFbe()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$accessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$this->configurationHandler->cleanOnboardingConfiguration();
$this->accessToken = '';
$body = [
'fbe_external_business_id' => $externalBusinessId,
'access_token' => $accessToken,
];
return $this->delete(
'fbe_business/fbe_installs',
[],
$body
);
}
/**
* @param int $catalogId
*
* @return array|false
*/
public function getProductsInCatalogCount($catalogId)
{
$body = [
'fields' => 'product_count',
];
return $this->post(
$catalogId,
[],
$body
);
}
public function disconnectFromFacebook()
{
$this->uninstallFbe();
$this->configurationHandler->cleanOnboardingConfiguration();
}
public function addFbeAttributeIfMissing(array &$onboardingParams)
{
if (!empty($onboardingParams['fbe']) && !isset($onboardingParams['fbe']['error'])) {
return;
}
$this->setAccessToken($onboardingParams['access_token']);
$onboardingParams['fbe'] = $this->getFbeAttribute($this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID));
}
/**
* @param string $id
* @param string $callerFunction
* @param array $fields
* @param array $query
*
* @return false|array
*
* @throws Exception
*/
private function get($id, $callerFunction, array $fields = [], array $query = [])
{
$query = array_merge(
[
'access_token' => $this->accessToken,
'fields' => implode(',', $fields),
],
$query
);
$request = new Request(
'GET',
"/{$this->sdkVersion}/{$id}?" . http_build_query($query)
);
$response = $this->responseListener->handleResponse(
$this->client->sendRequest($request),
[
'exceptionClass' => FacebookClientException::class,
]
);
$responseContent = $response->getBody();
if (!$response->isSuccessful()) {
$exceptionCode = false;
if (!empty($responseContent['error']['code'])) {
$exceptionCode = $responseContent['error']['code'];
}
if ($exceptionCode && in_array($exceptionCode, Config::OAUTH_EXCEPTION_CODE)) {
$this->disconnectFromFacebook();
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_FORCED_DISCONNECT, true);
}
return false;
}
return $responseContent;
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function post($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'POST');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function delete($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'DELETE');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
* @param string $method
*
* @return false|array
*/
private function sendRequest($id, array $headers, array $body, $method)
{
$body = array_merge(
[
'access_token' => $this->accessToken,
],
$body
);
$request = new Request(
$method,
"/{$this->sdkVersion}/{$id}",
$headers,
json_encode($body)
);
$response = $this->responseListener->handleResponse(
$this->client->sendRequest($request),
[
'exceptionClass' => FacebookClientException::class,
]
);
if (!$response->isSuccessful()) {
return false;
}
return $response->getBody();
}
}

View File

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

View File

@@ -0,0 +1,73 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API\EventSubscriber;
use Exception;
use PrestaShop\Module\PrestashopFacebook\API\ParsedResponse;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
class ApiErrorSubscriber implements SubscriberInterface
{
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(ErrorHandler $errorHandler)
{
$this->errorHandler = $errorHandler;
}
public function onParsedResponse(ParsedResponse $response, array $options): void
{
if ($response->isSuccessful()) {
return;
}
$class = $options['exceptionClass'] ?: Exception::class;
// TODO: Error sent to the error handler can be improved from the response content
$this->errorHandler->handle(
new $class(
$this->getMessage($response)
),
$response->getResponse()->getStatusCode(),
false,
[
'extra' => $response->getBody(),
]
);
}
private function getMessage(ParsedResponse $response)
{
$body = $response->getBody();
// If there is a error object returned by the Facebook API, use their codes
if (!empty($body['code']) && !empty($body['error_subcode']) && !empty($body['type'])) {
return 'Facebook API errored with ' . $body['type'] . ' (' . $body['code'] . ' / ' . $body['error_subcode'] . ')';
}
if (!empty($body['code']) && !empty($body['type'])) {
return 'Facebook API errored with ' . $body['type'] . ' (' . $body['code'] . ')';
}
return 'API errored with HTTP ' . $response->getResponse()->getStatusCode();
}
}

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,132 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class FacebookCategoryClient
{
/**
* @var Client
*/
private $client;
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
/**
* @var ErrorHandler
*/
private $errorHandler;
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
GoogleCategoryRepository $googleCategoryRepository,
ErrorHandler $errorHandler
) {
$this->client = $apiClientFactory->createClient();
$this->googleCategoryRepository = $googleCategoryRepository;
$this->errorHandler = $errorHandler;
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId)
{
$googleCategoryId = $this->googleCategoryRepository->getGoogleCategoryIdByCategoryId($categoryId, $shopId);
if (empty($googleCategoryId)) {
return null;
}
$googleCategory = $this->get('taxonomy/' . $googleCategoryId);
if (!is_array($googleCategory)) {
return null;
}
return reset($googleCategory);
}
protected function get($id, array $fields = [], array $query = [])
{
$query = array_merge(
[
'fields' => implode(',', $fields),
],
$query
);
try {
$request = $this->client->createRequest(
'GET',
"/{$id}",
[
'query' => $query,
]
);
$response = $this->client->send($request);
} catch (ClientException $e) {
$exceptionContent = json_decode($e->getResponse()->getBody()->getContents(), true);
$this->errorHandler->handle(
new FacebookClientException(
'Facebook category client failed when creating get request.',
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false,
[
'extra' => $exceptionContent,
]
);
return false;
} catch (Exception $e) {
$this->errorHandler->handle(
new FacebookClientException(
'Facebook category client failed when creating get request.',
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return json_decode($response->getBody()->getContents(), true);
}
}

View File

@@ -0,0 +1,476 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Ad;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\FacebookBusinessManager;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Page;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Pixel;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\User;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookClientException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use PrestaShop\Module\PrestashopFacebook\Handler\ConfigurationHandler;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
use PrestaShop\Module\PrestashopFacebook\Provider\AccessTokenProvider;
class FacebookClient
{
/**
* @var string
*/
private $accessToken;
/**
* @var string
*/
private $sdkVersion;
/**
* @var Client
*/
private $client;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var ConfigurationHandler
*/
private $configurationHandler;
/**
* @param ApiClientFactoryInterface $apiClientFactory
* @param AccessTokenProvider $accessTokenProvider
* @param ConfigurationAdapter $configurationAdapter
* @param ErrorHandler $errorHandler
* @param ConfigurationHandler $configurationHandler
*/
public function __construct(
ApiClientFactoryInterface $apiClientFactory,
AccessTokenProvider $accessTokenProvider,
ConfigurationAdapter $configurationAdapter,
ErrorHandler $errorHandler,
ConfigurationHandler $configurationHandler
) {
$this->accessToken = $accessTokenProvider->getUserAccessToken();
$this->sdkVersion = Config::API_VERSION;
$this->client = $apiClientFactory->createClient();
$this->configurationAdapter = $configurationAdapter;
$this->errorHandler = $errorHandler;
$this->configurationHandler = $configurationHandler;
}
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}
/**
* @return bool
*/
public function hasAccessToken()
{
return (bool) $this->accessToken;
}
public function getUserEmail()
{
$responseContent = $this->get('me', __FUNCTION__, ['email']);
return new User(
isset($responseContent['email']) ? $responseContent['email'] : null
);
}
/**
* @param string $businessManagerId
*
* @return FacebookBusinessManager
*/
public function getBusinessManager($businessManagerId)
{
$responseContent = $this->get($businessManagerId, __FUNCTION__, ['name', 'created_time']);
return new FacebookBusinessManager(
isset($responseContent['id']) ? $responseContent['id'] : $businessManagerId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
/**
* @param string $adId
* @param string $pixelId
*
* @see https://developers.facebook.com/docs/marketing-api/reference/ad-account/adspixels/?locale=en_US
*
* @return Pixel
*/
public function getPixel($adId, $pixelId)
{
$name = $lastFiredTime = null;
$isUnavailable = false;
if (!empty($adId)) {
$responseContent = $this->get('act_' . $adId . '/adspixels', __FUNCTION__, ['name', 'last_fired_time', 'is_unavailable']);
if (isset($responseContent['data'])) {
foreach ($responseContent['data'] as $adPixel) {
if ($adPixel['id'] !== $pixelId) {
continue;
}
$name = isset($adPixel['name']) ? $adPixel['name'] : null;
$lastFiredTime = isset($adPixel['last_fired_time']) ? $adPixel['last_fired_time'] : null;
$isUnavailable = isset($adPixel['is_unavailable']) ? $adPixel['is_unavailable'] : null;
}
}
}
return new Pixel(
$pixelId,
$name,
$lastFiredTime,
$isUnavailable,
(bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PIXEL_ENABLED)
);
}
/**
* @param array $pageIds
*
* @return Page
*/
public function getPage(array $pageIds)
{
$pageId = reset($pageIds);
$responseContent = $this->get($pageId, __FUNCTION__, ['name', 'fan_count']);
$logoResponse = $this->get($pageId . '/photos', __FUNCTION__ . 'Photo', ['picture']);
$logo = null;
if (is_array($logoResponse)) {
$logo = reset($logoResponse['data'])['picture'];
}
return new Page(
isset($responseContent['id']) ? $responseContent['id'] : $pageIds,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['fan_count']) ? $responseContent['fan_count'] : null,
$logo
);
}
/**
* @param string $adId
*
* @return Ad
*/
public function getAd($adId)
{
$responseContent = $this->get('act_' . $adId, __FUNCTION__, ['name', 'created_time']);
return new Ad(
isset($responseContent['id']) ? $responseContent['id'] : $adId,
isset($responseContent['name']) ? $responseContent['name'] : null,
isset($responseContent['created_time']) ? $responseContent['created_time'] : null
);
}
public function getFbeAttribute($externalBusinessId)
{
$responseContent = $this->get(
'fbe_business/fbe_installs',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
return reset($responseContent['data']);
}
public function getFbeFeatures($externalBusinessId)
{
$response = $this->get(
'fbe_business',
__FUNCTION__,
[],
[
'fbe_external_business_id' => $externalBusinessId,
]
);
if (!is_array($response)) {
return [];
}
return $response;
}
public function updateFeature($externalBusinessId, $configuration)
{
$body = [
'fbe_external_business_id' => $externalBusinessId,
'business_config' => $configuration,
];
return $this->post(
'fbe_business',
[],
$body
);
}
/**
* @see https://developers.facebook.com/docs/marketing-api/fbe/fbe2/guides/uninstall?locale=en_US#uninstall-fbe--v2-for-businesses
*
* @return false|array
*/
public function uninstallFbe()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$accessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$this->configurationHandler->cleanOnboardingConfiguration();
$this->accessToken = '';
$body = [
'fbe_external_business_id' => $externalBusinessId,
'access_token' => $accessToken,
];
return $this->delete(
'fbe_business/fbe_installs',
[],
$body
);
}
/**
* @param int $catalogId
*
* @return array|false
*/
public function getProductsInCatalogCount($catalogId)
{
$body = [
'fields' => 'product_count',
];
return $this->post(
$catalogId,
[],
$body
);
}
public function disconnectFromFacebook()
{
$this->uninstallFbe();
$this->configurationHandler->cleanOnboardingConfiguration();
}
public function addFbeAttributeIfMissing(array &$onboardingParams)
{
if (!empty($onboardingParams['fbe']) && !isset($onboardingParams['fbe']['error'])) {
return;
}
$this->setAccessToken($onboardingParams['access_token']);
$onboardingParams['fbe'] = $this->getFbeAttribute($this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID));
}
/**
* @param string $id
* @param string $method
* @param array $fields
* @param array $query
*
* @return false|array
*
* @throws Exception
*/
private function get($id, $method, array $fields = [], array $query = [])
{
$query = array_merge(
[
'access_token' => $this->accessToken,
'fields' => implode(',', $fields),
],
$query
);
try {
$request = $this->client->createRequest(
'GET',
"/{$this->sdkVersion}/{$id}",
[
'query' => $query,
]
);
$response = $this->client->send($request);
} catch (ClientException $e) {
$exceptionContent = json_decode($e->getResponse()->getBody()->getContents(), true);
$message = "Facebook client failed when creating get request. Method: {$method}.";
$exceptionCode = false;
if (!empty($exceptionContent['error']['code'])) {
$exceptionCode = $exceptionContent['error']['code'];
$message .= " Code: {$exceptionCode}";
}
if ($exceptionCode && in_array($exceptionCode, Config::OAUTH_EXCEPTION_CODE)) {
$this->disconnectFromFacebook();
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_FORCED_DISCONNECT, true);
return false;
}
$this->errorHandler->handle(
new FacebookClientException(
$message,
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false,
[
'extra' => $exceptionContent,
]
);
return false;
} catch (Exception $e) {
$this->errorHandler->handle(
new FacebookClientException(
'Facebook client failed when creating get request. Method: ' . $method,
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return json_decode($response->getBody()->getContents(), true);
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function post($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'POST');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
*
* @return false|array
*/
private function delete($id, array $headers = [], array $body = [])
{
return $this->sendRequest($id, $headers, $body, 'DELETE');
}
/**
* @param int|string $id
* @param array $headers
* @param array $body
* @param string $method
*
* @return false|array
*/
private function sendRequest($id, array $headers, array $body, $method)
{
$options = [
'headers' => $headers,
'body' => array_merge(
[
'access_token' => $this->accessToken,
],
$body
),
];
try {
$request = $this->client->createRequest(
$method,
"/{$this->sdkVersion}/{$id}",
$options
);
$response = $this->client->send($request);
} catch (ClientException $e) {
$exceptionContent = json_decode($e->getResponse()->getBody()->getContents(), true);
$this->errorHandler->handle(
new FacebookClientException(
'Facebook client failed when creating post request.',
FacebookClientException::FACEBOOK_CLIENT_GET_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false,
[
'extra' => $exceptionContent,
]
);
return false;
} catch (Exception $e) {
$this->errorHandler->handle(
new FacebookClientException(
'Facebook client failed when creating post request.',
FacebookClientException::FACEBOOK_CLIENT_POST_FUNCTION_EXCEPTION,
$e
),
$e->getCode(),
false
);
return false;
}
return json_decode($response->getBody()->getContents(), true);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API;
use Psr\Http\Message\ResponseInterface;
class ParsedResponse
{
/**
* @var ResponseInterface
*/
private $response;
private $body;
public function __construct(ResponseInterface $response)
{
$this->body = json_decode($response->getBody()->getContents(), true);
$this->response = $response;
}
/**
* @return mixed
*/
public function getBody()
{
return $this->body;
}
public function getResponse(): ResponseInterface
{
return $this->response;
}
public function isSuccessful(): bool
{
return $this->responseIsSuccessful($this->response->getStatusCode());
}
public function toArray(): array
{
$responseContents = $this->body;
return [
'isSuccessful' => $this->isSuccessful(),
'httpCode' => $this->response->getStatusCode(),
'body' => $responseContents,
];
}
/**
* Check if the response is successful or not (response code 200 to 299).
*
* @param int $httpStatusCode
*
* @return bool
*/
private function responseIsSuccessful($httpStatusCode)
{
return '2' === substr((string) $httpStatusCode, 0, 1);
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\API;
use PrestaShop\Module\PrestashopFacebook\API\EventSubscriber\SubscriberInterface;
use Psr\Http\Message\ResponseInterface;
class ResponseListener
{
/**
* @var array<SubscriberInterface>
*/
private $subscribers;
public function __construct(array $subscribers)
{
$this->subscribers = $subscribers;
}
/**
* Format api response.
*
* @return ParsedResponse
*/
public function handleResponse(ResponseInterface $response, array $options = [])
{
$parsedResponse = new ParsedResponse($response);
/*
* @var SubscriberInterface
*/
foreach ($this->subscribers as $subscriber) {
$subscriber->onParsedResponse($parsedResponse, $options);
}
return $parsedResponse;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,346 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\DTO;
use JsonSerializable;
class ConfigurationData implements JsonSerializable
{
/**
* @var array
*/
private $contextPsAccounts;
/**
* @var ContextPsFacebook
*/
private $contextPsFacebook;
/**
* @var string
*/
private $psFacebookExternalBusinessId;
/**
* @var string
*/
private $psAccountsToken;
/**
* @var string
*/
private $psFacebookCurrency;
/**
* @var string
*/
private $psFacebookTimezone;
/**
* @var string
*/
private $psFacebookLocale;
/**
* @var string
*/
private $psFacebookPixelActivationRoute;
/**
* @var string
*/
private $psFacebookFbeOnboardingSaveRoute;
/**
* @var string
*/
private $psFacebookFbeUiUrl;
/**
* @var string
*/
private $isoCode;
/**
* @var string
*/
private $languageCode;
/**
* @return array
*/
public function getContextPsAccounts()
{
return $this->contextPsAccounts;
}
/**
* @param array $contextPsAccounts
*
* @return ConfigurationData
*/
public function setContextPsAccounts($contextPsAccounts)
{
$this->contextPsAccounts = $contextPsAccounts;
return $this;
}
/**
* @return ContextPsFacebook
*/
public function getContextPsFacebook()
{
return $this->contextPsFacebook;
}
/**
* @param ContextPsFacebook $contextPsFacebook
*
* @return ConfigurationData
*/
public function setContextPsFacebook($contextPsFacebook)
{
$this->contextPsFacebook = $contextPsFacebook;
return $this;
}
/**
* @return string
*/
public function getPsFacebookExternalBusinessId()
{
return $this->psFacebookExternalBusinessId;
}
/**
* @param string $psFacebookExternalBusinessId
*
* @return ConfigurationData
*/
public function setPsFacebookExternalBusinessId($psFacebookExternalBusinessId)
{
$this->psFacebookExternalBusinessId = $psFacebookExternalBusinessId;
return $this;
}
/**
* @return string
*/
public function getPsAccountsToken()
{
return $this->psAccountsToken;
}
/**
* @param string $psAccountsToken
*
* @return ConfigurationData
*/
public function setPsAccountsToken($psAccountsToken)
{
$this->psAccountsToken = $psAccountsToken;
return $this;
}
/**
* @return string
*/
public function getPsFacebookCurrency()
{
return $this->psFacebookCurrency;
}
/**
* @param string $psFacebookCurrency
*
* @return ConfigurationData
*/
public function setPsFacebookCurrency($psFacebookCurrency)
{
$this->psFacebookCurrency = $psFacebookCurrency;
return $this;
}
/**
* @return string
*/
public function getPsFacebookTimezone()
{
return $this->psFacebookTimezone;
}
/**
* @param string $psFacebookTimezone
*
* @return ConfigurationData
*/
public function setPsFacebookTimezone($psFacebookTimezone)
{
$this->psFacebookTimezone = $psFacebookTimezone;
return $this;
}
/**
* @return string
*/
public function getPsFacebookLocale()
{
return $this->psFacebookLocale;
}
/**
* @param string $psFacebookLocale
*
* @return ConfigurationData
*/
public function setPsFacebookLocale($psFacebookLocale)
{
$this->psFacebookLocale = $psFacebookLocale;
return $this;
}
/**
* @return string
*/
public function getPsFacebookPixelActivationRoute()
{
return $this->psFacebookPixelActivationRoute;
}
/**
* @param string $psFacebookPixelActivationRoute
*
* @return ConfigurationData
*/
public function setPsFacebookPixelActivationRoute($psFacebookPixelActivationRoute)
{
$this->psFacebookPixelActivationRoute = $psFacebookPixelActivationRoute;
return $this;
}
/**
* @return string
*/
public function getPsFacebookFbeOnboardingSaveRoute()
{
return $this->psFacebookFbeOnboardingSaveRoute;
}
/**
* @param string $psFacebookFbeOnboardingSaveRoute
*
* @return ConfigurationData
*/
public function setPsFacebookFbeOnboardingSaveRoute($psFacebookFbeOnboardingSaveRoute)
{
$this->psFacebookFbeOnboardingSaveRoute = $psFacebookFbeOnboardingSaveRoute;
return $this;
}
/**
* @return string
*/
public function getPsFacebookFbeUiUrl()
{
return $this->psFacebookFbeUiUrl;
}
/**
* @param string $psFacebookFbeUiUrl
*
* @return ConfigurationData
*/
public function setPsFacebookFbeUiUrl($psFacebookFbeUiUrl)
{
$this->psFacebookFbeUiUrl = $psFacebookFbeUiUrl;
return $this;
}
/**
* @return string
*/
public function getIsoCode()
{
return $this->isoCode;
}
/**
* @param string $isoCode
*
* @return ConfigurationData
*/
public function setIsoCode($isoCode)
{
$this->isoCode = $isoCode;
return $this;
}
/**
* @return string
*/
public function getLanguageCode()
{
return $this->languageCode;
}
/**
* @param string $languageCode
*
* @return ConfigurationData
*/
public function setLanguageCode($languageCode)
{
$this->languageCode = $languageCode;
return $this;
}
public function jsonSerialize()
{
return [
'contextPsAccounts' => $this->getContextPsAccounts(),
'contextPsFacebook' => $this->getContextPsFacebook(),
'psFacebookExternalBusinessId' => $this->getPsFacebookExternalBusinessId(),
'psAccountsToken' => $this->getPsAccountsToken(),
'psFacebookCurrency' => $this->getPsFacebookCurrency(),
'psFacebookTimezone' => $this->getPsFacebookTimezone(),
'psFacebookLocale' => $this->getPsFacebookLocale(),
'psFacebookPixelActivationRoute' => $this->getPsFacebookPixelActivationRoute(),
'psFacebookFbeOnboardingSaveRoute' => $this->getPsFacebookFbeOnboardingSaveRoute(),
'psFacebookFbeUiUrl' => $this->getPsFacebookFbeUiUrl(),
'i18nSettings' => [
'isoCode' => $this->getIsoCode(),
'languageLocale' => $this->getLanguageCode(),
],
];
}
}

View File

@@ -0,0 +1,214 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\DTO;
use JsonSerializable;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Ad;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Catalog;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\FacebookBusinessManager;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Page;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Pixel;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\User;
class ContextPsFacebook implements JsonSerializable
{
/**
* @var User
*/
private $user;
/**
* @var FacebookBusinessManager|null
*/
private $facebookBusinessManager;
/**
* @var Pixel|null
*/
private $pixel;
/**
* @var Page|null
*/
private $page;
/**
* @var Ad|null
*/
private $ad;
/**
* @var Catalog|null
*/
private $catalog;
/**
* ContextPsFacebook constructor.
*
* @param User $user
* @param FacebookBusinessManager|null $facebookBusinessManager
* @param Pixel|null $pixel
* @param Page|null $page
* @param Ad|null $ad
* @param Catalog|null $catalog
*/
public function __construct($user, $facebookBusinessManager, $pixel, $page, $ad, $catalog)
{
$this->user = $user;
$this->facebookBusinessManager = $facebookBusinessManager;
$this->pixel = $pixel;
$this->page = $page;
$this->ad = $ad;
$this->catalog = $catalog;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param User $user
*
* @return ContextPsFacebook
*/
public function setUser($user)
{
$this->user = $user;
return $this;
}
/**
* @return FacebookBusinessManager|null
*/
public function getFacebookBusinessManager()
{
return $this->facebookBusinessManager;
}
/**
* @param FacebookBusinessManager|null $facebookBusinessManager
*
* @return ContextPsFacebook
*/
public function setFacebookBusinessManager($facebookBusinessManager)
{
$this->facebookBusinessManager = $facebookBusinessManager;
return $this;
}
/**
* @return Pixel|null
*/
public function getPixel()
{
return $this->pixel;
}
/**
* @param Pixel|null $pixel
*
* @return ContextPsFacebook
*/
public function setPixel($pixel)
{
$this->pixel = $pixel;
return $this;
}
/**
* @return Page|null
*/
public function getPage()
{
return $this->page;
}
/**
* @param Page|null $page
*
* @return ContextPsFacebook
*/
public function setPage($page)
{
$this->page = $page;
return $this;
}
/**
* @return Ad|null
*/
public function getAd()
{
return $this->ad;
}
/**
* @param Ad|null $ad
*
* @return ContextPsFacebook
*/
public function setAd($ad)
{
$this->ad = $ad;
return $this;
}
/**
* @return Catalog|null
*/
public function getCatalog()
{
return $this->catalog;
}
/**
* @param Catalog|null $catalog
*
* @return ContextPsFacebook
*/
public function setCatalog($catalog)
{
$this->catalog = $catalog;
return $this;
}
public function jsonSerialize()
{
return [
'user' => $this->getUser(),
'pixel' => $this->getPixel(),
'facebookBusinessManager' => $this->getFacebookBusinessManager(),
'page' => $this->getPage(),
'ads' => $this->getAd(),
'catalog' => $this->getCatalog(),
];
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,97 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Dispatcher;
use Context;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Handler\ApiConversionHandler;
use PrestaShop\Module\PrestashopFacebook\Handler\PixelHandler;
use PrestaShop\Module\PrestashopFacebook\Provider\EventDataProvider;
class EventDispatcher
{
/**
* @var ApiConversionHandler
*/
private $conversionHandler;
/**
* @var PixelHandler
*/
private $pixelHandler;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var EventDataProvider
*/
private $eventDataProvider;
/**
* @var Context
*/
private $context;
public function __construct(
ApiConversionHandler $apiConversionHandler,
PixelHandler $pixelHandler,
ConfigurationAdapter $configurationAdapter,
EventDataProvider $eventDataProvider,
Context $context
) {
$this->conversionHandler = $apiConversionHandler;
$this->pixelHandler = $pixelHandler;
$this->configurationAdapter = $configurationAdapter;
$this->eventDataProvider = $eventDataProvider;
$this->context = $context;
}
/**
* @param string $name
* @param array $params
*
* @return void
*/
public function dispatch($name, array $params)
{
// Events are related to actions on the shop, not the back office
/** @var \Controller|null $controller */
$controller = $this->context->controller;
if (!$controller || !in_array($controller->controller_type, ['front', 'modulefront'])) {
return;
}
if (false === (bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PIXEL_ENABLED)) {
return;
}
$eventData = $this->eventDataProvider->generateEventData($name, $params);
if ($eventData) {
$this->conversionHandler->handleEvent($eventData);
}
$this->pixelHandler->handleEvent($eventData);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

@@ -0,0 +1,66 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Factory;
use Context;
class ContextFactory
{
public static function getContext()
{
return Context::getContext();
}
public static function getLanguage()
{
return Context::getContext()->language;
}
public static function getCurrency()
{
return Context::getContext()->currency;
}
public static function getSmarty()
{
return Context::getContext()->smarty;
}
public static function getShop()
{
return Context::getContext()->shop;
}
public static function getController()
{
return Context::getContext()->controller;
}
public static function getCookie()
{
return Context::getContext()->cookie;
}
public static function getLink()
{
return Context::getContext()->link;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Factory;
use Prestashop\ModuleLibGuzzleAdapter\ClientFactory;
class FacebookEssentialsApiClientFactory implements ApiClientFactoryInterface
{
public const API_URL = 'https://graph.facebook.com';
/**
* @var ClientFactory
*/
private $clientFactory;
public function __construct(ClientFactory $clientFactory)
{
$this->clientFactory = $clientFactory;
}
public function createClient()
{
return $this->clientFactory->getClient([
'base_url' => self::API_URL,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Factory;
use GuzzleHttp\Client;
class GoogleCategoryEssentialsApiClientFactory implements ApiClientFactoryInterface
{
const API_URL = 'https://facebook-api.psessentials.net';
public function createClient()
{
return new Client(['base_url' => self::API_URL]);
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Factory;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
use Prestashop\ModuleLibGuzzleAdapter\ClientFactory;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class PsApiClientFactory implements ApiClientFactoryInterface
{
/**
* @var string
*/
private $baseUrl;
/**
* @var PsAccounts
*/
private $psAccountsFacade;
/**
* @var ClientFactory
*/
private $clientFactory;
public function __construct(
Env $env,
PsAccounts $psAccountsFacade,
ClientFactory $clientFactory
) {
$this->baseUrl = $env->get('PSX_FACEBOOK_API_URL');
$this->psAccountsFacade = $psAccountsFacade;
$this->clientFactory = $clientFactory;
}
/**
* {@inheritdoc}
*/
public function createClient()
{
$client = $this->clientFactory->getClient([
'base_url' => $this->baseUrl,
'timeout' => 10,
'verify' => false,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $this->psAccountsFacade->getPsAccountsService()->getOrRefreshToken(),
],
]);
return $client;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,260 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use FacebookAds\Api;
use FacebookAds\Http\Exception\AuthorizationException;
use FacebookAds\Object\ServerSide\ActionSource;
use FacebookAds\Object\ServerSide\Content;
use FacebookAds\Object\ServerSide\CustomData;
use FacebookAds\Object\ServerSide\Event;
use FacebookAds\Object\ServerSide\EventRequest;
use FacebookAds\Object\ServerSide\UserData;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookConversionAPIException;
use PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler\ErrorHandler;
class ApiConversionHandler
{
/**
* @var false|string
*/
private $pixelId;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var FacebookClient
*/
private $facebookClient;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ErrorHandler $errorHandler,
FacebookClient $facebookClient
) {
$this->configurationAdapter = $configurationAdapter;
$this->errorHandler = $errorHandler;
$this->pixelId = $this->configurationAdapter->get(Config::PS_PIXEL_ID);
Api::init(
null, // app_id
null, // app_secret
$this->configurationAdapter->get(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN),
false
);
$this->facebookClient = $facebookClient;
}
public function handleEvent($params)
{
if (empty($this->pixelId)) {
return;
}
if (isset($params['event_type'])) {
$eventType = $params['event_type'];
}
if (isset($params['event_time'])) {
$eventTime = $params['event_time'];
}
if (isset($params['user'])) {
$userData = $params['user'];
}
if (isset($params['custom_data'])) {
$customData = $params['custom_data'];
}
if (isset($params['event_source_url'])) {
$eventSourceUrl = $params['event_source_url'];
}
if (isset($customData) && isset($customData['contents'])) {
$contentsData = $customData['contents'];
}
if (isset($contentsData)) {
$contents = [];
foreach ($contentsData as $contentData) {
$content = new Content();
if (isset($contentData['id'])) {
$content->setProductId($contentData['id']);
}
if (isset($contentData['title'])) {
$content->setTitle($contentData['title']);
}
if (isset($contentData['category'])) {
$content->setCategory($contentData['category']);
}
if (isset($contentData['item_price'])) {
$content->setItemPrice($contentData['item_price']);
}
if (isset($contentData['brand'])) {
$content->setBrand($contentData['brand']);
}
if (isset($contentData['quantity'])) {
$content->setQuantity($contentData['quantity']);
}
$contents[] = $content;
}
}
if (isset($userData)) {
$user = $this->createSdkUserData($userData);
}
if (isset($customData)) {
$customDataObj = new CustomData();
if (isset($customData['currency'])) {
$customDataObj->setCurrency($customData['currency']);
}
/* more about value here: https://www.facebook.com/business/help/392174274295227?id=1205376682832142 */
if (isset($customData['value'])) {
$customDataObj->setValue($customData['value']);
}
if (isset($contents)) {
$customDataObj->setContents($contents);
}
if (isset($customData['content_type'])) {
$customDataObj->setContentType($customData['content_type']);
}
if (isset($customData['content_name'])) {
$customDataObj->setContentName($customData['content_name']);
}
if (isset($customData['content_category'])) {
$customDataObj->setContentCategory($customData['content_category']);
}
if (isset($customData['content_type'])) {
$customDataObj->setContentType($customData['content_type']);
}
if (isset($customData['content_ids'])) {
$customDataObj->setContentIds($customData['content_ids']);
}
if (isset($customData['num_items'])) {
$customDataObj->setNumItems($customData['num_items']);
}
if (isset($customData['order_id'])) {
$customDataObj->setOrderId($customData['order_id']);
}
if (isset($customData['search_string'])) {
$customDataObj->setSearchString($customData['search_string']);
}
if (isset($customData['custom_properties'])) {
$customDataObj->setCustomProperties($customData['custom_properties']);
}
}
$event = new Event();
if (isset($eventType)) {
$event->setEventName($eventType);
}
if (isset($eventTime)) {
$event->setEventTime($eventTime);
}
if (isset($user)) {
$event->setUserData($user);
}
if (isset($customDataObj)) {
$event->setCustomData($customDataObj);
}
if (isset($eventSourceUrl)) {
$event->setEventSourceUrl($eventSourceUrl);
}
if (isset($params['eventID'])) {
$event->setEventId($params['eventID']);
}
$event->setActionSource(ActionSource::WEBSITE);
$this->sendEvents([$event]);
}
/**
* @return UserData
*/
protected function createSdkUserData($customerInformation)
{
// \Context::getContext()->cookie doesn't have fbp and fbc
$fbp = isset($_COOKIE['_fbp']) ? $_COOKIE['_fbp'] : '';
$fbc = isset($_COOKIE['_fbc']) ? $_COOKIE['_fbc'] : '';
$httpUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
$remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
return (new UserData())
->setFbp($fbp)
->setFbc($fbc)
->setClientIpAddress($remoteAddr)
->setClientUserAgent($httpUserAgent)
->setEmail($customerInformation['email'])
->setFirstName($customerInformation['firstname'])
->setLastName($customerInformation['lastname'])
->setPhone($customerInformation['phone'])
->setDateOfBirth($customerInformation['birthday'])
->setCity($customerInformation['city'])
->setState($customerInformation['stateIso'])
->setZipCode($customerInformation['postCode'])
->setCountryCode($customerInformation['countryIso'])
->setGender($customerInformation['gender']);
}
protected function sendEvents(array $events)
{
$request = (new EventRequest($this->pixelId))
->setEvents($events)
->setPartnerAgent(Config::PS_FACEBOOK_CAPI_PARTNER_AGENT);
// A test event code can be set to check the events are properly sent to Facebook
$testEventCode = $this->configurationAdapter->get(Config::PS_FACEBOOK_CAPI_TEST_EVENT_CODE);
if (!empty($testEventCode)) {
$request->setTestEventCode($testEventCode);
}
try {
$request->execute();
} catch (AuthorizationException $e) {
if (in_array($e->getCode(), Config::OAUTH_EXCEPTION_CODE)) {
$this->facebookClient->disconnectFromFacebook();
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_FORCED_DISCONNECT, true);
return false;
}
} catch (\Exception $e) {
$this->errorHandler->handle(
new FacebookConversionAPIException(
'Failed to send conversion API event',
FacebookConversionAPIException::SEND_EVENT_EXCEPTION,
$e
),
$e->getCode(),
false
);
}
}
}

View File

@@ -0,0 +1,113 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use Category;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class CategoryMatchHandler
{
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
public function __construct(GoogleCategoryRepository $googleCategoryRepository)
{
$this->googleCategoryRepository = $googleCategoryRepository;
}
/**
* @param int $categoryId
* @param int|null $googleCategoryId
* @param string $googleCategoryName
* @param int $googleCategoryParentId
* @param string $googleCategoryParentName
* @param bool $updateChildren
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function updateCategoryMatch(
$categoryId,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$updateChildren,
$shopId
) {
if ($googleCategoryId === null) {
return $this->unsetCategoryMatch($categoryId, $updateChildren, $shopId);
}
if ($updateChildren === true) {
$category = new Category($categoryId);
$categoryChildrenIds = $category->getAllChildren();
$this->googleCategoryRepository->updateCategoryChildrenMatch(
$categoryChildrenIds,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId
);
}
$this->googleCategoryRepository->updateCategoryMatch(
$categoryId,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId,
$updateChildren
);
}
/**
* @param int $categoryId
* @param bool $updateChildren
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function unsetCategoryMatch(
$categoryId,
$updateChildren,
$shopId
) {
if ($updateChildren === true) {
$category = new Category($categoryId);
$categoryChildrenIds = $category->getAllChildren();
$this->googleCategoryRepository->unsetCategoryChildrenMatch(
$categoryChildrenIds,
$shopId
);
}
$this->googleCategoryRepository->unsetCategoryMatch(
$categoryId,
$shopId
);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class ConfigurationHandler
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(
ConfigurationAdapter $configurationAdapter
) {
$this->configurationAdapter = $configurationAdapter;
}
public function handle($onboardingInputs)
{
$this->saveOnboardingConfiguration($onboardingInputs);
}
private function saveOnboardingConfiguration(array $onboardingParams)
{
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_USER_ACCESS_TOKEN, $onboardingParams['access_token']);
$this->configurationAdapter->updateValue(Config::PS_PIXEL_ID, isset($onboardingParams['fbe']['pixel_id']) ? $onboardingParams['fbe']['pixel_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_PROFILES, isset($onboardingParams['fbe']['profiles']) ? implode(',', $onboardingParams['fbe']['profiles']) : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_PAGES, isset($onboardingParams['fbe']['pages']) ? implode(',', $onboardingParams['fbe']['pages']) : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID, isset($onboardingParams['fbe']['business_manager_id']) ? $onboardingParams['fbe']['business_manager_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_AD_ACCOUNT_ID, isset($onboardingParams['fbe']['ad_account_id']) ? $onboardingParams['fbe']['ad_account_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_CATALOG_ID, isset($onboardingParams['fbe']['catalog_id']) ? $onboardingParams['fbe']['catalog_id'] : '');
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_PIXEL_ENABLED, true);
$this->configurationAdapter->deleteByName(Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE);
$this->configurationAdapter->deleteByName(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN);
$this->configurationAdapter->deleteByName(Config::PS_FACEBOOK_CAPI_TEST_EVENT_CODE);
}
public function cleanOnboardingConfiguration()
{
$dataConfigurationKeys = [
Config::PS_FACEBOOK_USER_ACCESS_TOKEN,
Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE,
Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN,
Config::PS_PIXEL_ID,
Config::PS_FACEBOOK_PROFILES,
Config::PS_FACEBOOK_PAGES,
Config::PS_FACEBOOK_BUSINESS_MANAGER_ID,
Config::PS_FACEBOOK_AD_ACCOUNT_ID,
Config::PS_FACEBOOK_CATALOG_ID,
Config::PS_FACEBOOK_PIXEL_ENABLED,
Config::PS_FACEBOOK_CAPI_TEST_EVENT_CODE,
Config::PS_FACEBOOK_PRODUCT_SYNC_FIRST_START,
Config::PS_FACEBOOK_PRODUCT_SYNC_ON,
Config::PS_FACEBOOK_FORCED_DISCONNECT,
Config::PS_FACEBOOK_SUSPENSION_REASON,
];
foreach ($dataConfigurationKeys as $key) {
$this->configurationAdapter->deleteByName($key);
}
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler\ErrorHandler;
use Module;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Config\Env;
/**
* Handle Error.
*/
class ErrorHandler
{
/**
* @var ModuleFilteredRavenClient
*/
protected $client;
public function __construct(Module $module, Env $env)
{
$this->client = new ModuleFilteredRavenClient(
$env->get('PSX_FACEBOOK_SENTRY_CREDENTIALS'),
[
'level' => 'warning',
'tags' => [
'php_version' => phpversion(),
'ps_facebook_version' => $module->version,
'prestashop_version' => _PS_VERSION_,
'ps_facebook_is_enabled' => Module::isEnabled($module->name),
'ps_facebook_is_installed' => Module::isInstalled($module->name),
'facebook_app_id' => Config::PSX_FACEBOOK_APP_ID,
],
'error_types' => E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED & ~E_NOTICE & ~E_USER_NOTICE,
]
);
// We use realpath to get errors even if module is behind a symbolic link
$this->client->setAppPath(realpath(_PS_MODULE_DIR_ . $module->name . '/'));
// - Do no not add the shop root folder, it will exclude everything even if specified in the app path.
// - Excluding vendor/ avoids errors comming from one of your libraries library when called by another module.
$this->client->setExcludedAppPaths([
realpath(_PS_MODULE_DIR_ . $module->name . '/vendor/'),
]);
$this->client->setExcludedDomains(['127.0.0.1', 'localhost', '.local']);
// Other conditions can be done here to prevent the full installation of the client:
// - PHP versions,
// - PS versions,
// - Integration environment,
// - ...
if ($env->get('PSX_FACEBOOK_APP_ID') !== Config::PSX_FACEBOOK_APP_ID) {
return;
}
if (version_compare(phpversion(), '7.4.0', '>=') && version_compare(_PS_VERSION_, '1.7.8.0', '<')) {
return;
}
$this->client->install();
}
/**
* @param \Exception $error
* @param mixed $code
* @param bool|null $throw
* @param array|null $data
*
* @return void
*
* @throws \Exception
*/
public function handle($error, $code = null, $throw = true, $data = null)
{
$this->client->captureException($error, $data);
if ($code && true === $throw) {
http_response_code($code);
throw $error;
}
}
/**
* @return void
*/
private function __clone()
{
}
}

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,93 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use PrestaShop\Module\PrestashopFacebook\Repository\ProductRepository;
use PrestaShop\Module\Ps_facebook\Utility\EventBusProductUtility;
class EventBusProductHandler
{
/**
* @var ProductRepository
*/
private $productRepository;
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* @param array $eventBusProducts
* @param int $shopId
* @param string $isoCode
*
* @return array
*
* @throws \PrestaShopDatabaseException
*/
public function getInformationAboutEventBusProductsWithErrors(array $eventBusProducts, $shopId, $isoCode)
{
$eventBusProductsInformation = [];
foreach ($eventBusProducts as $eventBusProductId => $messages) {
$eventBusProductObj = eventBusProductUtility::eventBusProductToObject($eventBusProductId);
$eventBusProductInfo = $this->productRepository->getInformationAboutEventBusProduct(
$eventBusProductObj,
$shopId,
$isoCode
);
$eventBusProductsInformation[$eventBusProductId] = $eventBusProductInfo ? $eventBusProductInfo[0] : [];
$eventBusProductsInformation[$eventBusProductId]['messages'] = $messages;
}
return $eventBusProductsInformation;
}
/**
* @param array $eventBusProducts
* @param string $lastSyncDate
* @param int $shopId
*
* @return array
*
* @throws \PrestaShopDatabaseException
*/
public function getFilteredInformationAboutEventBusProducts(
array $eventBusProducts,
$lastSyncDate,
$shopId
) {
$formattedSyncTimeDate = date('Y-m-d H:i:s', strtotime($lastSyncDate));
$productsWithErrors = array_keys($eventBusProducts);
$eventBusProductsInfo = $this->productRepository->getInformationAboutEventBusProducts(
$formattedSyncTimeDate,
$shopId,
$productsWithErrors
);
foreach ($eventBusProducts as $eventBusProductId => $messages) {
$eventBusProductsInfo[$eventBusProductId]['messages'] = $messages;
}
return $eventBusProductsInfo;
}
}

View File

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

View File

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

View File

@@ -0,0 +1,135 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use FacebookAds\Object\ServerSide\Normalizer;
use FacebookAds\Object\ServerSide\Util;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Buffer\TemplateBuffer;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class PixelHandler
{
/**
* @var \Context
*/
private $context;
/**
* @var \Ps_facebook
*/
private $module;
/**
* @var TemplateBuffer
*/
private $templateBuffer;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct($module, ConfigurationAdapter $configurationAdapter)
{
$this->context = \Context::getContext();
$this->module = $module;
$this->templateBuffer = $module->templateBuffer;
$this->configurationAdapter = $configurationAdapter;
}
public function handleEvent($params)
{
$pixel_id = $this->configurationAdapter->get(Config::PS_PIXEL_ID);
if (empty($pixel_id)) {
return;
}
$track = 'track';
$eventType = false;
if (isset($params['event_type'])) {
$eventType = $params['event_type'];
}
if (isset($params['user'])) {
$userData = $params['user'];
}
$content = $eventData = [];
if (isset($params['eventID'])) {
$eventData = ['eventID' => $params['eventID']];
}
if (isset($params['custom_data'])) {
$content = $params['custom_data'];
}
$smartyVariables = [
'pixel_fc' => $this->module->front_controller,
'id_pixel' => $pixel_id,
'type' => $eventType,
'content' => $this->formatPixel($content),
'track' => $track,
'eventData' => $this->formatPixel($eventData),
];
if (isset($userData)) {
$smartyVariables['userInfos'] = $this->getCustomerInformation($userData);
}
$this->context->smarty->assign($smartyVariables);
$this->templateBuffer->add($this->module->display($this->module->getfilePath(), 'views/templates/hook/header.tpl'));
}
/**
* formatPixel
*
* @param array $params
*
* @return string|false
*/
protected function formatPixel($params)
{
return json_encode((object) $params);
}
/**
* getCustomerInformation
*
* @param array $customerInformation
*
* @return array
*/
protected function getCustomerInformation($customerInformation)
{
return [
'ct' => Util::hash(Normalizer::normalize('ct', $customerInformation['city'])),
'country' => Util::hash(Normalizer::normalize('country', $customerInformation['countryIso'])),
'zp' => Util::hash(Normalizer::normalize('zp', $customerInformation['postCode'])),
'ph' => Util::hash(Normalizer::normalize('ph', $customerInformation['phone'])),
'gender' => Util::hash(Normalizer::normalize('gender', $customerInformation['gender'])),
'fn' => Util::hash(Normalizer::normalize('fn', $customerInformation['firstname'])),
'ln' => Util::hash(Normalizer::normalize('ln', $customerInformation['lastname'])),
'em' => Util::hash(Normalizer::normalize('em', $customerInformation['email'])),
'bd' => Util::hash(Normalizer::normalize('bd', $customerInformation['birthday'])),
'st' => Util::hash(Normalizer::normalize('st', $customerInformation['stateIso'])),
];
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Handler;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Provider\PrevalidationScanCacheProvider;
use PrestaShop\Module\PrestashopFacebook\Repository\ProductRepository;
class PrevalidationScanRefreshHandler
{
/**
* @var PrevalidationScanCacheProvider
*/
protected $prevalidationScanCacheProvider;
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var int
*/
protected $shopId;
/**
* @param int $shopId
*/
public function __construct(
PrevalidationScanCacheProvider $prevalidationScanCacheProvider,
ProductRepository $productRepository,
$shopId
) {
$this->prevalidationScanCacheProvider = $prevalidationScanCacheProvider;
$this->productRepository = $productRepository;
$this->shopId = $shopId;
}
/**
* @param int $page
*
* @return array
*/
public function run($page = 0)
{
if ($page === 0) {
$this->prevalidationScanCacheProvider->clear();
}
$products = $this->productRepository->getProductsWithErrors($this->shopId, $page);
$this->prevalidationScanCacheProvider->set(
PrevalidationScanCacheProvider::CACHE_KEY_PAGE . $this->shopId . '_' . $page,
json_encode($products)
);
$numberOfProductsWithError = count($products) + Config::REPORTS_PER_PAGE * $page;
if (count($products) === Config::REPORTS_PER_PAGE) {
// We reached the maximum number of results, this is likely meaning
// that we have another page to work with.
return [
'success' => true,
'complete' => false,
'page_done' => $page,
'progress' => $numberOfProductsWithError,
];
}
// This was the last page, we store and return the summary
$summary = $this->generateSummaryData($numberOfProductsWithError);
$this->prevalidationScanCacheProvider->set(
PrevalidationScanCacheProvider::CACHE_KEY_SUMMARY . $this->shopId,
json_encode($summary)
);
return [
'success' => true,
'complete' => true,
'prevalidation' => $summary,
];
}
/**
* @param int $numberOfProductsWithError
*
* @return array
*/
private function generateSummaryData($numberOfProductsWithError)
{
$productsTotal = $this->productRepository->getProductsTotal($this->shopId, ['onlyActive' => true]);
return [
'syncable' => $productsTotal - $numberOfProductsWithError,
'notSyncable' => $numberOfProductsWithError,
'lastScanDate' => date(DATE_ISO8601),
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,105 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Presenter;
use Context;
use Module;
class ModuleUpgradePresenter
{
/**
* @var Context
*/
private $context;
public function __construct($context)
{
$this->context = $context;
}
/**
* Generate the object responsible of displaying the alert when module upgrade is requested
*
* @param string $moduleName
* @param string $versionRequired
*
* @return array
*/
public function generateModuleDependencyVersionCheck($moduleName, $versionRequired)
{
$needsUpgrade = false;
$currentVersion = null;
$moduleInstance = null;
if (Module::isInstalled($moduleName)) {
$moduleInstance = Module::getInstanceByName($moduleName);
if ($moduleInstance !== false) {
$currentVersion = $moduleInstance->version;
$needsUpgrade = version_compare(
$currentVersion,
$versionRequired,
'<'
);
}
}
return [
'needsInstall' => !($moduleInstance && Module::isInstalled($moduleName)),
'needsEnable' => !Module::isEnabled($moduleName),
'needsUpgrade' => $needsUpgrade,
'currentVersion' => $currentVersion,
'requiredVersion' => $versionRequired,
'psFacebookUpgradeRoute' => $this->context->link->getAdminLink(
'AdminAjaxPsfacebook',
true,
[],
[
'action' => 'ManageModule',
'module_action' => 'upgrade',
'module_name' => $moduleName,
'ajax' => 1,
]
),
'psFacebookInstallRoute' => $this->context->link->getAdminLink(
'AdminAjaxPsfacebook',
true,
[],
[
'action' => 'ManageModule',
'module_action' => 'install',
'module_name' => $moduleName,
'ajax' => 1,
]
),
'psFacebookEnableRoute' => $this->context->link->getAdminLink(
'AdminAjaxPsfacebook',
true,
[],
[
'action' => 'ManageModule',
'module_action' => 'enable',
'module_name' => $moduleName,
'ajax' => 1,
]
),
];
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,200 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use Controller;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\AccessTokenException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
class AccessTokenProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var Controller
*/
private $controller;
/**
* @var ApiClientFactoryInterface
*/
private $psApiClientFactory;
/**
* @var ResponseListener
*/
private $responseListener;
/**
* @var string
*/
private $userAccessToken;
/**
* @var string|null
*/
private $systemAccessToken;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ResponseListener $responseListener,
$controller,
ApiClientFactoryInterface $psApiClientFactory
) {
$this->configurationAdapter = $configurationAdapter;
$this->responseListener = $responseListener;
$this->controller = $controller;
$this->psApiClientFactory = $psApiClientFactory;
}
/**
* @return string
*/
public function getUserAccessToken()
{
if (!$this->userAccessToken) {
$this->getOrRefreshTokens();
}
return $this->userAccessToken;
}
/**
* @return string|null
*/
public function getSystemAccessToken()
{
if (!$this->systemAccessToken) {
$this->getOrRefreshTokens();
}
return $this->systemAccessToken;
}
/**
* Load data from configuration table and request from API them if something is missing
*/
private function getOrRefreshTokens()
{
$this->userAccessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$this->systemAccessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN);
$tokenExpirationDate = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE);
$currentTimestamp = time();
if ((!$this->systemAccessToken
|| !$tokenExpirationDate
|| ($tokenExpirationDate - $currentTimestamp <= 86400))
&& isset($this->controller->controller_type)
&& $this->controller->controller_type === 'moduleadmin'
&& $this->userAccessToken
) {
$this->refreshTokens();
}
}
/**
* Exchange existing tokens with new ones, then store them in the DB + make them available in this class
*
* @return void
*/
public function refreshTokens()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$accessToken = $this->configurationAdapter->get(Config::PS_FACEBOOK_USER_ACCESS_TOKEN);
$managerId = $this->configurationAdapter->get(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID);
if (!$managerId) {
// Force as null, otherwise it gets a falsy value in the API request
$managerId = null;
}
$response = $this->responseListener->handleResponse(
$this->psApiClientFactory->createClient()->sendRequest(
new Request(
'POST',
'/account/' . $externalBusinessId . '/exchange_tokens',
[],
json_encode([
'userAccessToken' => $accessToken,
'businessManagerId' => $managerId,
])
)
),
[
'exceptionClass' => AccessTokenException::class,
]
);
if (!$response->isSuccessful()) {
return;
}
$responseContent = $response->getBody();
if (isset($responseContent['longLived']['access_token'])) {
$tokenExpiresIn = time() + (70 * 365 * 24 * 3600); // never expires
$this->userAccessToken = $responseContent['longLived']['access_token'];
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_USER_ACCESS_TOKEN, $this->userAccessToken);
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_USER_ACCESS_TOKEN_EXPIRATION_DATE, $tokenExpiresIn);
}
if (isset($responseContent['system']['access_token'])) {
$this->systemAccessToken = $responseContent['system']['access_token'];
$this->configurationAdapter->updateValue(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN, $this->systemAccessToken);
}
}
/**
* Exchange existing tokens with new ones, then store them in the DB + make them available in this class
*
* @return array|null
*/
public function retrieveTokens()
{
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$response = $this->responseListener->handleResponse(
$this->psApiClientFactory->createClient()->sendRequest(
new Request(
'GET',
'/account/' . $externalBusinessId . '/app_tokens'
)
),
[
'exceptionClass' => AccessTokenException::class,
]
);
if (!$response->isSuccessful()) {
return null;
}
return $response->getBody();
}
}

View File

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

View File

@@ -0,0 +1,92 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\Client\FacebookClient;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\ContextPsFacebook;
use PrestaShop\Module\PrestashopFacebook\DTO\Object\Catalog;
class FacebookDataProvider
{
/**
* @var FacebookClient
*/
protected $facebookClient;
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
public function __construct(FacebookClient $facebookClient, ConfigurationAdapter $configurationAdapter)
{
$this->facebookClient = $facebookClient;
$this->configurationAdapter = $configurationAdapter;
}
/**
* https://github.com/facebookarchive/php-graph-sdk
* https://developers.facebook.com/docs/graph-api/changelog/version8.0
**
* @param array $fbe
*
* @return ContextPsFacebook|null
*/
public function getContext(array $fbe)
{
if (isset($fbe['error']) || !$this->facebookClient->hasAccessToken()) {
return null;
}
$externalBusinessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$hasFbeFeatures = (bool) $this->facebookClient->getFbeFeatures($externalBusinessId);
if (!$hasFbeFeatures) {
return null;
}
$user = $this->facebookClient->getUserEmail();
$businessManager = $this->facebookClient->getBusinessManager($fbe['business_manager_id']);
$pixel = $this->facebookClient->getPixel($fbe['ad_account_id'], $fbe['pixel_id']);
$pages = $this->facebookClient->getPage($fbe['pages']);
$ad = $this->facebookClient->getAd($fbe['ad_account_id']);
$productSyncStarted = (bool) $this->configurationAdapter->get(Config::PS_FACEBOOK_PRODUCT_SYNC_FIRST_START);
$categoryMatchingStarted = false; // TODO : must be true only if all parent categories are matched !
$catalog = new Catalog($fbe['catalog_id'], $productSyncStarted, $categoryMatchingStarted);
return new ContextPsFacebook(
$user,
$businessManager,
$pixel,
$pages,
$ad,
$catalog
);
}
public function getProductsInCatalogCount()
{
$catalogId = $this->configurationAdapter->get(Config::PS_FACEBOOK_CATALOG_ID);
return $this->facebookClient->getProductsInCatalogCount($catalogId);
}
}

View File

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

View File

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

View File

@@ -0,0 +1,161 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use Category;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Repository\GoogleCategoryRepository;
class GoogleCategoryProvider implements GoogleCategoryProviderInterface
{
/**
* @var GoogleCategoryRepository
*/
private $googleCategoryRepository;
public function __construct(
GoogleCategoryRepository $googleCategoryRepository
) {
$this->googleCategoryRepository = $googleCategoryRepository;
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|null
*/
public function getGoogleCategory($categoryId, $shopId)
{
$categoryMatch = $this->googleCategoryRepository->getCategoryMatchByCategoryId($categoryId, $shopId);
if (!is_array($categoryMatch)) {
return null;
}
return $categoryMatch;
}
/**
* @param int $categoryId
* @param int $langId
* @param int $shopId
* @param int $page
*
* @return array|null
*/
public function getGoogleCategoryChildren($categoryId, $langId, $shopId, $page = 1)
{
if ($page < 1) {
$page = 1;
}
$googleCategories = $this->googleCategoryRepository->getFilteredCategories(
$categoryId,
$langId,
Config::CATEGORIES_PER_PAGE * ($page - 1),
Config::CATEGORIES_PER_PAGE,
$shopId
);
if (!is_array($googleCategories)) {
return null;
}
return $googleCategories;
}
/**
* @param int $shopId
*
* @return array
*/
public function getInformationAboutCategoryMatches($shopId)
{
$numberOfMatchedCategories = $this->googleCategoryRepository->getNumberOfMatchedCategories($shopId);
$totalCategories = $this->googleCategoryRepository->getNumberOfTotalCategories($shopId);
return [
'matched' => $numberOfMatchedCategories,
'total' => $totalCategories,
];
}
/**
* @param array $categoryIds
* @param int $shopId
*
* @return array|null
*
* @throws \PrestaShopDatabaseException
*/
public function getGoogleCategories(array $categoryIds, $shopId)
{
$categoryMatch = $this->googleCategoryRepository->getCategoryMatchesByCategoryIds($categoryIds, $shopId);
if (!is_array($categoryMatch)) {
return null;
}
return $categoryMatch;
}
public function getCategoryPaths($topCategoryId, $langId, $shopId)
{
if ((int) $topCategoryId === 0) {
return [
'category_path' => '',
'category_id_path' => '',
];
}
$categoryId = $topCategoryId;
$categories = [];
try {
$categoriesWithParentsInfo = $this->googleCategoryRepository->getCategoriesWithParentInfo($langId, $shopId);
} catch (\PrestaShopDatabaseException $e) {
return [
'category_path' => '',
'category_id_path' => '',
];
}
$homeCategory = Category::getTopCategory()->id;
$categoryExists = true;
while ((int) $categoryId != $homeCategory && $categoryExists) {
$categoryExists = false;
foreach ($categoriesWithParentsInfo as $category) {
if ($category['id_category'] == $categoryId) {
$categories[] = $category;
$categoryId = $category['id_parent'];
$categoryExists = true;
break;
}
}
}
$categories = array_reverse($categories);
return [
'category_path' => implode(' > ', array_map(function ($category) {
return $category['name'];
}, $categories)),
'category_id_path' => implode(' > ', array_map(function ($category) {
return $category['id_category'];
}, $categories)),
];
}
}

View File

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

View File

@@ -0,0 +1,80 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use PrestaShop\Module\PrestashopFacebook\Repository\ShopRepository;
use PrestaShop\Module\Ps_facebook\Tracker\Segment;
use Shop;
class MultishopDataProvider
{
/**
* @var ShopRepository
*/
private $shopRepository;
/**
* @var Segment
*/
private $segment;
public function __construct(
ShopRepository $shopRepository,
Segment $segment
) {
$this->shopRepository = $shopRepository;
$this->segment = $segment;
}
/**
* It appeared that PS Account is currently incompatible with multistore feature.
* While a new major version is prepared, we display a message if the merchant
* onboarded one other shop.
*
* To revent this, we check if a shop is already onboarded and
* warn the merchant accordingly.
*
* @param Shop $currentShop
*
* @return bool
*/
public function isCurrentShopInConflict(Shop $currentShop)
{
$configurationData = $this->shopRepository->getShopDomainsAndConfiguration();
foreach ($configurationData as $shopData) {
if ((int) $shopData['id_shop'] === (int) $currentShop->id) {
continue;
}
if (empty($shopData['acces_token_value'])) {
continue;
}
$this->segment->setMessage('Error: Warn about multistore incompatibility with PS Account');
$this->segment->track();
return true;
}
return false;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
class PrevalidationScanDataProvider
{
/**
* @var PrevalidationScanCacheProvider
*/
protected $preValidationCacheProvider;
public function __construct(PrevalidationScanCacheProvider $preValidationCacheProvider)
{
$this->preValidationCacheProvider = $preValidationCacheProvider;
}
/**
* @return array|null
*/
public function getPrevalidationScanSummary($shopId)
{
return json_decode($this->preValidationCacheProvider->get(
PrevalidationScanCacheProvider::CACHE_KEY_SUMMARY . $shopId
));
}
/**
* @param int $page
* @param int $shopId
*
* @return array
*/
public function getPageOfPrevalidationScan($shopId, $page)
{
$cacheContent = json_decode($this->preValidationCacheProvider->get(
PrevalidationScanCacheProvider::CACHE_KEY_PAGE . $shopId . '_' . $page
));
if (empty($cacheContent)) {
return [];
}
return $cacheContent;
}
}

View File

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

View File

@@ -0,0 +1,58 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use FacebookAds\Object\Values\ProductItemAvailabilityValues;
use Product;
use StockAvailable;
class ProductAvailabilityProvider implements ProductAvailabilityProviderInterface
{
/**
* @param int $productId
* @param int $productAttributeId
*
* @return string
*
* @throws \PrestaShopDatabaseException
* @throws \PrestaShopException
*/
public function getProductAvailability($productId, $productAttributeId)
{
$product = new Product($productId);
if ((int) StockAvailable::getQuantityAvailableByProduct($productId, $productAttributeId)) {
return ProductItemAvailabilityValues::IN_STOCK;
}
switch ($product->out_of_stock) {
case 1:
return ProductItemAvailabilityValues::AVAILABLE_FOR_ORDER;
case 2:
$isAvailable = Product::isAvailableWhenOutOfStock($product->out_of_stock);
return $isAvailable ? ProductItemAvailabilityValues::AVAILABLE_FOR_ORDER : ProductItemAvailabilityValues::OUT_OF_STOCK;
case 0:
default:
return ProductItemAvailabilityValues::OUT_OF_STOCK;
}
}
}

View File

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

View File

@@ -0,0 +1,107 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Provider;
use GuzzleHttp\Psr7\Request;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\API\ResponseListener;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\Exception\FacebookAccountException;
use PrestaShop\Module\PrestashopFacebook\Factory\ApiClientFactoryInterface;
use Psr\Http\Client\ClientInterface;
class ProductSyncReportProvider
{
/**
* @var ConfigurationAdapter
*/
private $configurationAdapter;
/**
* @var ClientInterface
*/
private $psApiClient;
/**
* @var ResponseListener
*/
private $responseListener;
public function __construct(
ConfigurationAdapter $configurationAdapter,
ApiClientFactoryInterface $psApiClientFactory,
ResponseListener $responseListener
) {
$this->configurationAdapter = $configurationAdapter;
$this->responseListener = $responseListener;
$this->psApiClient = $psApiClientFactory->createClient();
}
public function getProductSyncReport()
{
$businessId = $this->configurationAdapter->get(Config::PS_FACEBOOK_EXTERNAL_BUSINESS_ID);
$response = $this->responseListener->handleResponse(
$this->psApiClient->sendRequest(
new Request(
'GET',
"/account/{$businessId}/reporting"
)
),
[
'exceptionClass' => FacebookAccountException::class,
]
);
$responseContent = $response->getBody();
if (!$response->isSuccessful()) {
$responseContent = [];
}
return $this->fixMissingValues($responseContent);
}
private function fixMissingValues($response)
{
if (!isset($response['errors'])) {
$response['errors'] = [];
}
if (!isset($response['lastFinishedSyncStartedAt'])) {
$response['lastFinishedSyncStartedAt'] = 0;
}
$response['errors'] = array_filter($response['errors'], [$this, 'filterErrorsWithoutMessage']);
return $response;
}
/**
* Hotfix as the Nest API should not return products without message
*
* @return bool
*/
private function filterErrorsWithoutMessage(array $productInError)
{
return !empty($productInError);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,368 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PrestashopFacebook\Adapter\ConfigurationAdapter;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShopCollection;
class GoogleCategoryRepository
{
public const NO_CHILDREN = 0;
public const HAS_CHILDREN = 1;
/**
* @var int
*/
private $homeCategoryId;
public function __construct(ConfigurationAdapter $configurationAdapter)
{
$this->homeCategoryId = (int) $configurationAdapter->get('PS_HOME_CATEGORY');
}
/**
* @param int $categoryId
* @param int $googleCategoryId
* @param string $googleCategoryName
* @param int $googleCategoryParentId
* @param string $googleCategoryParentName
* @param int $shopId
* @param bool $isParentCategory
*
* @throws \PrestaShopDatabaseException
*/
public function updateCategoryMatch(
$categoryId,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId,
$isParentCategory = false
) {
Db::getInstance()->insert(
'fb_category_match',
[
'id_category' => (int) $categoryId,
'google_category_id' => (int) $googleCategoryId,
'google_category_name' => pSQL($googleCategoryName),
'google_category_parent_id' => (int) $googleCategoryParentId,
'google_category_parent_name' => pSQL($googleCategoryParentName),
'is_parent_category' => $isParentCategory,
'id_shop' => (int) $shopId,
],
false,
true,
DB::REPLACE
);
}
/**
* @param PrestaShopCollection $childCategories
* @param int $googleCategoryId
* @param string $googleCategoryName
* @param int $googleCategoryParentId
* @param string $googleCategoryParentName
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function updateCategoryChildrenMatch(
PrestaShopCollection $childCategories,
$googleCategoryId,
$googleCategoryName,
$googleCategoryParentId,
$googleCategoryParentName,
$shopId
) {
$data = [];
foreach ($childCategories as $category) {
$data[] = [
'id_category' => (int) $category->id,
'google_category_id' => (int) $googleCategoryId,
'google_category_name' => pSQL($googleCategoryName),
'google_category_parent_id' => (int) $googleCategoryParentId,
'google_category_parent_name' => pSQL($googleCategoryParentName),
'is_parent_category' => 1,
'id_shop' => (int) $shopId,
];
}
Db::getInstance()->insert(
'fb_category_match',
$data,
false,
true,
DB::REPLACE
);
}
/**
* @param int $categoryId
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function unsetCategoryMatch(
$categoryId,
$shopId
) {
Db::getInstance()->delete(
'fb_category_match',
'`id_category` = ' . (int) $categoryId . ' AND `id_shop` = ' . (int) $shopId
);
}
/**
* @param PrestaShopCollection $childCategories
* @param int $shopId
*
* @throws \PrestaShopDatabaseException
*/
public function unsetCategoryChildrenMatch(
PrestaShopCollection $childCategories,
$shopId
) {
foreach ($childCategories as $category) {
$this->unsetCategoryMatch($category->id, $shopId);
}
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return int
*/
public function getGoogleCategoryIdByCategoryId($categoryId, $shopId)
{
$sql = new DbQuery();
$sql->select('google_category_id');
$sql->from('fb_category_match');
$sql->where('`id_category` = "' . (int) $categoryId . '"');
$sql->where('id_shop = ' . (int) $shopId);
return (int) Db::getInstance()->getValue($sql);
}
/**
* @param int $categoryId
* @param int $shopId
*
* @return array|false
*/
public function getCategoryMatchByCategoryId($categoryId, $shopId)
{
$sql = new DbQuery();
$sql->select('id_category');
$sql->select('google_category_id');
$sql->select('google_category_name');
$sql->select('google_category_parent_id');
$sql->select('google_category_parent_name');
$sql->select('is_parent_category');
$sql->from('fb_category_match');
$sql->where('`id_category` = "' . (int) $categoryId . '"');
$sql->where('id_shop = ' . (int) $shopId);
return Db::getInstance()->getRow($sql);
}
/**
* @param array $categoryIds
* @param int $shopId
*
* @return array|false
*
* @throws \PrestaShopDatabaseException
*/
public function getGoogleCategoryIdsByCategoryIds(array $categoryIds, $shopId)
{
$sql = new DbQuery();
$sql->select('google_category_id');
$sql->from('fb_category_match');
$sql->where('`id_category` IN ("' . implode('", "', $categoryIds) . '")');
$sql->where('id_shop = ' . (int) $shopId);
return Db::getInstance()->executeS($sql);
}
/**
* @param array $categoryIds
* @param int $shopId
*
* @return array|false
*
* @throws \PrestaShopDatabaseException
*/
public function getCategoryMatchesByCategoryIds(array $categoryIds, $shopId)
{
$sql = new DbQuery();
$sql->select('id_category');
$sql->select('google_category_id');
$sql->select('google_category_parent_id');
$sql->select('is_parent_category');
$sql->from('fb_category_match');
$sql->where('`id_category` IN ("' . implode('", "', $categoryIds) . '")');
$sql->where('id_shop = ' . (int) $shopId);
return Db::getInstance()->executeS($sql);
}
public function getFilteredCategories($parentCategoryId, $langId, $offset, $limit, $shopId)
{
$sql = new DbQuery();
$sql->select('c.id_category as shopCategoryId');
$sql->select('cl.name as shopCategoryName');
$sql->select('cm.google_category_id as googleCategoryId');
$sql->select('cm.google_category_name as googleCategoryName');
$sql->select('cm.google_category_parent_id as googleCategoryParentId');
$sql->select('cm.google_category_parent_name as googleCategoryParentName');
$sql->select('cm.is_parent_category as isParentCategory');
$sql->select('case when c.nleft = c.nright -1 and c.`level_depth` = ' . Config::MAX_CATEGORY_DEPTH .
' then ' . self::NO_CHILDREN . ' else ' . self::HAS_CHILDREN . ' end deploy');
$sql->from('category', 'c');
$sql->innerJoin('category_shop', 'cs', 'cs.id_category = c.id_category');
$sql->innerJoin('category_lang', 'cl', 'c.id_category = cl.id_category AND cl.id_lang = ' . (int) $langId);
$sql->leftJoin(
'fb_category_match',
'cm',
'cm.id_category = c.id_category AND cm.id_shop = ' . (int) $shopId
);
$sql->where('cs.id_shop = ' . (int) $shopId);
$sql->where(
'c.`id_parent` = ' . (int) $parentCategoryId . ' OR
(
c.`nleft` > (SELECT pc.`nleft` from `' . _DB_PREFIX_ . 'category` as pc WHERE pc.id_category = '
. (int) $parentCategoryId . ' AND pc.`level_depth` >= ' . Config::MAX_CATEGORY_DEPTH . ') AND
c.`nright` < (SELECT pc.`nright` from `' . _DB_PREFIX_ . 'category` as pc WHERE pc.id_category = '
. (int) $parentCategoryId . ' AND pc.`level_depth` >= ' . Config::MAX_CATEGORY_DEPTH . ')
)'
);
$sql->groupBy('c.id_category');
$sql->limit($limit, $offset);
return Db::getInstance()->executeS($sql);
}
/**
* @param int $shopId
*
* @return bool
*
* @throws \PrestaShopDatabaseException
*/
public function areParentCategoriesMatched($shopId)
{
$sql = new DbQuery();
$sql->select('c.id_category');
$sql->from('category', 'c');
$sql->innerJoin('category_shop', 'cs', 'cs.id_category = c.id_category');
$sql->leftJoin('fb_category_match', 'cm', 'cm.id_category = c.id_category AND cm.id_shop = cs.id_shop');
$sql->where("c.id_parent = {$this->homeCategoryId} AND cm.google_category_id IS NULL");
$sql->where('cs.id_shop = ' . (int) $shopId);
return (bool) Db::getInstance()->executeS($sql);
}
/**
* @param int $langId
* @param int $shopId
*
* @return array
*
* @throws \PrestaShopDatabaseException
*/
public function getCategoriesWithParentInfo($langId, $shopId)
{
$query = new DbQuery();
$query->select('c.id_category, cl.name, c.id_parent')
->from('category', 'c')
->leftJoin(
'category_lang',
'cl',
'cl.id_category = c.id_category AND cl.id_shop = ' . (int) $shopId
)
->where('cl.id_lang = ' . (int) $langId)
->orderBy('cl.id_category');
$result = Db::getInstance()->executeS($query);
if ($result) {
return $result;
} else {
throw new \PrestaShopDatabaseException('No categories found');
}
}
/**
* @param int $shopId
*
* @return bool
*
* @throws \PrestaShopDatabaseException
*/
public function isMatchingDone($shopId)
{
$sql = new DbQuery();
$sql->select('cm.id_category');
$sql->from('fb_category_match', 'cm');
$sql->where('cm.id_shop = ' . (int) $shopId);
return (bool) Db::getInstance()->executeS($sql);
}
/**
* @param int $shopId
*
* @return int
*/
public function getNumberOfMatchedCategories($shopId)
{
$sql = new DbQuery();
$sql->select('cm.id_category');
$sql->from('fb_category_match', 'cm');
$sql->where('cm.id_shop = ' . (int) $shopId);
Db::getInstance()->execute($sql);
return Db::getInstance()->numRows();
}
/**
* @param int $shopId
*
* @return int
*/
public function getNumberOfTotalCategories($shopId)
{
$sql = new DbQuery();
$sql->select('c.id_category');
$sql->from('category', 'c');
$sql->innerJoin('category_shop', 'cp', 'cp.id_category = c.id_category');
$sql->where('cp.id_shop = ' . (int) $shopId . ' AND c.id_parent >=' . (int) $this->homeCategoryId);
Db::getInstance()->execute($sql);
return Db::getInstance()->numRows();
}
}

View File

@@ -0,0 +1,359 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\Module\PrestashopFacebook\DTO\EventBusProduct;
use PrestaShop\Module\Ps_facebook\Utility\ProductCatalogUtility;
use PrestaShopException;
use Product;
class ProductRepository
{
/**
* @var \Language
*/
private $language;
public function __construct(\Language $language)
{
$this->language = $language;
}
/**
* Copy of prestashop Product::getIdProductAttributeByIdAttributes function
* because old PS versions are missing this function
*
* Get an id_product_attribute by an id_product and one or more
* id_attribute.
*
* e.g: id_product 8 with id_attribute 4 (size medium) and
* id_attribute 5 (color blue) returns id_product_attribute 9 which
* is the dress size medium and color blue.
*
* @param int $idProduct
* @param int|int[] $idAttributes
* @param bool $findBest
*
* @return int
*
* @throws PrestaShopException
*/
public function getIdProductAttributeByIdAttributes($idProduct, $idAttributes, $findBest = false)
{
$idProduct = (int) $idProduct;
if (!is_array($idAttributes) && is_numeric($idAttributes)) {
$idAttributes = [(int) $idAttributes];
}
if (!is_array($idAttributes) || empty($idAttributes)) {
throw new PrestaShopException(sprintf('Invalid parameter $idAttributes with value: "%s"', print_r($idAttributes, true)));
}
$idAttributesImploded = implode(',', array_map('intval', $idAttributes));
$idProductAttribute = Db::getInstance()->getValue(
'
SELECT
pac.`id_product_attribute`
FROM
`' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.id_product_attribute = pac.id_product_attribute
WHERE
pa.id_product = ' . $idProduct . '
AND pac.id_attribute IN (' . $idAttributesImploded . ')
GROUP BY
pac.`id_product_attribute`
HAVING
COUNT(pa.id_product) = ' . count($idAttributes)
);
if ($idProductAttribute === false && $findBest) {
//find the best possible combination
//first we order $idAttributes by the group position
$orderred = [];
$result = Db::getInstance()->executeS(
'
SELECT
a.`id_attribute`
FROM
`' . _DB_PREFIX_ . 'attribute` a
INNER JOIN `' . _DB_PREFIX_ . 'attribute_group` g ON a.`id_attribute_group` = g.`id_attribute_group`
WHERE
a.`id_attribute` IN (' . $idAttributesImploded . ')
ORDER BY
g.`position` ASC'
);
foreach ($result as $row) {
$orderred[] = $row['id_attribute'];
}
while ($idProductAttribute === false && count($orderred) > 0) {
array_pop($orderred);
$idProductAttribute = Db::getInstance()->getValue(
'
SELECT
pac.`id_product_attribute`
FROM
`' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.id_product_attribute = pac.id_product_attribute
WHERE
pa.id_product = ' . (int) $idProduct . '
AND pac.id_attribute IN (' . implode(',', array_map('intval', $orderred)) . ')
GROUP BY
pac.id_product_attribute
HAVING
COUNT(pa.id_product) = ' . count($orderred)
);
}
}
if (empty($idProductAttribute)) {
throw new PrestaShopException('Can not retrieve the id_product_attribute');
}
return (int) $idProductAttribute;
}
public function getProductsWithErrors($shopId, $page = -1)
{
$sql = new DbQuery();
$sql->select('ps.id_product');
$sql->select('IF(pas.id_product_attribute IS NULL, 0, id_product_attribute) as id_product_attribute');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
$sql->leftJoin('product_attribute_shop', 'pas', 'pas.id_product = ps.id_product AND pas.id_shop = ps.id_shop');
$sql->where('ps.id_shop = ' . (int) $shopId . ' AND ps.active = 1');
$result = Db::getInstance()->executeS($sql);
$productIdsWithInvalidSalePrice = [0];
$productAttributeIdsWithInvalidSalePrice = [0];
foreach ($result as $product) {
$salePriceTaxExcluded = $this->getSalePriceTaxExcluded($product['id_product'], $product['id_product_attribute']);
if ($salePriceTaxExcluded <= 0) {
$productIdsWithInvalidSalePrice[] = $product['id_product'];
$productAttributeIdsWithInvalidSalePrice[] = $product['id_product_attribute'];
}
}
$sql = new DbQuery();
$sql->select('ps.id_product, pas.id_product_attribute, pl.name');
$sql->select('pl.id_lang, l.iso_code as language');
$sql->select('
IF((m.name = "" OR m.name IS NULL) AND p.ean13 = "" AND p.upc = "" AND p.isbn = "", false, true) as has_manufacturer_or_ean_or_upc_or_isbn
');
$sql->select('IF(is.id_image IS NOT NULL, true, false) as has_cover');
$sql->select('IF(pl.link_rewrite = "" OR pl.link_rewrite is NULL, false, true) as has_link');
$sql->select('IF(ps.price + IFNULL(pas.price, 0) > 0, true, false) as has_price_tax_excl');
$sql->select('IF((pl.description_short = "" OR pl.description_short IS NULL) AND (pl.description = "" OR pl.description IS NULL), false, true) as has_description_or_short_description');
$sql->select('true as correct_sales_price');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = ps.id_product AND pl.id_shop = ps.id_shop');
$sql->innerJoin('lang', 'l', 'l.id_lang = pl.id_lang');
$sql->leftJoin('product_attribute_shop', 'pas', 'pas.id_product = ps.id_product AND pas.id_shop = ps.id_shop');
$sql->leftJoin('manufacturer', 'm', 'm.id_manufacturer = p.id_manufacturer');
$sql->leftJoin('image_shop', 'is', 'is.id_product = ps.id_product AND is.id_shop = ps.id_shop AND is.cover = 1');
$sql->where('ps.id_shop = ' . (int) $shopId . ' AND ps.active = 1');
$sql->where('
(m.name = "" OR m.name IS NULL) AND p.ean13 = "" AND p.upc = "" AND p.isbn = ""
OR ((pl.description_short = "" OR pl.description_short IS NULL) AND (pl.description = "" OR pl.description IS NULL))
OR is.id_image is NULL
OR pl.link_rewrite = "" OR pl.link_rewrite is NULL
OR ps.price + IFNULL(pas.price, 0) <= 0
OR pl.name = "" OR pl.name is NULL
OR
(
ps.id_product in (' . implode(',', $productIdsWithInvalidSalePrice) . ') AND
(
pas.id_product_attribute in (' . implode(',', $productAttributeIdsWithInvalidSalePrice) . ') OR
pas.id_product_attribute IS NULL
)
)
');
$sql->orderBy('p.id_product ASC, pas.id_product_attribute ASC, language ASC');
if ($page > -1) {
$sql->limit(Config::REPORTS_PER_PAGE, Config::REPORTS_PER_PAGE * ($page));
}
$result = Db::getInstance()->executeS($sql);
foreach ($result as $key => &$value) {
if (!in_array($value['id_product'], $productIdsWithInvalidSalePrice)) {
continue;
}
if (in_array($value['id_product_attribute'], $productAttributeIdsWithInvalidSalePrice)
|| $value['id_product_attribute'] === null) {
$value['correct_sales_price'] = false;
}
}
return $result;
}
public function getProductsTotal($shopId, array $options = [])
{
$sql = new DbQuery();
$sql->select('COUNT(1) as total');
$sql->from('product', 'p');
$sql->innerJoin('product_shop', 'ps', 'ps.id_product = p.id_product');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = ps.id_product AND pl.id_shop = ps.id_shop');
$sql->leftJoin('product_attribute_shop', 'pas', 'pas.id_product = ps.id_product AND pas.id_shop = ps.id_shop');
$sql->where('ps.id_shop = ' . (int) $shopId);
if (isset($options['onlyActive'])) {
$sql->where('ps.active = 1');
}
$res = Db::getInstance()->executeS($sql);
return $res[0]['total'];
}
/**
* @param EventBusProduct $eventBusProduct
* @param int $shopId
* @param string $isoCode
*
* @return array|bool|\mysqli_result|\PDOStatement|resource|null
*
* @throws \PrestaShopDatabaseException
*/
public function getInformationAboutEventBusProduct(EventBusProduct $eventBusProduct, $shopId, $isoCode)
{
$sql = new DbQuery();
$sql->select('pa.id_product, pa.id_product_attribute, pl.name');
$sql->select('l.iso_code');
$sql->from('product_attribute', 'pa');
$sql->innerJoin('lang', 'l', 'l.iso_code = "' . pSQL($isoCode) . '"');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = pa.id_product AND pl.id_lang = l.id_lang');
$sql->where('pa.id_product = ' . (int) $eventBusProduct->getProductId());
$sql->where('pa.id_product_attribute = ' . (int) $eventBusProduct->getProductAttributeId());
$sql->where('pl.id_shop = ' . (int) $shopId);
return Db::getInstance()->executeS($sql);
}
/**
* @param string $syncUpdateDate
* @param int $shopId
* @param array $productsWithErrors
* @param int|false $page
* @param string|null $status
* @param string|null $sortBy
* @param string $sortTo
* @param int|bool $searchById
* @param string|bool $searchByName
* @param string|bool $searchByMessage
*
* @return array|bool|\mysqli_result|\PDOStatement|resource|null
*
* @throws \PrestaShopDatabaseException
*/
public function getInformationAboutEventBusProducts(
$syncUpdateDate,
$shopId,
$productsWithErrors,
$page = false,
$status = null,
$sortBy = null,
$sortTo = 'ASC',
$searchById = false,
$searchByName = false,
$searchByMessage = false
) {
$sql = new DbQuery();
$sql->select('ps.id_product, pa.id_product_attribute, pl.name, ps.date_upd');
$sql->select('
IF(CONCAT_WS("-", ps.id_product, IFNULL(pa.id_product_attribute, "0")) IN ( "' . implode('","', $productsWithErrors) . '"), "disapproved",
IF(ps.date_upd <= "' . pSQL($syncUpdateDate) . '", "approved", "pending" )
) as status
');
$sql->from('product_shop', 'ps');
$sql->leftJoin('product_attribute', 'pa', 'pa.id_product = ps.id_product');
$sql->innerJoin('product_lang', 'pl', 'pl.id_product = ps.id_product');
$sql->where('pl.id_shop = ' . (int) $shopId);
$sql->where('CONCAT_WS("-", ps.id_product, IFNULL(pa.id_product_attribute, 0)) IN ( "' . implode('","', $productsWithErrors) . '")');
// GROUP BY Id product AND ID combination of attributes
$sql->groupBy('ps.id_product');
$sql->groupBy('pa.id_product_attribute');
if ($page !== false) {
$sql->limit(Config::REPORTS_PER_PAGE, Config::REPORTS_PER_PAGE * ($page - 1));
}
if ($sortBy) {
$sql->orderBy(pSQL($sortBy) . ' ' . pSQL($sortTo));
}
if ($searchById) {
$sql->where('ps.id_product LIKE "%' . (int) $searchById . '%"');
}
if ($searchByName) {
$sql->where('pl.name LIKE "%' . pSQL($searchByName) . '%"');
}
if ($searchByMessage) {
$sql->where('ps.id_product LIKE "%' . (int) $searchByMessage . '%"');
}
if ($status) {
$sql->having('ps.id_product LIKE "%' . pSQL($status) . '%"');
}
$result = Db::getInstance()->executeS($sql);
$products = [];
foreach ($result as $product) {
$eventBusProductId = ProductCatalogUtility::makeProductId(
$product['id_product'],
$product['id_product_attribute']
);
$products[$eventBusProductId] = $product;
}
return $products;
}
/**
* @param int $productId
* @param int $attributeId
*
* @return float
*/
public function getSalePriceTaxExcluded($productId, $attributeId)
{
return Product::getPriceStatic($productId, false, $attributeId, 6);
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Repository;
use Exception;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
use PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts;
class ServerInformationRepository
{
/**
* @var bool
*/
private $isPsAccountsOnboarded;
public function __construct(PsAccounts $psAccountsFacade)
{
try {
$this->isPsAccountsOnboarded = (bool) $psAccountsFacade->getPsAccountsService()->getOrRefreshToken();
} catch (Exception $e) {
$this->isPsAccountsOnboarded = false;
}
}
/**
* @return array
*/
public function getHealthCheckData()
{
$isFacebookSystemTokenSet = false;
if (\Configuration::get(Config::PS_FACEBOOK_SYSTEM_ACCESS_TOKEN)) {
$isFacebookSystemTokenSet = true;
}
return [
'ps_accounts' => \Module::isInstalled('ps_accounts'),
'ps_accounts_onboarded' => $this->isPsAccountsOnboarded,
'ps_eventbus' => \Module::isInstalled('ps_eventbus'),
'ps_facebook_system_token_set' => $isFacebookSystemTokenSet,
'pixel_enabled' => (bool) \Configuration::get(Config::PS_FACEBOOK_PIXEL_ENABLED),
'pixel_id' => (bool) \Configuration::get(Config::PS_PIXEL_ID),
'profile_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_PROFILES),
'page_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_PAGES),
'business_manager_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_BUSINESS_MANAGER_ID),
'ad_account_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_AD_ACCOUNT_ID),
'catalog_id' => (bool) \Configuration::get(Config::PS_FACEBOOK_CATALOG_ID),
'env' => [
'PSX_FACEBOOK_API_URL' => isset($_ENV['PSX_FACEBOOK_API_URL']) ? $_ENV['PSX_FACEBOOK_API_URL'] : null,
'ACCOUNTS_SVC_API_URL' => isset($_ENV['ACCOUNTS_SVC_API_URL']) ? $_ENV['ACCOUNTS_SVC_API_URL'] : null,
'EVENT_BUS_PROXY_API_URL' => isset($_ENV['EVENT_BUS_PROXY_API_URL']) ? $_ENV['EVENT_BUS_PROXY_API_URL'] : null,
'EVENT_BUS_SYNC_API_URL' => isset($_ENV['EVENT_BUS_SYNC_API_URL']) ? $_ENV['EVENT_BUS_SYNC_API_URL'] : null,
],
];
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
namespace PrestaShop\Module\PrestashopFacebook\Repository;
use Db;
use DbQuery;
use PrestaShop\Module\PrestashopFacebook\Config\Config;
class ShopRepository
{
public function getShopDomainsAndConfiguration()
{
$sql = new DbQuery();
$sql->select('su.`id_shop`, `domain`, `domain_ssl`, c.`value` as acces_token_value');
$sql->from('shop_url', 'su');
$sql->leftJoin('configuration', 'c', 'su.id_shop = c.id_shop');
$sql->where('c.name LIKE "' . Config::PS_FACEBOOK_USER_ACCESS_TOKEN . '"');
return Db::getInstance()->executeS($sql);
}
public function getDefaultCategoryShop()
{
$sql = new DbQuery();
$sql->select('id_category');
$sql->from('shop');
return Db::getInstance()->executeS($sql)[0];
}
}

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

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;