Current File : /var/www/prestashop/modules/ps_mbo/src/Addons/Provider/AddonsDataProvider.php |
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
declare(strict_types=1);
namespace PrestaShop\Module\Mbo\Addons\Provider;
use Exception;
use GuzzleHttp\Exception\ClientException;
use PrestaShop\Module\Mbo\Addons\ApiClient;
use PrestaShop\Module\Mbo\Addons\Exception\DownloadModuleException;
use PrestaShop\Module\Mbo\Addons\User\AddonsUser;
use PrestaShop\Module\Mbo\Exception\AddonsDownloadModuleException;
use PrestaShop\Module\Mbo\Helpers\ErrorHelper;
/**
* This class will provide data from Addons API
*/
class AddonsDataProvider implements DataProviderInterface
{
/** @var string */
public const ADDONS_API_MODULE_CHANNEL_STABLE = 'stable';
/** @var string */
public const ADDONS_API_MODULE_CHANNEL_BETA = 'beta';
/** @var string */
public const ADDONS_API_MODULE_CHANNEL_ALPHA = 'alpha';
/** @var array<string> */
public const ADDONS_API_MODULE_CHANNELS = [
self::ADDONS_API_MODULE_CHANNEL_STABLE,
self::ADDONS_API_MODULE_CHANNEL_BETA,
self::ADDONS_API_MODULE_CHANNEL_ALPHA,
];
/** @var array<string, string> */
public const ADDONS_API_MODULE_ACTIONS = [
'native' => 'getNativesModules',
'service' => 'getServices',
'native_all' => 'getNativesModules',
'must-have' => 'getMustHaveModules',
'customer' => 'getCustomerModules',
'customer_themes' => 'getCustomerThemes',
'check_customer' => 'getCheckCustomer',
'check_module' => 'getCheckModule',
'module_download' => 'getModuleZip',
'module' => 'getModule',
'install-modules' => 'getPreInstalledModules',
'categories' => 'getCategories',
];
/**
* @var bool
*/
protected static $is_addons_up = true;
/**
* @var ApiClient
*/
protected $marketplaceClient;
/**
* @var string the cache directory location
*/
public $cacheDir;
/**
* @var string
*/
protected $moduleChannel;
/**
* @var AddonsUser
*/
protected $user;
/**
* @param ApiClient $apiClient
* @param AddonsUser $user
* @param string|null $moduleChannel
*/
public function __construct(
ApiClient $apiClient,
AddonsUser $user,
?string $moduleChannel = null
) {
$this->marketplaceClient = $apiClient;
$this->moduleChannel = $moduleChannel ?? self::ADDONS_API_MODULE_CHANNEL_STABLE;
$this->user = $user;
}
/**
* Downloads a module source from addons, store it and returns the file name.
*
* @throws DownloadModuleException
*/
public function downloadModule(int $moduleId): string
{
$params = [
'id_module' => $moduleId,
'format' => 'json',
];
// Module downloading
try {
$moduleData = $this->request('module_download', $params);
} catch (Exception $e) {
ErrorHelper::reportError($e);
$message = $this->isUserAuthenticated() ?
'Error sent by Addons. You may be not allowed to download this module.'
: 'Error sent by Addons. You may need to be logged.';
if ($e instanceof ClientException) {
throw new AddonsDownloadModuleException($e);
}
throw new DownloadModuleException($message, 0, $e);
}
$temporaryZipFilename = tempnam($this->cacheDir, 'mod');
if (file_put_contents($temporaryZipFilename, $moduleData) !== false) {
return $temporaryZipFilename;
} else {
throw new DownloadModuleException('Cannot store module content in temporary file !');
}
}
/**
* Tells if the user is authenticated to Addons or Account
*/
public function isUserAuthenticated(): bool
{
return $this->user->isAuthenticated();
}
/**
* Tells if the user is authenticated to Addons
*/
public function isUserAuthenticatedOnAccounts(): bool
{
return $this->user->hasAccountsTokenInSession() || $this->user->isConnectedOnPsAccounts();
}
/**
* Returns the user's login if he is authenticated to Addons
*/
public function getAuthenticatedUserEmail(): ?string
{
return $this->isUserAuthenticated() ? (string) $this->user->getEmail()['username'] : null;
}
/**
* {@inheritdoc}
*
* @throws Exception
*/
public function request(string $action, array $params = [])
{
if (!$this->isServiceUp()) {
throw new Exception('Previous call failed and disabled client.');
}
if (
!array_key_exists($action, self::ADDONS_API_MODULE_ACTIONS) ||
!method_exists($this->marketplaceClient, self::ADDONS_API_MODULE_ACTIONS[$action])
) {
throw new Exception("Action '{$action}' not found in actions list.");
}
$this->marketplaceClient->reset();
// We merge the addons credentials
$authParams = $this->getAuthenticationParams();
if (null !== $authParams['bearer'] && is_string($authParams['bearer'])) {
$this->marketplaceClient->setHeaders([
'Authorization' => 'Bearer ' . $authParams['bearer'],
]);
}
if (null !== $authParams['credentials'] && is_array($authParams['credentials'])) {
$params = array_merge($authParams['credentials'], $params);
}
if ($action === 'module_download') {
$params['channel'] = $this->moduleChannel;
} elseif ($action === 'native_all') {
$params['iso_code'] = 'all';
}
try {
return $this->marketplaceClient->{self::ADDONS_API_MODULE_ACTIONS[$action]}($params);
} catch (Exception $e) {
ErrorHelper::reportError($e);
self::$is_addons_up = false;
throw $e;
}
}
public function getAuthenticationParams(): array
{
$authParams = [
'bearer' => null,
'credentials' => null,
];
// We merge the addons credentials
if ($this->isUserAuthenticated()) {
$credentials = $this->user->getCredentials();
if (null !== $credentials && array_key_exists('accounts_token', $credentials)) {
$authParams['bearer'] = $credentials['accounts_token'];
// This is a bug for now, we need to give a couple of username/password even if a token is given
// It has to be cleaned once the bug fixed
$authParams['credentials'] = [
'username' => 'name@domain.com',
'password' => 'fakepwd',
];
} else {
$authParams['credentials'] = $credentials;
}
}
return $authParams;
}
public function getAccountsShopUuid(): ?string
{
if (!$this->isUserAuthenticatedOnAccounts()) {
return null;
}
return $this->user->getAccountsShopUuid();
}
/**
* Check if the previous request to Addons has failed.
*
* @return bool
*/
public function isServiceUp(): bool
{
return self::$is_addons_up;
}
}