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