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,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;