first commit
This commit is contained in:
200
modules/ps_facebook/classes/Provider/AccessTokenProvider.php
Normal file
200
modules/ps_facebook/classes/Provider/AccessTokenProvider.php
Normal 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();
|
||||
}
|
||||
}
|
||||
553
modules/ps_facebook/classes/Provider/EventDataProvider.php
Normal file
553
modules/ps_facebook/classes/Provider/EventDataProvider.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
54
modules/ps_facebook/classes/Provider/FbeDataProvider.php
Normal file
54
modules/ps_facebook/classes/Provider/FbeDataProvider.php
Normal 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),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
}
|
||||
161
modules/ps_facebook/classes/Provider/GoogleCategoryProvider.php
Normal file
161
modules/ps_facebook/classes/Provider/GoogleCategoryProvider.php
Normal 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)),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
28
modules/ps_facebook/classes/Provider/index.php
Normal file
28
modules/ps_facebook/classes/Provider/index.php
Normal 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;
|
||||
Reference in New Issue
Block a user