Download project

This commit is contained in:
Roman Pyrih
2024-11-20 09:09:44 +01:00
parent 547a138d6a
commit 5ff041757f
40737 changed files with 7766183 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<?php
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,170 @@
Academic Free License (“AFL”) v. 3.0
This Academic Free License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the
following licensing notice adjacent to the copyright notice for the Original
Work:
Licensed under the Academic Free License version 3.0
1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, for the duration of the copyright, to do
the following:
a) to reproduce the Original Work in copies, either alone or as part of a
collective work;
b) to translate, adapt, alter, transform, modify, or arrange the Original
Work, thereby creating derivative works ("Derivative Works") based upon
the Original Work;
c) to distribute or communicate copies of the Original Work and
Derivative Works to the public, under any license of your choice that
does not contradict the terms and conditions, including Licensors
reserved rights and remedies, in this Academic Free License;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, under patent claims owned or controlled
by the Licensor that are embodied in the Original Work as furnished by the
Licensor, for the duration of the patents, to make, use, sell, offer for sale,
have made, and import the Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred
form of the Original Work for making modifications to it and all available
documentation describing how to modify the Original Work. Licensor agrees to
provide a machine-readable copy of the Source Code of the Original Work along
with each copy of the Original Work that Licensor distributes. Licensor
reserves the right to satisfy this obligation by placing a machine-readable
copy of the Source Code in an information repository reasonably calculated to
permit inexpensive and convenient access by You for as long as Licensor
continues to distribute the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
of any contributors to the Original Work, nor any of their trademarks or
service marks, may be used to endorse or promote products derived from this
Original Work without express prior permission of the Licensor. Except as
expressly stated herein, nothing in this License grants any license to
Licensors trademarks, copyrights, patents, trade secrets or any other
intellectual property. No patent license is granted to make, use, sell, offer
for sale, have made, or import embodiments of any patent claims other than the
licensed claims defined in Section 2. No license is granted to the trademarks
of Licensor even if such marks are included in the Original Work. Nothing in
this License shall be interpreted to prohibit Licensor from licensing under
terms different from this License any Original Work that Licensor otherwise
would have a right to license.
5) External Deployment. The term "External Deployment" means the use,
distribution, or communication of the Original Work or Derivative Works in any
way such that the Original Work or Derivative Works may be used by anyone
other than You, whether those works are distributed or communicated to those
persons or made available as an application intended for use over a network.
As an express condition for the grants of license hereunder, You must treat
any External Deployment by You of the Original Work or a Derivative Work as a
distribution under section 1(c).
6) Attribution Rights. You must retain, in the Source Code of any Derivative
Works that You create, all copyright, patent, or trademark notices from the
Source Code of the Original Work, as well as any notices of licensing and any
descriptive text identified therein as an "Attribution Notice." You must cause
the Source Code for any Derivative Works that You create to carry a prominent
Attribution Notice reasonably calculated to inform recipients that You have
modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
the copyright in and to the Original Work and the patent rights granted herein
by Licensor are owned by the Licensor or are sublicensed to You under the
terms of this License with the permission of the contributor(s) of those
copyrights and patent rights. Except as expressly stated in the immediately
preceding sentence, the Original Work is provided under this License on an "AS
IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without
limitation, the warranties of non-infringement, merchantability or fitness for
a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK
IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this
License. No license to the Original Work is granted by this License except
under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory,
whether in tort (including negligence), contract, or otherwise, shall the
Licensor be liable to anyone for any indirect, special, incidental, or
consequential damages of any character arising as a result of this License or
the use of the Original Work including, without limitation, damages for loss
of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. This limitation of liability shall not
apply to the extent applicable law prohibits such limitation.
9) Acceptance and Termination. If, at any time, You expressly assented to this
License, that assent indicates your clear and irrevocable acceptance of this
License and all of its terms and conditions. If You distribute or communicate
copies of the Original Work or a Derivative Work, You must make a reasonable
effort under the circumstances to obtain the express assent of recipients to
the terms of this License. This License conditions your rights to undertake
the activities listed in Section 1, including your right to create Derivative
Works based upon the Original Work, and doing so without honoring these terms
and conditions is prohibited by copyright law and international treaty.
Nothing in this License is intended to affect copyright exceptions and
limitations (including “fair use” or “fair dealing”). This License shall
terminate immediately and You may no longer exercise any of the rights granted
to You by this License upon your failure to honor the conditions in Section
1(c).
10) Termination for Patent Action. This License shall terminate automatically
and You may no longer exercise any of the rights granted to You by this
License as of the date You commence an action, including a cross-claim or
counterclaim, against Licensor or any licensee alleging that the Original Work
infringes a patent. This termination provision shall not apply for an action
alleging patent infringement by combinations of the Original Work with other
software or hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
License may be brought only in the courts of a jurisdiction wherein the
Licensor resides or in which Licensor conducts its primary business, and under
the laws of that jurisdiction excluding its conflict-of-law provisions. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded. Any use of the Original
Work outside the scope of this License or after its termination shall be
subject to the requirements and penalties of copyright or patent law in the
appropriate jurisdiction. This section shall survive the termination of this
License.
12) Attorneys Fees. In any action to enforce the terms of this License or
seeking damages relating thereto, the prevailing party shall be entitled to
recover its costs and expenses, including, without limitation, reasonable
attorneys' fees and costs incurred in connection with such action, including
any appeal of such action. This section shall survive the termination of this
License.
13) Miscellaneous. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent necessary
to make it enforceable.
14) Definition of "You" in This License. "You" throughout this License,
whether in upper or lower case, means an individual or a legal entity
exercising rights under, and complying with all of the terms of, this License.
For legal entities, "You" includes any entity that controls, is controlled by,
or is under common control with you. For purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity.
15) Right to Use. You may use the Original Work in all ways not otherwise
restricted or conditioned by this License or by law, and Licensor promises not
to interfere with or be responsible for such uses by You.
16) Modification of This License. This License is Copyright © 2005 Lawrence
Rosen. Permission is granted to copy, distribute, or communicate this License
without modification. Nothing in this License permits You to modify this
License as applied to the Original Work or to Derivative Works. However, You
may modify the text of this License and copy, distribute or communicate your
modified version (the "Modified License") and apply it to other original works
of authorship subject to the following conditions: (i) You may not indicate in
any way that your Modified License is the "Academic Free License" or "AFL" and
you may not use those names in the name of your Modified License; (ii) You
must replace the notice specified in the first paragraph above with the notice
"Licensed under <insert your license name here>" or with a notice of your own
that is not confusingly similar to the notice in this License; and (iii) You
may not claim that your original works are open source software unless your
Modified License has been approved by Open Source Initiative (OSI) and You
comply with its license review and certification process.

View File

@@ -0,0 +1,30 @@
# PrestaShop Cache Directory Provider for Modules
This repository provides the cache directory for PrestaShop modules.
## Pre-requisites
You should install this library only on a PrestaShop environment and with PHP 5.6.0 minimum.
## Installation
```
composer require prestashop/module-lib-cache-directory-provider
```
When this project is successfully added to your dependencies, you can add the new CacheDirectoryProvider to your module and use it.
## Usage
To use this library, it's simple :
```
$cacheDirectoryProvider = new CacheDirectoryProvider(
_PS_VERSION_,
_PS_ROOT_DIR_,
_PS_MODE_DEV_
);
```
With the getPath() function, you will retrieve the cache path of your module :
```
$cacheDirectoryProvider->getPath();
```

View File

@@ -0,0 +1,34 @@
{
"name": "prestashop/module-lib-cache-directory-provider",
"description": "Cache directory provider to use on prestashop modules",
"keywords": ["prestashop", "modules", "composer", "package"],
"license": "AFL-3.0",
"authors": [
{
"name": "PrestaShop SA",
"email": "contact@prestashop.com"
}
],
"type": "project",
"config": {
"platform": {
"php": "5.6.0"
}
},
"require": {
"php": ">=5.6.0"
},
"require-dev": {
"phpunit/phpunit": "~5.7"
},
"autoload": {
"psr-4": {
"PrestaShop\\ModuleLibCacheDirectoryProvider\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
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,98 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibCacheDirectoryProvider\Cache;
/**
* Class responsible for returning cache directory path.
*/
class CacheDirectoryProvider
{
/**
* @var string PrestaShop version
*/
private $psVersion;
/**
* @var string PrestaShop path
*/
private $psPath;
/**
* @var bool PrestaShop Debug Mode
*/
private $psIsDebugMode;
/**
* @param string $psVersion
* @param string $psPath
* @param bool $psIsDebugMode
*/
public function __construct($psVersion, $psPath, $psIsDebugMode)
{
$this->psVersion = $psVersion;
$this->psPath = $psPath;
$this->psIsDebugMode = $psIsDebugMode;
}
/**
* @return string
*/
public function getPath()
{
if (defined('_PS_CACHE_DIR_')) {
return constant('_PS_CACHE_DIR_');
}
$path = '/var/cache/' . $this->getEnvName();
if (version_compare($this->psVersion, '1.7.0.0', '<')) {
$path = '/cache';
} elseif (version_compare($this->psVersion, '1.7.4.0', '<')) {
$path = '/app/cache/' . $this->getEnvName();
}
return $this->psPath . $path;
}
/**
* @return bool
*/
public function isWritable()
{
return is_writable($this->getPath());
}
/**
* @return bool
*/
public function isReadable()
{
return is_readable($this->getPath());
}
/**
* @return string
*/
private function getEnvName()
{
return $this->psIsDebugMode ? 'dev' : 'prod';
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
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,48 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace Tests\Unit\Cache;
use PHPUnit\Framework\TestCase;
use PrestaShop\ModuleLibCacheDirectoryProvider\Cache\CacheDirectoryProvider;
class CacheDirectoryProviderTest extends TestCase
{
public function testItIsReturnValidPathForVersionLessThan17()
{
$cacheDirectory = new CacheDirectoryProvider('1.6.1.0', __DIR__, true);
$this->assertSame(__DIR__ . '/cache', $cacheDirectory->getPath());
}
public function testItIsReturnValidPathForVersionLessThan174()
{
$cacheDirectory = new CacheDirectoryProvider('1.7.0.0', __DIR__, true);
$this->assertSame(__DIR__ . '/app/cache/dev', $cacheDirectory->getPath());
}
public function testItIsReturnValidPathForVersionGreaterThanEq174()
{
$cacheDirectory = new CacheDirectoryProvider('1.7.4.0', __DIR__, true);
$this->assertSame(__DIR__ . '/var/cache/dev', $cacheDirectory->getPath());
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
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,9 @@
<phpunit stopOnFailure="true"
backupGlobals="true"
>
<testsuites>
<testsuite name="Unit">
<directory>.</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
$config = new PrestaShop\CodingStandards\CsFixer\Config();
$config
->setUsingCache(false)
->getFinder()
->in(__DIR__)
->exclude('vendor');
return $config;

View File

@@ -0,0 +1,84 @@
# PrestaShop module library for FAQ
This library retrieves the FAQ (Frequently Asked Questions) content from PrestaShop APIs.
It is most likely to be used in PrestaShop modules, but can be integrated in any PHP project.
This library is compatible with PHP 5.6 and above.
## Installation
```
composer require prestashop/module-lib-faq
```
## Usage
* Common case
The simplest way to use this library is:
```php
use PrestaShop\ModuleLibFaq\Faq;
// [...]
$faq = new Faq('your module key', _PS_VERSION, 'the current iso code');
$faqContent = $faq->getFaq();
```
* With additional code to run in case of error
```php
use PrestaShop\ModuleLibFaq\Faq;
// [...]
$faq = new Faq('your module key', _PS_VERSION, 'the current iso code');
$faq->setErrorCallable(function(\Exception $e) { /* send to logger */ });
$faqContent = $faq->getFaq();
```
The content returned is an array of categories, each of them having an array of questions/answers.
Example of json that will be `json_decode`d by the library:
```json
{
"id_faq": 117,
"module_key": "82bc76354cfef947e06f1cc78f5efe2e",
"id_product": 46347,
"categories": [
{
"id_faq_category": 142,
"position": 1,
"id_faq": 117,
"title": "Questions about payments",
"blocks": [
{
"id_faq_block": 522,
"question": "Will my customers be able to see the PrestaShop Checkout payment method?",
"answer": "No, PrestaShop Checkout is the name of the service and the module. Your customers will only see the payment methods they are already familiar with including: credit card, PayPal, and/or another major payment method used in their country.",
"version_min": "",
"version_max": ""
},
]
},
{
"id_faq_category": 141,
"position": 2,
"id_faq": 117,
"title": "Questions about refund feature",
"blocks": [
{
"id_faq_block": 521,
"question": "I am trying to issue a refund for a PrestaShop order, but an error message says, “Capture could not be refunded due to insufficient funds.” However, I know I have the funds in my PayPal account.",
"answer": "For refunds for an order paid for using a different currency than the ones available on your PayPal account, you have two options:\n\n- Adding all the currencies covered in your store to your PayPal account to avoid rejections of cross-currency transactions and any refund issues.\n\nTo do so, go to paypal.com > Login > Settings > My Money > Currencies management > Add a currency\n\n- Contacting PayPal and asking them to activate the cross-currency refund option. (Via the \"\"Contact us\"\" tab on paypal.com).",
"version_min": "",
"version_max": ""
}
]
}
]
}
```

View File

@@ -0,0 +1,37 @@
{
"name": "prestashop/module-lib-faq",
"description": "Library allowing modules to load FAQ from PrestaShop servers",
"type": "library",
"license": "AFL-3.0",
"authors": [
{
"name": "PrestaShop SA",
"email": "contact@prestashop.com"
}
],
"config": {
"platform": {
"php": "7.2.5"
}
},
"require": {
"php": "^7.2 || ^8.0",
"prestashop/module-lib-guzzle-adapter": "^0"
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"prestashop/php-dev-tools": "^4.2",
"php-http/mock-client": "^1.5",
"guzzlehttp/guzzle": "^7.4"
},
"autoload": {
"psr-4": {
"PrestaShop\\ModuleLibFaq\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"PrestaShop\\ModuleLibFaq\\Tests\\": "tests/"
}
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,136 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibFaq;
use GuzzleHttp\Psr7\Request;
use Http\Client\Exception\HttpException;
use Http\Client\Exception\TransferException;
use Prestashop\ModuleLibGuzzleAdapter\ClientFactory;
use Psr\Http\Client\ClientInterface;
/**
* Retrieve the FAQ of the module
*/
class Faq
{
public const BASE_URL = 'https://api.addons.prestashop.com/request/faq/';
/**
* @var ClientInterface
*/
private $client;
/**
* @var Parameters
*/
private $parameters;
/**
* Method to call in case of error
*
* @var callable|null
*/
private $errorCallable;
/**
* @param string $moduleKey
* @param string $psVersion
* @param string $isoCode
*/
public function __construct($moduleKey, $psVersion, $isoCode, array $options = [])
{
$this->parameters = (new Parameters())
->setModuleKey($moduleKey)
->setPsVersion($psVersion)
->setIsoCode($isoCode);
// Allow client options to be customized
$options = array_merge_recursive([
'base_url' => self::BASE_URL,
// If available from PrestaShop, use _PS_CACHE_CA_CERT_FILE_ constant
'verify' => defined('_PS_CACHE_CA_CERT_FILE_') && file_exists(constant('_PS_CACHE_CA_CERT_FILE_')) ? constant('_PS_CACHE_CA_CERT_FILE_') : true,
'defaults' => [
'timeout' => 10,
],
], $options);
$this->client = (new ClientFactory())->getClient($options);
}
/**
* Wrapper of method post from guzzle client
*
* @return array|false return response or false if no response
*/
public function getFaq()
{
try {
$response = $this->client->sendRequest(new Request('POST', $this->parameters->getFaqUri()));
} catch (HttpException $e) {
if (is_callable($this->errorCallable)) {
call_user_func($this->errorCallable, $e);
}
$response = $e->getResponse();
} catch (TransferException $e) {
if (is_callable($this->errorCallable)) {
call_user_func($this->errorCallable, $e);
}
return false;
}
$data = json_decode($response->getBody()->getContents(), true);
return !empty($data['categories']) ? $data : false;
}
/**
* @return ClientInterface
*/
public function getClient()
{
return $this->client;
}
/**
* @param ClientInterface $client
*
* @return self
*/
public function setClient(ClientInterface $client)
{
$this->client = $client;
return $this;
}
/**
* Allow modules to run specific code in case of exception
*
* @return self
*/
public function setErrorCallable(callable $c)
{
$this->errorCallable = $c;
return $this;
}
}

View File

@@ -0,0 +1,115 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibFaq;
class Parameters
{
/**
* Module key to identify on which module we will retrieve the faq
*
* @var string
*/
private $moduleKey;
/**
* The version of PrestaShop
*
* @var string
*/
private $psVersion;
/**
* In which language the faq will be retrieved
*
* @var string
*/
private $isoCode;
/**
* Generate the route to retrieve the faq
*
* @return string route
*/
public function getFaqUri()
{
return $this->getModuleKey() . '/' . $this->getPsVersion() . '/' . $this->getIsoCode();
}
/**
* @param string $moduleKey
*
* @return self
*/
public function setModuleKey($moduleKey)
{
$this->moduleKey = $moduleKey;
return $this;
}
/**
* @param string $psVersion
*
* @return self
*/
public function setPsVersion($psVersion)
{
$this->psVersion = $psVersion;
return $this;
}
/**
* @param string $isoCode
*
* @return self
*/
public function setIsoCode($isoCode)
{
$this->isoCode = $isoCode;
return $this;
}
/**
* @return string
*/
public function getIsoCode()
{
return $this->isoCode;
}
/**
* @return string
*/
public function getPsVersion()
{
return $this->psVersion;
}
/**
* @return string
*/
public function getModuleKey()
{
return $this->moduleKey;
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,117 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibFaq\Tests;
use Exception;
use GuzzleHttp\Psr7\Response as Psr7Response;
use Http\Client\Exception\TransferException;
use Http\Mock\Client;
use PHPUnit\Framework\TestCase;
use PrestaShop\ModuleLibFaq\Faq;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
class FaqTest extends TestCase
{
/**
* This is not a unit test, as it runs the call to the marketplace
* Data for PS Checkout module
*/
public function testWorkingTest()
{
$faq = new Faq('82bc76354cfef947e06f1cc78f5efe2e', '1.7.5.2', 'fr');
$faq->setClient(new class() implements ClientInterface {
public function sendRequest(RequestInterface $request): ResponseInterface
{
return new Psr7Response(200, [], file_get_contents('tests/faqExample.json'));
}
});
$faqContent = $faq->getFaq();
$this->assertInternalType('array', $faqContent);
$this->assertTrue(count($faqContent) > 0);
}
/**
* Mock Client so we fake an HTTP error
*/
public function testCallableIsTriggered()
{
$faq = (new Faq('<InvalidKey>', '1.7.5.2', 'fr'));
$client = new Client();
$faq->setClient($client);
$exception = new TransferException('Server error response [url] https://api.addons.prestashop.com/request/faq/%3CInvalidKey%3E/1.7.5.2/fr [status code] 500 [reason phrase] Internal Server Error');
$client->addException($exception);
/**
* we create here a callable that will be triggered because of the error during the API call.
*
* It provides an example in which we retrieve the exception in the caller.
*/
$message = false;
$callable = function (Exception $e) use (&$message) {
$message = $e->getMessage();
};
$faq->setErrorCallable($callable);
/**
* Run test
*/
$faqContent = $faq->getFaq();
$this->assertSame(false, $faqContent);
$this->assertSame(
'Server error response [url] https://api.addons.prestashop.com/request/faq/%3CInvalidKey%3E/1.7.5.2/fr [status code] 500 [reason phrase] Internal Server Error',
$message
);
}
public function testCallableIsNotCalledByDefault()
{
$faq = (new Faq('<InvalidKey>', '1.7.5.2', 'fr'));
/*
* Mock of the API
*/
$faq->setClient(new class() implements ClientInterface {
public function sendRequest(RequestInterface $request): ResponseInterface
{
return new Psr7Response(200);
}
});
/**
* Create error callable
*/
$callable = function () {
throw new Exception('The callable should not be called!');
};
$faq->setErrorCallable($callable);
/**
* Run test
*/
$faqContent = $faq->getFaq();
$this->assertSame(false, $faqContent);
}
}

View File

@@ -0,0 +1,38 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibFaq\Tests;
use PHPUnit\Framework\TestCase;
use PrestaShop\ModuleLibFaq\Parameters;
class ParametersTest extends TestCase
{
public function testReturnsTheRouteApi()
{
$parameters = new Parameters();
$parameters->setIsoCode('fr')
->setModuleKey('someModuleKey')
->setPsVersion('1.7.5.2');
$this->assertSame('someModuleKey/1.7.5.2/fr', $parameters->getFaqUri());
}
}

View File

@@ -0,0 +1,129 @@
{
"id_faq": 117,
"module_key": "82bc76354cfef947e06f1cc78f5efe2e",
"id_product": 46347,
"categories": [
{
"id_faq_category": 136,
"position": 0,
"id_faq": 117,
"title": "",
"blocks": [
{
"id_faq_block": 516,
"question": "Pourquoi le moyen de paiement par Carte de Crédit est limité à 500$ ?",
"answer": "Si le moyen de paiement \"Carte de crédit & de débit\" est indiqué come \"Limité à 500$\", cela signifie que votre compte n'est pas totalement validé.\nVous avez surement reçu un mail pour vous le préciser : il faut fournir plus d'informations dans votre compte PayPal pour lever cette limite. Ces informations complémentaires peuvent être : une carte bancaire pour prélever de l'argent si besoin, un compte banciare à créditer si besoin, une pièce d'identité pour des vérifications suplémentaires, ... Rendez vous sur votre compte PayPal sur www.paypal.com et regardez les notifications sur la cloche en haut à droite et suivez les instructions.\n\nNe tardez pas, après avoir fourni ces informations supplémentaires, les équipes PayPal léveront la limite sous 72h pour vous permettre de recevoir des paiement par carte sans limité.\nAvant cette levée de limite vous ne pourrez pas retirer l'argent de votre compte ni en virer, vous pouvez uniquement créditer votre compte PayPal avec les paiements de vos clients.\nSi vous recevez plus que 500$ de commandes par carte, le moyen de paiement par carte sera désactivé jusqu'à validation totale de votre compte.\nEn attendant, vous pouvez toujours recevoir des paiements via PayPal sans limite.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 519,
"question": "Comment activer les moyens de paiement locaux ?",
"answer": "La simple création d'un compte PayPal avec le module PrestaShop Checkout suffit pour activer les moyens de paiements locaux. Vous n'aurez pas besoin de créer d'autres comptes marchands pour chacun des moyens de paiement.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 520,
"question": "Comment passer du module Paypal ou Stripe à PrestaShop Checkout ? ",
"answer": "\"1 - Dans l'espace \"\"Personnaliser\"\" dans l'interface dadministration de votre boutique, cliquez sur \"\"Paiement\"\" > \"\"Modes de paiement\"\".  L'ensemble des modules de paiement qui sont activés s'affichent.  Cherchez le module \"\"PrestaShop Checkout\"\" et cliquez sur \"\"Configurer\"\". \n\n2 - Suivez les étapes d'onboarding de PrestaShop Checkout : compte PrestaShop Checkout et compte PayPal\n\n3 - Quand les moyens de paiement sont activés (Stripe, Paypal ...) et que vous les retrouvez dans votre parcours d'achat de votre boutique, allez dans “Moyen de Paiement” de votre back-office et désactivez les autres modules de paiement.  \"\n",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 523,
"question": "Quelles sont les commissions du module “PrestaShop Checkout” ?",
"answer": "Ces tarifications sont disponibles via ce lien: https://www.prestashop.com/fr/prestashop-checkout ",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 524,
"question": "Je suis déjà marchand avec un compte PayPal business, puis-je garder ma tarification actuelle ?",
"answer": "Les tarifications de PrestaShop Checkout sont uniformisées pour tous les utilisateurs mais vous pouvez contacter PayPal pour ajuster la tarification à votre utilisation et conserver votre tarification actuelle.\n\nPour cela, allez dans la rubrique \"Contactez nous\" sur paypal.com pour communiquer avec un conseiller PayPal.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 537,
"question": "Lorsque je lie mon compte PayPal, je clique sur Retourner à la boutique, la fenêtre PayPal se ferme mais rien ne se passe et mon compte PayPal n'est pas lié. Que puis-je faire ? ",
"answer": "Si le compte PayPal n'est pas lié, même après avoir fini le parcours de connexion PayPal, vérifiez que votre serveur ou back-office n'est protégé par un htaccess ou un VPN. Si c'est le cas, le module ne pourra pas recevoir de webhook pour mettre à jour votre identifiant PayPal et lier le compte.\nÇa ne devrait pas être le cas pour une configuration classique de serveur mais si c'est le cas, pas de souci, veuillez whitelister l'adresse IP pour l'URL suivante a minima : https://YOURSTORE.com/shop/index.php?fc=module&module=ps_checkout&controller=DispatchWebHook.\n\nL'adresse IP publique à whitelister si besoin : 35.195.228.149.",
"version_min": "",
"version_max": ""
}
]
},
{
"id_faq_category": 142,
"position": 1,
"id_faq": 117,
"title": "Questions à propos des paiements",
"blocks": [
{
"id_faq_block": 522,
"question": "Est-ce que mes clients verront le moyen de paiement PrestaShop Checkout ?",
"answer": "Non, PrestaShop Checkout est le nom du service et du module. Vos clients ne verront que les moyens de paiement qu'ils connaissent : par carte de crédit, par PayPal ou autre moyen de paiement incontournable dans leur pays.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 525,
"question": "Pourquoi certains achats aboutissent dans l'état ",
"answer": "\"Les commandes passées dans une devise non configurée dans le compte PayPal sont soient converties automatiquement soient en attente de validation manuelle depuis l'interface PayPal, selon la configuration.\n\nSi vous souhaitez accepter automatiquement les achats de certaines devises sans les valider à la main vous pouvez soit :\n\n- Ajouter cette devise dans la liste des devises supportées par votre compte PayPal:\n\nDepuis votre compte PayPal (www.paypal.com) > Paramètres de Compte > Profil Professionnel > Argent, cartes et comptes bancaires\n\n- Activer les conversions automatiques :\n\nDepuis votre compte PayPal (www.paypal.com)Paramètres de Compte > Compte et Sécurité > Préférences de Paiement > Bloquer les paiements > Mettre à jour > Préférence de réception de paiements\"",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 527,
"question": "Quelles sont les commissions du module “PrestaShop Checkout” ?",
"answer": "Ces tarifications sont affichées via ce lien: https://www.prestashop.com/fr/prestashop-checkout \n\nCe sont les seules commissions existantes, appliquées seulement sur les transaction validées, il n'y a pas de coûts additionnels ou d'abonnement à payer à PayPal ou PrestaShop.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 528,
"question": "PrestaShop Checkout est-il compatible avec les réglementations Européennes DSP ? ",
"answer": "PrestaShop Checkout est dès à présent compatible avec les réglementations DSP 2 entrant en vigueur en septembre.\n\nLe paiement par carte est compatible avec le 3DSecure et les clés digitales des différentes banques. \n",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 529,
"question": "Quels sont les différents statuts de transactions du module PrestaShop Checkout?",
"answer": "Une commande peut être :\n\n- En attente de paiement (par Carte Bancaire ou par PayPal)\n\n- Paiement accepté,\n\n- Remboursé,\n\n- Remboursement Partiel,\n\n- Erreur de Paiement.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 530,
"question": "Est ce que le paiement par carte est compatible avec tous types de cartes et tous les navigateurs internet ?",
"answer": "Vos clients pourront finaliser leur commande quelque soit leur carte de crédit avec PrestaShop Checkout.\nDe plus, tous les navigateurs peuvent être utilisés par vos visiteurs, sauf Internet Explorer, qui n'est plus maintenu par Microsoft, et dont l'utilisation se fait de plus en plus rare.",
"version_min": "",
"version_max": ""
},
{
"id_faq_block": 536,
"question": "Comment sont mises à jours les commandes si la configuration de ma boutique crée des commandes ",
"answer": "Si certains paniers génèrent différentes commandes (pour répartir les produits sur différents transporteurs ou pour des raisons de stockage dans différents entrepôts par exemple) seule la commande \"parent\" sera mise à jour pour des changements de statut arrivant après la finalisation de commande. Il est possible de mettre à jour les commandes \"enfants\" à la main si besoin. ",
"version_min": "",
"version_max": ""
}
]
},
{
"id_faq_category": 141,
"position": 2,
"id_faq": 117,
"title": "Questions à propos des remboursements",
"blocks": [
{
"id_faq_block": 521,
"question": "J'essaye de faire un remboursement sur ma commande PrestaShop, mais un message d'erreur me dit que je n'ai pas les fonds suffisants ",
"answer": "Pour les remboursements d'une commande faite dans une monnaie différente que celles disponibles sur votre compte PayPal, vous avez 2 choix :\n\n- Ajouter toutes les monnaies de votre boutique dans votre compte PayPal, pour éviter de refuser les transactions cross-monnaie ou les problèmes de remboursements.\n\nPour cela, rendez-vous sur paypal.com > Login > Settings > My Money > Currencies management > Add a currency\n\n- Contacter PayPal et leur demander d'activer l'option de remboursement cross-monnaie. (onglet \"\"Nous contacter\"\" sur paypal.com).",
"version_min": "",
"version_max": ""
}
]
}
]
}

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
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,6 @@
parameters:
paths:
- ../../src
checkMissingIterableValueType: false
level: 7

View File

@@ -0,0 +1,11 @@
<?php
$config = new PrestaShop\CodingStandards\CsFixer\Config();
$config
->setUsingCache(false)
->getFinder()
->in(__DIR__)
->exclude('vendor');
return $config;

View File

@@ -0,0 +1,65 @@
# PrestaShop module library for Guzzle clients
Plug modules to the Guzzle client available on a running shop.
This library is compatible with PHP 5.6.0 and above. Please check [Version Guidance](#version-guidance) for the PHP version compatibility.
[![Latest Stable Version](https://img.shields.io/packagist/v/prestashop/module-lib-guzzle-adapter.svg?style=flat-square)](https://packagist.org/packages/prestashop/module-lib-guzzle-adapter) [![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6.0-8892BF.svg?style=flat-square)](https://php.net/) [![Quality Control Status](https://img.shields.io/github/workflow/status/prestashopcorp/module-lib-guzzle-adapter/PHP%20tests?style=flat-square)](https://github.com/PrestaShopCorp/module-lib-guzzle-adapter/actions/workflows/php.yml)
## Installation
```
composer require prestashop/module-lib-guzzle-adapter
```
## Version Guidance
| Version | Status | Packagist -| Namespace | Repo | Docs | PHP Version |
|---------|----------------|----------------------|--------------|---------------------|---------------------|--------------|
| <=0.5 | Stable | `prestashop/module-lib-guzzle-adapter` | `Prestashop\ModuleLibGuzzleAdapter` | [v0.x][lib-1-repo] | N/A | >=7.2.5 |
| >=0.6 | Latest | `prestashop/module-lib-guzzle-adapter` | `Prestashop\ModuleLibGuzzleAdapter` | [v0.x][lib-php5-repo] | N/A | >=5.6.0 |
| 1.x | Latest | `prestashop/module-lib-guzzle-adapter` | `Prestashop\ModuleLibGuzzleAdapter` | [v1.x][lib-1-repo] | N/A | >=7.2.5 |
[lib-1-repo]: https://github.com/PrestaShopCorp/module-lib-guzzle-adapter/tree/main
[lib-php5-repo]: https://github.com/PrestaShopCorp/module-lib-guzzle-adapter/tree/0.x
## Usage
```php
# Getting a client (Psr\Http\Client\ClientInterface)
$options = ['base_url' => 'http://some-url/'];
$client = (new Prestashop\ModuleLibGuzzleAdapter\ClientFactory())->getClient($options);
# Sending requests and receive response (Psr\Http\Message\ResponseInterface)
$response = $this->client->sendRequest(
new GuzzleHttp\Psr7\Request('POST', 'some-uri')
);
```
In this example, `base_url` is known to be a option for Guzzle 5 that has been replaced for `base_uri` on Guzzle 6+. Any of this two keys can be set, as it will be automatically modified for the other client if needed.
The automatically changed properties are:
| Guzzle 5 property | | Guzzle 7 property |
| ------------- | -- | ------------- |
| base_url | <=> | base_url |
| defaults.authorization | <=> | authorization |
| defaults.exceptions | <=> | http_errors |
| defaults.timeout | <=> | timeout |
## Why this library?
Making HTTP requests in a PrestaShop module can be done in several ways. With `file_get_contents()`, cURL or Guzzle when provided by the core.
Depending on the running version of PrestaShop, the bundled version of Guzzle can be different:
* PrestaShop 1.7: Guzzle 5
* PrestaShop 8: Guzzle 7
Having a module compatible for these two major PrestaShop versions can be tricky. The classes provided by the two Guzzle version are named the same, but their methods are different.
It is not possible for a module contributor to require its own Guzzle dependency either, because PHP cannot load different versions of a same class and he would never know which one would be loaded first.
## Implementation notes
This library reuses the idea behind [PHP-HTTP](https://docs.php-http.org), where the implementation of HTTP requests should be the same (PSR) whatever the client chosen.
The client files from [php-http/guzzle5-adapter](https://github.com/php-http/guzzle5-adapter) and [php-http/guzzle7-adapter](https://github.com/php-http/guzzle7-adapter) have been copied in this repository because these libraries both require a different version Guzzle in their dependencies to work. Requiring them together would conflict, so we duplicated the client adapters to be safe.

View File

@@ -0,0 +1,39 @@
{
"name": "prestashop/module-lib-guzzle-adapter",
"description": "Plug modules to the Guzzle client available on a running shop",
"license": "AFL-3.0",
"autoload": {
"psr-4": {
"Prestashop\\ModuleLibGuzzleAdapter\\": "src/"
}
},
"authors": [
{
"name": "PrestaShop SA",
"email": "contact@prestashop.com"
}
],
"provide": {
"php-http/client-implementation": "1.0",
"psr/http-client-implementation": "1.0"
},
"require": {
"php": ">=5.6.0",
"psr/http-message": "^1.0",
"php-http/message": "^1.7",
"php-http/httplug": "~1.1",
"guzzlehttp/psr7": "~1.9"
},
"require-dev": {
"phpunit/phpunit": "^9.5|^8.5|^5.7",
"prestashop/php-dev-tools": "^4.2|^3.16"
},
"scripts": {
"phpstan-g5": "vendor/bin/phpstan analyze -c tests/Guzzle5/phpstan.neon",
"phpstan-g7": "vendor/bin/phpstan analyze -c tests/Guzzle7/phpstan.neon",
"phpstan": [
"@phpstan-g5",
"@phpstan-g7"
]
}
}

View File

@@ -0,0 +1,40 @@
{
"name": "prestashop/module-lib-guzzle-adapter",
"description": "Plug modules to the Guzzle client available on a running shop",
"license": "AFL-3.0",
"autoload": {
"psr-4": {
"Prestashop\\ModuleLibGuzzleAdapter\\": "src/"
}
},
"authors": [
{
"name": "PrestaShop SA",
"email": "contact@prestashop.com"
}
],
"provide": {
"php-http/client-implementation": "1.0",
"psr/http-client-implementation": "1.0"
},
"require": {
"php": ">=5.6.0",
"psr/http-message": "^1.0",
"php-http/message": "^1.7",
"php-http/httplug": "~1.1",
"guzzlehttp/psr7": "~1.9"
},
"require-dev": {
"phpstan/phpstan": "^1.7",
"phpunit/phpunit": "^9.5|^8.5|^5.7",
"prestashop/php-dev-tools": "^4.2|^3.16"
},
"scripts": {
"phpstan-g5": "vendor/bin/phpstan analyze -c tests/Guzzle5/phpstan.neon",
"phpstan-g7": "vendor/bin/phpstan analyze -c tests/Guzzle7/phpstan.neon",
"phpstan": [
"@phpstan-g5",
"@phpstan-g7"
]
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,49 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle5\Client as Guzzle5Client;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle5\Config as Guzzle5Config;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle7\Client as Guzzle7Client;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle7\Config as Guzzle7Config;
class ClientFactory
{
/**
* @var VersionDetection
*/
private $versionDetection;
public function __construct(VersionDetection $versionDetection = null)
{
$this->versionDetection = $versionDetection ?: new VersionDetection();
}
/**
* @param array<string, mixed> $config
*
* @return \Prestashop\ModuleLibGuzzleAdapter\Interfaces\HttpClientInterface
*/
public function getClient(array $config = [])
{
return $this->initClient($config);
}
/**
* @param array<string, mixed> $config
*
* @return \Prestashop\ModuleLibGuzzleAdapter\Interfaces\HttpClientInterface
*/
private function initClient(array $config = [])
{
if ($this->versionDetection->getGuzzleMajorVersionNumber() >= 7) {
return Guzzle7Client::createWithConfig(
Guzzle7Config::fixConfig($config)
);
}
return Guzzle5Client::createWithConfig(
Guzzle5Config::fixConfig($config)
);
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter\Guzzle5;
use Exception;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception as GuzzleExceptions;
use GuzzleHttp\Message\RequestInterface as GuzzleRequest;
use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
use GuzzleHttp\Psr7\Response;
use Http\Client\Exception as HttplugException;
use Prestashop\ModuleLibGuzzleAdapter\Interfaces\HttpClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* @author GeLo <geloen.eric@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*
* @see https://github.com/php-http/guzzle5-adapter/blob/master/src/Client.php
*/
class Client implements HttpClientInterface
{
/**
* @var ClientInterface
*/
private $client;
/**
* @param ClientInterface|null $client
*/
public function __construct(ClientInterface $client = null)
{
$this->client = $client ?: new GuzzleClient();
}
/**
* Factory method to create the Guzzle 5 adapter with custom Guzzle configuration.
* Added after duplication of adapter.
*
* @param array<string, mixed> $config
*
* @return self
*/
public static function createWithConfig(array $config)
{
return new self(new GuzzleClient($config));
}
/**
* {@inheritdoc}
*/
public function sendRequest(RequestInterface $request)
{
$guzzleRequest = $this->createRequest($request);
try {
$response = $this->client->send($guzzleRequest);
} catch (GuzzleExceptions\TransferException $e) {
throw $this->handleException($e, $request);
}
return $this->createResponse($response);
}
/**
* Converts a PSR request into a Guzzle request.
*
* @param RequestInterface $request
*
* @return GuzzleRequest
*/
private function createRequest(RequestInterface $request)
{
$options = [
'exceptions' => false,
'allow_redirects' => false,
];
$options['version'] = $request->getProtocolVersion();
$options['headers'] = $request->getHeaders();
$body = (string) $request->getBody();
$options['body'] = '' === $body ? null : $body;
return $this->client->createRequest(
$request->getMethod(),
(string) $request->getUri(),
$options
);
}
/**
* Converts a Guzzle response into a PSR response.
*
* @param GuzzleResponse $response
*
* @return ResponseInterface
*/
private function createResponse(GuzzleResponse $response)
{
$body = $response->getBody();
return new Response(
$response->getStatusCode(),
$response->getHeaders(),
isset($body) ? $body->detach() : null,
$response->getProtocolVersion()
);
}
/**
* Converts a Guzzle exception into an Httplug exception.
*
* @param GuzzleExceptions\TransferException $exception
* @param RequestInterface $request
*
* @return \Exception
*/
private function handleException(GuzzleExceptions\TransferException $exception, RequestInterface $request)
{
if ($exception instanceof GuzzleExceptions\ConnectException) {
return new HttplugException\NetworkException($exception->getMessage(), $request, $exception);
}
if ($exception instanceof GuzzleExceptions\RequestException) {
// Make sure we have a response for the HttpException
if ($exception->hasResponse()) {
$psr7Response = $this->createResponse($exception->getResponse());
return new HttplugException\HttpException(
$exception->getMessage(),
$request,
$psr7Response,
$exception
);
}
return new HttplugException\RequestException($exception->getMessage(), $request, $exception);
}
return new HttplugException\TransferException($exception->getMessage(), 0, $exception);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter\Guzzle5;
use Prestashop\ModuleLibGuzzleAdapter\Interfaces\ConfigInterface;
class Config implements ConfigInterface
{
/**
* {@inheritdoc}
*/
public static function fixConfig(array $config)
{
if (isset($config['timeout'])) {
$config['defaults']['timeout'] = $config['timeout'];
unset($config['timeout']);
}
if (isset($config['headers'])) {
$config['defaults']['headers'] = $config['headers'];
unset($config['headers']);
}
if (isset($config['http_errors'])) {
$config['defaults']['exceptions'] = $config['http_errors'];
unset($config['http_errors']);
}
if (isset($config['base_uri'])) {
$config['base_url'] = $config['base_uri'];
unset($config['base_uri']);
}
return $config;
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,82 @@
<?php
declare(strict_types=1);
namespace Prestashop\ModuleLibGuzzleAdapter\Guzzle7;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Utils;
use Prestashop\ModuleLibGuzzleAdapter\Interfaces\HttpClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* HTTP Adapter for Guzzle 7.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*
* @see https://github.com/php-http/guzzle7-adapter/blob/master/src/Client.php
*/
class Client implements HttpClientInterface
{
/**
* @var ClientInterface
*/
private $client;
public function __construct(ClientInterface $client = null)
{
if (!$client) {
$client = self::buildClient();
}
$this->client = $client;
}
/**
* Factory method to create the Guzzle 7 adapter with custom Guzzle configuration.
*
* @param array<string, mixed> $config
*
* @return self
*/
public static function createWithConfig(array $config): Client
{
return new self(self::buildClient($config));
}
/**
* {@inheritdoc}
*/
public function sendRequest(RequestInterface $request): ResponseInterface
{
return $this->sendAsyncRequest($request)->wait();
}
/**
* {@inheritdoc}
*/
public function sendAsyncRequest(RequestInterface $request): Promise
{
$promise = $this->client->sendAsync($request);
return new Promise($promise, $request);
}
/**
* Build the Guzzle client instance.
*
* @param array<string, mixed> $config
*/
private static function buildClient(array $config = []): GuzzleClient
{
$handlerStack = new HandlerStack(Utils::chooseHandler());
$handlerStack->push(Middleware::prepareBody(), 'prepare_body');
$config = array_merge(['handler' => $handlerStack], $config);
return new GuzzleClient($config);
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Prestashop\ModuleLibGuzzleAdapter\Guzzle7;
use Prestashop\ModuleLibGuzzleAdapter\Interfaces\ConfigInterface;
class Config implements ConfigInterface
{
/**
* {@inheritdoc}
*/
public static function fixConfig(array $config): array
{
if (isset($config['defaults'])) {
if (isset($config['defaults']['timeout'])) {
$config['timeout'] = $config['defaults']['timeout'];
}
if (isset($config['defaults']['exceptions'])) {
$config['http_errors'] = $config['defaults']['exceptions'];
}
if (isset($config['defaults']['headers'])) {
$config['headers'] = $config['defaults']['headers'];
}
unset($config['defaults']);
}
if (isset($config['base_url'])) {
$config['base_uri'] = $config['base_url'];
unset($config['base_url']);
}
return $config;
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter\Guzzle7\Exception;
use Http\Client\Exception;
final class UnexpectedValueException extends \UnexpectedValueException implements Exception
{
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,132 @@
<?php
declare(strict_types=1);
namespace Prestashop\ModuleLibGuzzleAdapter\Guzzle7;
use GuzzleHttp\Exception as GuzzleExceptions;
use GuzzleHttp\Promise\PromiseInterface;
use Http\Client\Exception as HttplugException;
use Http\Promise\Promise as HttpPromise;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle7\Exception\UnexpectedValueException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Wrapper around Guzzle promises.
*
* @author Joel Wurtz <joel.wurtz@gmail.com>
*/
final class Promise implements HttpPromise
{
/**
* @var PromiseInterface
*/
private $promise;
/**
* @var string State of the promise
*/
private $state;
/**
* @var ResponseInterface
*/
private $response;
/**
* @var HttplugException
*/
private $exception;
/**
* @var RequestInterface
*/
private $request;
public function __construct(PromiseInterface $promise, RequestInterface $request)
{
$this->request = $request;
$this->state = self::PENDING;
$this->promise = $promise->then(function ($response) {
$this->response = $response;
$this->state = self::FULFILLED;
return $response;
}, function ($reason) use ($request) {
$this->state = self::REJECTED;
if ($reason instanceof HttplugException) {
$this->exception = $reason;
} elseif ($reason instanceof GuzzleExceptions\GuzzleException) {
$this->exception = $this->handleException($reason, $request);
} elseif ($reason instanceof \Throwable) {
$this->exception = new HttplugException\TransferException('Invalid exception returned from Guzzle7', 0, $reason);
} else {
$this->exception = new UnexpectedValueException('Reason returned from Guzzle7 must be an Exception');
}
throw $this->exception;
});
}
/**
* {@inheritdoc}
*/
public function then(callable $onFulfilled = null, callable $onRejected = null)
{
return new static($this->promise->then($onFulfilled, $onRejected), $this->request);
}
/**
* {@inheritdoc}
*/
public function getState()
{
return $this->state;
}
/**
* {@inheritdoc}
*/
public function wait($unwrap = true)
{
$this->promise->wait(false);
if ($unwrap) {
if (self::REJECTED == $this->getState()) {
throw $this->exception;
}
return $this->response;
}
}
/**
* Converts a Guzzle exception into an Httplug exception.
*
* @return HttplugException
*/
private function handleException(GuzzleExceptions\GuzzleException $exception, RequestInterface $request)
{
if ($exception instanceof GuzzleExceptions\ConnectException) {
return new HttplugException\NetworkException($exception->getMessage(), $exception->getRequest(), $exception);
}
if ($exception instanceof GuzzleExceptions\RequestException) {
// Make sure we have a response for the HttpException
if ($exception->hasResponse()) {
return new HttplugException\HttpException(
$exception->getMessage(),
$exception->getRequest(),
$exception->getResponse(),
$exception
);
}
return new HttplugException\RequestException($exception->getMessage(), $exception->getRequest(), $exception);
}
return new HttplugException\TransferException($exception->getMessage(), 0, $exception);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,10 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter\Interfaces;
/**
* Every HTTP client related exception MUST implement this interface.
*/
interface ClientExceptionInterface extends \Throwable
{
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter\Interfaces;
interface ConfigInterface
{
/**
* When a client is created with the config of another version,
* this method makes sure the keys match.
*
* @param array<string, mixed> $config
*
* @return array<string, mixed>
*/
public static function fixConfig(array $config);
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter\Interfaces;
use Psr\Http\Message\RequestInterface;
/**
* HTTP Client Interface
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Victor Bocharsky <victor@symfonycasts.com>
*
* @see https://github.com/php-fig/http-client/blob/master/src/ClientInterface.php
*/
interface HttpClientInterface
{
/**
* Sends a PSR-7 request and returns a PSR-7 response.
*
* @param \Psr\Http\Message\RequestInterface $request
*
* @return \Psr\Http\Message\ResponseInterface
*
* @throws ClientExceptionInterface If an error happens while processing the request
*/
public function sendRequest(RequestInterface $request);
}

View File

@@ -0,0 +1,11 @@
<?php
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,26 @@
<?php
namespace Prestashop\ModuleLibGuzzleAdapter;
class VersionDetection
{
/**
* @return int|null
*/
public function getGuzzleMajorVersionNumber()
{
// Guzzle 7 and above
if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
// @phpstan-ignore-next-line
return (int) \GuzzleHttp\ClientInterface::MAJOR_VERSION;
}
// Before Guzzle 7
if (defined('\GuzzleHttp\ClientInterface::VERSION')) {
// @phpstan-ignore-next-line
return (int) \GuzzleHttp\ClientInterface::VERSION[0];
}
return null;
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,5 @@
{
"require-dev": {
"guzzlehttp/guzzle": "^5.3.4"
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,10 @@
parameters:
paths:
- ../../src
excludePaths:
- ../../src/Guzzle7
bootstrapFiles:
- vendor/autoload.php
reportUnmatchedIgnoredErrors: false
level: 6

View File

@@ -0,0 +1,5 @@
{
"require-dev": {
"guzzlehttp/guzzle": "^7.4.3"
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,14 @@
parameters:
paths:
- ../../src
excludePaths:
- ../../src/Guzzle5
bootstrapFiles:
- vendor/autoload.php
reportUnmatchedIgnoredErrors: false
ignoreErrors:
-
message: '#^Invalid type Http\\Client\\Exception to throw.$#'
path: ../../src/Guzzle7/Promise.php
level: 6

View File

@@ -0,0 +1,11 @@
<?php
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,103 @@
<?php
use PHPUnit\Framework\TestCase;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle5\Config;
class Guzzle5ConfigTest extends TestCase
{
public function testConfigWithoutChangeNeeded()
{
$originalConfig = [
'base_url' => 'http://some-url',
'verify' => 'path/to/cert',
'defaults' => [
'timeout' => 10,
],
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals($originalConfig, $actualConfig);
}
public function testAllConfigKeys()
{
$originalConfig = [
'base_uri' => 'http://some-url',
'verify' => 'path/to/cert',
'timeout' => 10,
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'base_url' => 'http://some-url',
'verify' => 'path/to/cert',
'defaults' => [
'timeout' => 10,
],
], $actualConfig);
}
public function testBaseUri()
{
$originalConfig = [
'base_uri' => 'http://some-url',
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'base_url' => 'http://some-url',
], $actualConfig);
}
public function testTimeout()
{
$originalConfig = [
'timeout' => 10,
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'defaults' => [
'timeout' => 10,
],
], $actualConfig);
}
public function testExceptions()
{
$originalConfig = [
'http_errors' => true,
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'defaults' => [
'exceptions' => true,
],
], $actualConfig);
}
public function testAuthorization()
{
$originalConfig = [
'headers' => [
'Authorization' => 'Bearer someMegaToken',
],
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'defaults' => [
'headers' => [
'Authorization' => 'Bearer someMegaToken',
],
],
], $actualConfig);
}
}

View File

@@ -0,0 +1,101 @@
<?php
use PHPUnit\Framework\TestCase;
use Prestashop\ModuleLibGuzzleAdapter\Guzzle7\Config;
class Guzzle7ConfigTest extends TestCase
{
public function testConfigWithoutChangeNeeded()
{
$originalConfig = [
'base_uri' => 'http://some-url',
'verify' => 'path/to/cert',
'timeout' => 10,
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals($originalConfig, $actualConfig);
}
public function testAllConfigKeys()
{
$originalConfig = [
'base_url' => 'http://some-url',
'verify' => 'path/to/cert',
'defaults' => [
'timeout' => 10,
],
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'base_uri' => 'http://some-url',
'verify' => 'path/to/cert',
'timeout' => 10,
], $actualConfig);
}
public function testBaseUri()
{
$originalConfig = [
'base_url' => 'http://some-url',
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'base_uri' => 'http://some-url',
], $actualConfig);
}
public function testTimeout()
{
$originalConfig = [
'defaults' => [
'timeout' => 10,
],
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'timeout' => 10,
], $actualConfig);
}
public function testExceptions()
{
$originalConfig = [
'defaults' => [
'exceptions' => true,
],
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'http_errors' => true,
], $actualConfig);
}
public function testAuthorization()
{
$originalConfig = [
'defaults' => [
'headers' => [
'Authorization' => 'Bearer someMegaToken',
],
],
];
$actualConfig = Config::fixConfig($originalConfig);
$this->assertEquals([
'headers' => [
'Authorization' => 'Bearer someMegaToken',
],
], $actualConfig);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,170 @@
Academic Free License (“AFL”) v. 3.0
This Academic Free License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the
following licensing notice adjacent to the copyright notice for the Original
Work:
Licensed under the Academic Free License version 3.0
1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, for the duration of the copyright, to do
the following:
a) to reproduce the Original Work in copies, either alone or as part of a
collective work;
b) to translate, adapt, alter, transform, modify, or arrange the Original
Work, thereby creating derivative works ("Derivative Works") based upon
the Original Work;
c) to distribute or communicate copies of the Original Work and
Derivative Works to the public, under any license of your choice that
does not contradict the terms and conditions, including Licensors
reserved rights and remedies, in this Academic Free License;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor grants You a worldwide, royalty-free,
non-exclusive, sublicensable license, under patent claims owned or controlled
by the Licensor that are embodied in the Original Work as furnished by the
Licensor, for the duration of the patents, to make, use, sell, offer for sale,
have made, and import the Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred
form of the Original Work for making modifications to it and all available
documentation describing how to modify the Original Work. Licensor agrees to
provide a machine-readable copy of the Source Code of the Original Work along
with each copy of the Original Work that Licensor distributes. Licensor
reserves the right to satisfy this obligation by placing a machine-readable
copy of the Source Code in an information repository reasonably calculated to
permit inexpensive and convenient access by You for as long as Licensor
continues to distribute the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
of any contributors to the Original Work, nor any of their trademarks or
service marks, may be used to endorse or promote products derived from this
Original Work without express prior permission of the Licensor. Except as
expressly stated herein, nothing in this License grants any license to
Licensors trademarks, copyrights, patents, trade secrets or any other
intellectual property. No patent license is granted to make, use, sell, offer
for sale, have made, or import embodiments of any patent claims other than the
licensed claims defined in Section 2. No license is granted to the trademarks
of Licensor even if such marks are included in the Original Work. Nothing in
this License shall be interpreted to prohibit Licensor from licensing under
terms different from this License any Original Work that Licensor otherwise
would have a right to license.
5) External Deployment. The term "External Deployment" means the use,
distribution, or communication of the Original Work or Derivative Works in any
way such that the Original Work or Derivative Works may be used by anyone
other than You, whether those works are distributed or communicated to those
persons or made available as an application intended for use over a network.
As an express condition for the grants of license hereunder, You must treat
any External Deployment by You of the Original Work or a Derivative Work as a
distribution under section 1(c).
6) Attribution Rights. You must retain, in the Source Code of any Derivative
Works that You create, all copyright, patent, or trademark notices from the
Source Code of the Original Work, as well as any notices of licensing and any
descriptive text identified therein as an "Attribution Notice." You must cause
the Source Code for any Derivative Works that You create to carry a prominent
Attribution Notice reasonably calculated to inform recipients that You have
modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
the copyright in and to the Original Work and the patent rights granted herein
by Licensor are owned by the Licensor or are sublicensed to You under the
terms of this License with the permission of the contributor(s) of those
copyrights and patent rights. Except as expressly stated in the immediately
preceding sentence, the Original Work is provided under this License on an "AS
IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without
limitation, the warranties of non-infringement, merchantability or fitness for
a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK
IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this
License. No license to the Original Work is granted by this License except
under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory,
whether in tort (including negligence), contract, or otherwise, shall the
Licensor be liable to anyone for any indirect, special, incidental, or
consequential damages of any character arising as a result of this License or
the use of the Original Work including, without limitation, damages for loss
of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. This limitation of liability shall not
apply to the extent applicable law prohibits such limitation.
9) Acceptance and Termination. If, at any time, You expressly assented to this
License, that assent indicates your clear and irrevocable acceptance of this
License and all of its terms and conditions. If You distribute or communicate
copies of the Original Work or a Derivative Work, You must make a reasonable
effort under the circumstances to obtain the express assent of recipients to
the terms of this License. This License conditions your rights to undertake
the activities listed in Section 1, including your right to create Derivative
Works based upon the Original Work, and doing so without honoring these terms
and conditions is prohibited by copyright law and international treaty.
Nothing in this License is intended to affect copyright exceptions and
limitations (including “fair use” or “fair dealing”). This License shall
terminate immediately and You may no longer exercise any of the rights granted
to You by this License upon your failure to honor the conditions in Section
1(c).
10) Termination for Patent Action. This License shall terminate automatically
and You may no longer exercise any of the rights granted to You by this
License as of the date You commence an action, including a cross-claim or
counterclaim, against Licensor or any licensee alleging that the Original Work
infringes a patent. This termination provision shall not apply for an action
alleging patent infringement by combinations of the Original Work with other
software or hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
License may be brought only in the courts of a jurisdiction wherein the
Licensor resides or in which Licensor conducts its primary business, and under
the laws of that jurisdiction excluding its conflict-of-law provisions. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded. Any use of the Original
Work outside the scope of this License or after its termination shall be
subject to the requirements and penalties of copyright or patent law in the
appropriate jurisdiction. This section shall survive the termination of this
License.
12) Attorneys Fees. In any action to enforce the terms of this License or
seeking damages relating thereto, the prevailing party shall be entitled to
recover its costs and expenses, including, without limitation, reasonable
attorneys' fees and costs incurred in connection with such action, including
any appeal of such action. This section shall survive the termination of this
License.
13) Miscellaneous. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent necessary
to make it enforceable.
14) Definition of "You" in This License. "You" throughout this License,
whether in upper or lower case, means an individual or a legal entity
exercising rights under, and complying with all of the terms of, this License.
For legal entities, "You" includes any entity that controls, is controlled by,
or is under common control with you. For purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity.
15) Right to Use. You may use the Original Work in all ways not otherwise
restricted or conditioned by this License or by law, and Licensor promises not
to interfere with or be responsible for such uses by You.
16) Modification of This License. This License is Copyright © 2005 Lawrence
Rosen. Permission is granted to copy, distribute, or communicate this License
without modification. Nothing in this License permits You to modify this
License as applied to the Original Work or to Derivative Works. However, You
may modify the text of this License and copy, distribute or communicate your
modified version (the "Modified License") and apply it to other original works
of authorship subject to the following conditions: (i) You may not indicate in
any way that your Modified License is the "Academic Free License" or "AFL" and
you may not use those names in the name of your Modified License; (ii) You
must replace the notice specified in the first paragraph above with the notice
"Licensed under <insert your license name here>" or with a notice of your own
that is not confusingly similar to the notice in this License; and (iii) You
may not claim that your original works are open source software unless your
Modified License has been approved by Open Source Initiative (OSI) and You
comply with its license review and certification process.

View File

@@ -0,0 +1,67 @@
# PrestaShop Service Container for Modules
This repository includes the service container from Symfony that you can use in your PrestaShop Module.
## Pre-requisites
You should install this library only on a PrestaShop environment and with PHP 5.6.0 minimum.
## Installation
```bash
# PrestaShop 1.7+
composer require prestashop/module-lib-service-container
# PrestaShop 1.6
composer require prestashop/module-lib-service-container
composer require symfony/config:^3.4 symfony/dependency-injection:^3.4 symfony/expression-language:^3.4 symfony/yaml:^3.4
```
When this project is successfully added to your dependencies, you can add the new ServiceContainer to your module and use it.
PrestaShop runs with Symfony components from version 1.7, so dependancies are not required anymore here. I you plan to run your module on PrestaShop, Symfony dependencies must be required separately.
## Usage
To use this library, it's simple :
- First, declare your new service Container in your root module PHP file (like mymodule.php at your root project folder) :
```
/**
* @var ServiceContainer
*/
private $serviceContainer;
```
- And instantiate it in the constructor with the module name and its local path :
```
$this->serviceContainer = new ServiceContainer($this->name, $this->getLocalPath());
```
- You can add a new function on your root module PHP file, like getService, to retrieve your service name in the new service container :
```
/**
* @param string $serviceName
*
* @return mixed
*/
public function getService($serviceName)
{
return $this->serviceContainer->getService($serviceName);
}
```
- Then, you have to declare your service in the services.yml file. You must declare your services in the config/ folder. From Symfony 4, services must be explicitely declared as public to be loaded with the method `getService()`;
We split the services in two folders in the config : /front and /admin folders. So the tree should be like :
```
/mymodule
/config
/front
services.yml
/admin
services.yml
common.yml
```
- Of course, you can include a common file, with common services that are use in front and admin project by an import in the services.yml file :
```
imports:
- { resource: ../common.yml }
```
Now you can add your services in the services.yml like you were in a Symfony project ;)

View File

@@ -0,0 +1,49 @@
{
"name": "prestashop/module-lib-service-container",
"description": "Service container to use on prestashop modules",
"keywords": ["prestashop", "modules", "composer", "package"],
"license": "AFL-3.0",
"authors": [
{
"name": "PrestaShop SA",
"email": "contact@prestashop.com"
}
],
"type": "library",
"config": {
"platform": {
"php": "5.6.0"
}
},
"require": {
"php": ">=5.6.0",
"prestashop/module-lib-cache-directory-provider": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "~5.7"
},
"suggest": {
"symfony/config": "Needed when the running PrestaShop does not already run with Symfony",
"symfony/dependency-injection": "Needed when the running PrestaShop does not already run with Symfony",
"symfony/expression-language": "Needed when the running PrestaShop does not already run with Symfony",
"symfony/yaml": "Needed when the running PrestaShop does not already run with Symfony"
},
"autoload": {
"psr-4": {
"PrestaShop\\ModuleLibServiceContainer\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"phpstan-sf3": "tests/Symfony3/vendor/bin/phpstan analyze -c tests/Symfony3/phpstan.neon",
"phpstan-sf4": "tests/Symfony4/vendor/bin/phpstan analyze -c tests/Symfony4/phpstan.neon",
"phpstan": [
"@phpstan-sf3",
"@phpstan-sf4"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
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,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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibServiceContainer\DependencyInjection;
use PrestaShop\ModuleLibCacheDirectoryProvider\Cache\CacheDirectoryProvider;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
class ContainerProvider
{
/**
* @var string Module Name
*/
private $moduleName;
/**
* @var string Module Local Path
*/
private $moduleLocalPath;
/**
* @var CacheDirectoryProvider
*/
private $cacheDirectory;
/**
* @param string $moduleName
* @param string $moduleLocalPath
* @param CacheDirectoryProvider $cacheDirectory
*/
public function __construct($moduleName, $moduleLocalPath, CacheDirectoryProvider $cacheDirectory)
{
$this->moduleName = $moduleName;
$this->moduleLocalPath = $moduleLocalPath;
$this->cacheDirectory = $cacheDirectory;
}
/**
* @param string $containerName
*
* @return ContainerInterface
*/
public function get($containerName)
{
$containerClassName = ucfirst($this->moduleName)
. ucfirst($containerName)
. 'Container'
;
$containerFilePath = $this->cacheDirectory->getPath() . '/' . $containerClassName . '.php';
$containerConfigCache = new ConfigCache($containerFilePath, constant('_PS_MODE_DEV_'));
if ($containerConfigCache->isFresh()) {
require_once $containerFilePath;
return new $containerClassName();
}
$containerBuilder = new ContainerBuilder();
$containerBuilder->set(
$this->moduleName . '.cache.directory',
$this->cacheDirectory
);
$moduleConfigPath = $this->moduleLocalPath
. 'config/'
. $containerName
;
$loader = new YamlFileLoader($containerBuilder, new FileLocator($moduleConfigPath));
$loader->load('services.yml');
$containerBuilder->compile();
$dumper = new PhpDumper($containerBuilder);
$containerConfigCache->write(
$dumper->dump(['class' => $containerClassName]),
$containerBuilder->getResources()
);
return $containerBuilder;
}
}

View File

@@ -0,0 +1,83 @@
<?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 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace PrestaShop\ModuleLibServiceContainer\DependencyInjection;
use PrestaShop\ModuleLibCacheDirectoryProvider\Cache\CacheDirectoryProvider;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ServiceContainer
{
/**
* @var string Module Name
*/
private $moduleName;
/**
* @var string Module Local Path
*/
private $moduleLocalPath;
/**
* @var ContainerInterface
*/
private $container;
/**
* @param string $moduleName
* @param string $moduleLocalPath
*/
public function __construct($moduleName, $moduleLocalPath)
{
$this->moduleName = $moduleName;
$this->moduleLocalPath = $moduleLocalPath;
}
/**
* @param string $serviceName
*
* @return object|null
*/
public function getService($serviceName)
{
if (null === $this->container) {
$this->initContainer();
}
return $this->container->get($serviceName);
}
/**
* Instantiate a new ContainerProvider
*
* @return void
*/
private function initContainer()
{
$cacheDirectory = new CacheDirectoryProvider(
constant('_PS_VERSION_'),
constant('_PS_ROOT_DIR_'),
constant('_PS_MODE_DEV_')
);
$containerProvider = new ContainerProvider($this->moduleName, $this->moduleLocalPath, $cacheDirectory);
$this->container = $containerProvider->get(defined('_PS_ADMIN_DIR_') || defined('PS_INSTALLATION_IN_PROGRESS') || PHP_SAPI === 'cli' ? 'admin' : 'front');
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
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,9 @@
{
"require-dev": {
"phpstan/phpstan": "^1.7",
"symfony/config": "^3.4",
"symfony/dependency-injection": "^3.4",
"symfony/expression-language": "^3.4",
"symfony/yaml": "^3.4"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
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,15 @@
parameters:
paths:
- ../../src
excludePaths:
- ../../src/Symfony4
bootstrapFiles:
- vendor/autoload.php
- ../../vendor/autoload.php
reportUnmatchedIgnoredErrors: false
dynamicConstantNames:
- _PS_VERSION_
- _PS_ROOT_DIR_
- _PS_MODE_DEV_
level: 6

View File

@@ -0,0 +1,9 @@
{
"require-dev": {
"phpstan/phpstan": "^1.7",
"symfony/config": "^4.4",
"symfony/dependency-injection": "^4.4",
"symfony/expression-language": "^4.4",
"symfony/yaml": "^4.4"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
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,15 @@
parameters:
paths:
- ../../src
excludePaths:
- ../../src/Symfony3
bootstrapFiles:
- vendor/autoload.php
- ../../vendor/autoload.php
reportUnmatchedIgnoredErrors: false
dynamicConstantNames:
- _PS_VERSION_
- _PS_ROOT_DIR_
- _PS_MODE_DEV_
level: 6

View File

@@ -0,0 +1,36 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace Tests\Unit\DependencyInjection;
use PHPUnit\Framework\TestCase;
use PrestaShop\ModuleLibCacheDirectoryProvider\Cache\CacheDirectoryProvider;
use PrestaShop\ModuleLibServiceContainer\DependencyInjection\ContainerProvider;
class ContainerProviderTest extends TestCase
{
public function testItIsReturnValidInstance()
{
/** @var CacheDirectoryProvider $cacheDirectory */
$cacheDirectory = $this->createMock(CacheDirectoryProvider::class);
$containerProvider = new ContainerProvider('test', __DIR__, $cacheDirectory);
$this->assertInstanceOf(ContainerProvider::class, $containerProvider);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License 3.0 (AFL-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 <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/
namespace Tests\Unit\DependencyInjection;
use PHPUnit\Framework\TestCase;
use PrestaShop\ModuleLibServiceContainer\DependencyInjection\ServiceContainer;
class ServiceContainerTest extends TestCase
{
public function testItIsReturnValidInstance()
{
$serviceContainer = new ServiceContainer('test', __DIR__);
$this->assertInstanceOf(ServiceContainer::class, $serviceContainer);
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
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,9 @@
<phpunit stopOnFailure="true"
backupGlobals="true"
>
<testsuites>
<testsuite name="Unit">
<directory>.</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,11 @@
<?php
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,12 @@
<?php
$config = new PrestaShop\CodingStandards\CsFixer\Config();
$config
->setUsingCache(false)
->getFinder()
->in(__DIR__)
->exclude('vendor')
->exclude('tests');
return $config;

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 PrestaShopCorp
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,107 @@
# prestashop-accounts-installer
Utility package to install `ps_accounts` module or present data to trigger manual install from psx configuration page.
This module also give you access to `ps_accounts` services through its module service container dealing with the installation status of the module.
### Compatibility Matrix
We aims to follow partially the Prestashop compatibility charts
- [Compatibility Chart Prestashop 1.6 & 1.7](https://devdocs.prestashop.com/1.7/basics/installation/system-requirements/#php-compatibility-chart)
- [Compatibility Chart Prestashop 8](https://devdocs.prestashop.com/8/basics/installation/system-requirements/#php-compatibility-chart)
| ps_account version | Prestashop Version | PHP Version | Event Bus installation
|-----------------------------------------|----------------------|-----------------|-------------------------
| 6.x | >=8.0.0 | ≥7.2 \|\| ≤8.1 | Yes
| 5.x | >=1.7.0 \|\| <8.0.0 | ≥5.6 \|\| ≤7.4 | Yes
| 5.x | >=1.6.1 \|\| <1.7.0 | ≥5.6 \|\| ≤7.4 | No
## Installation
This package is available on [Packagist](https://packagist.org/packages/prestashop/prestashop-accounts-installer),
you can install it via [Composer](https://getcomposer.org).
```shell script
composer require prestashop/prestashop-accounts-installer
```
## Register as a service in your PSx container (recommended)
Example :
```yaml
services:
<your_module>.ps_accounts_installer:
class: 'PrestaShop\PsAccountsInstaller\Installer\Installer'
arguments:
- '5.0.0'
<your_module>.ps_accounts_facade:
class: 'PrestaShop\PsAccountsInstaller\Installer\Facade\PsAccounts'
arguments:
- '@<your_module>.ps_accounts_installer'
```
The name under which you register both services in your service container must be unique to avoid collision with other modules including it.
The `5.0.0` specified argument is the minimum required `ps_account` module version. You should modify it if you need another version.
## How to use it
### Installer
In your module main class `install` method. (Will only do something on PrestaShop 1.7 and above)
```php
$this->getService('ps_accounts.installer')->install();
```
### Presenter
For example in your main module's class `getContent` method.
```php
Media::addJsDef([
'contextPsAccounts' => $this->getService('ps_accounts.facade')
->getPsAccountsPresenter()
->present($this->name),
]);
```
This presenter will serve as default minimal presenter and switch to PsAccountsPresenter data when `ps_accounts` module is installed.
### Accessing PsAccounts Services
Installer class includes accessors to get instances of services from PsAccounts Module :
* getPsAccountsService
* getPsBillingService
The methods above will throw an exception in case `ps_accounts` module is not installed or not in the required version.
Example :
```php
use PrestaShop\PsAccountsInstaller\Installer\Exception\ModuleVersionException;
use PrestaShop\PsAccountsInstaller\Installer\Exception\ModuleNotInstalledException;
try {
$psAccountsService = $this->getService('ps_accounts.facade')->getPsAccountsService();
$shopJwt = $psAccountsService->getOrRefreshToken();
$shopUuid = $psAccountsService->getShopUuid();
$apiUrl = $psAccountsService->getAdminAjaxUrl();
// Your code here
} catch (ModuleNotInstalledException $e) {
// You handle exception here
} catch (ModuleVersionException $e) {
// You handle exception here
}
```

View File

@@ -0,0 +1,28 @@
{
"name": "prestashop/prestashop-accounts-installer",
"type": "library",
"description": "Utility package to install `ps_accounts` module or present data to trigger manual install from psx configuration page.",
"license": "MIT",
"autoload": {
"psr-4": {
"PrestaShop\\PsAccountsInstaller\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"PrestaShop\\PsAccountsInstaller\\Tests\\": "tests/"
}
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"phpunit/phpunit": "^5.7",
"prestashop/php-dev-tools": "3.*",
"friendsofphp/php-cs-fixer": "^2.16",
"fzaninotto/faker": "^1.9"
},
"scripts": {
"test": "XDEBUG_MODE=coverage ./vendor/phpunit/phpunit/phpunit --configuration './phpunit.xml' --bootstrap './tests/bootstrap.php' --test-suffix 'Test.php,.phpt' --coverage-text"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
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,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./tests/bootstrap.php" colors="true" stopOnFailure="false">
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="prestashop-accounts-installer tests">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,7 @@
<?php
namespace PrestaShop\PsAccountsInstaller\Installer\Exception;
class InstallerException extends \Exception
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace PrestaShop\PsAccountsInstaller\Installer\Exception;
class ModuleNotInstalledException extends InstallerException
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace PrestaShop\PsAccountsInstaller\Installer\Exception;
class ModuleVersionException extends InstallerException
{
}

View File

@@ -0,0 +1,11 @@
<?php
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
namespace PrestaShop\PsAccountsInstaller\Installer\Facade;
use PrestaShop\PsAccountsInstaller\Installer\Exception\ModuleNotInstalledException;
use PrestaShop\PsAccountsInstaller\Installer\Exception\ModuleVersionException;
use PrestaShop\PsAccountsInstaller\Installer\Installer;
use PrestaShop\PsAccountsInstaller\Installer\Presenter\InstallerPresenter;
class PsAccounts
{
/**
* Available services class names
*/
const PS_ACCOUNTS_PRESENTER = 'PrestaShop\Module\PsAccounts\Presenter\PsAccountsPresenter';
const PS_ACCOUNTS_SERVICE = 'PrestaShop\Module\PsAccounts\Service\PsAccountsService';
const PS_BILLING_SERVICE = 'PrestaShop\Module\PsAccounts\Service\PsBillingService';
/**
* @var Installer
*/
private $installer;
/**
* PsAccounts constructor.
*
* @param Installer $installer
*/
public function __construct(Installer $installer)
{
$this->installer = $installer;
}
/**
* @param string $serviceName
*
* @return mixed
*
* @throws ModuleNotInstalledException
* @throws ModuleVersionException
*/
public function getService($serviceName)
{
if ($this->installer->isModuleInstalled()) {
if ($this->installer->checkModuleVersion()) {
return \Module::getInstanceByName($this->installer->getModuleName())
->getService($serviceName);
}
throw new ModuleVersionException('The current version of the module "' . $this->installer->getModuleName() . '" is below the required one and should be upgraded. The minimum expected version is: ' . $this->installer->getModuleVersion());
}
throw new ModuleNotInstalledException('Module not installed : ' . $this->installer->getModuleName());
}
/**
* @return mixed
*
* @throws ModuleNotInstalledException
* @throws ModuleVersionException
*/
public function getPsAccountsService()
{
return $this->getService(self::PS_ACCOUNTS_SERVICE);
}
/**
* @return mixed
*
* @throws ModuleNotInstalledException
* @throws ModuleVersionException
*/
public function getPsBillingService()
{
return $this->getService(self::PS_BILLING_SERVICE);
}
/**
* @return mixed
*
* @throws ModuleNotInstalledException
* @throws ModuleVersionException
*/
public function getPsAccountsPresenter()
{
if ($this->installer->isModuleInstalled() &&
$this->installer->checkModuleVersion() &&
$this->installer->isModuleEnabled()
) {
return $this->getService(self::PS_ACCOUNTS_PRESENTER);
} else {
return new InstallerPresenter($this->installer);
}
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,242 @@
<?php
namespace PrestaShop\PsAccountsInstaller\Installer;
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
use PrestaShop\PrestaShop\Core\Addon\Module\ModuleManagerBuilder;
class Installer
{
const PS_ACCOUNTS_MODULE_NAME = 'ps_accounts';
/**
* @var string required version
*/
private $moduleVersion;
/**
* @var string
*/
private $moduleName = self::PS_ACCOUNTS_MODULE_NAME;
/**
* @var \Link
*/
private $link;
/**
* @var mixed
*/
private $moduleManager;
/**
* Installer constructor.
*
* @param string $psAccountsVersion
* @param \Link|null $link
*/
public function __construct($psAccountsVersion, \Link $link = null)
{
$this->moduleVersion = $psAccountsVersion;
if (null === $link) {
$link = new \Link();
}
$this->link = $link;
if (true === $this->isShopVersion17()) {
$moduleManagerBuilder = ModuleManagerBuilder::getInstance();
$this->moduleManager = $moduleManagerBuilder->build();
}
}
/**
* Install ps_accounts module if not installed
* Method to call in every psx modules during the installation process
*
* @return bool
*
* @throws \Exception
*/
public function install()
{
if (true === $this->isModuleInstalled()) {
return true;
}
if (false === $this->isShopVersion17()) {
return true;
}
return $this->moduleManager->install($this->getModuleName());
}
/**
* @return bool
*/
public function isModuleInstalled()
{
if (false === $this->isShopVersion17()) {
return \Module::isInstalled($this->getModuleName());
}
return $this->moduleManager->isInstalled($this->getModuleName());
}
/**
* @return bool
*/
public function isModuleEnabled()
{
if (false === $this->isShopVersion17()) {
return \Module::isEnabled($this->getModuleName());
}
return $this->moduleManager->isEnabled($this->getModuleName());
}
/**
* @return string|null
*
* @throws \PrestaShopException
*/
public function getInstallLink()
{
if ($this->isShopVersion173()) {
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'install',
'module_name' => $this->moduleName,
]);
}
return $this->getAdminLink('AdminModules', true, [], [
'module_name' => $this->moduleName,
'install' => $this->moduleName,
]);
}
/**
* @return string|null
*
* @throws \PrestaShopException
*/
public function getEnableLink()
{
if ($this->isShopVersion173()) {
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'enable',
'module_name' => $this->moduleName,
]);
}
return $this->getAdminLink('AdminModules', true, [], [
'module_name' => $this->moduleName,
'enable' => 1,
]);
}
/**
* @return string|null
*
* @throws \PrestaShopException
*/
public function getUpgradeLink()
{
if ($this->isShopVersion173()) {
$router = SymfonyContainer::getInstance()->get('router');
return \Tools::getHttpHost(true) . $router->generate('admin_module_manage_action', [
'action' => 'upgrade',
'module_name' => $this->moduleName,
]);
}
return $this->getAdminLink('AdminModules', true, [], [
'module_name' => $this->moduleName,
'upgrade' => $this->moduleName,
]);
}
/**
* @return bool
*/
public function isShopVersion17()
{
return version_compare(_PS_VERSION_, '1.7.0.0', '>=');
}
/**
* @return bool
*/
public function isShopVersion173()
{
return version_compare(_PS_VERSION_, '1.7.3.0', '>=');
}
/**
* @return bool
*/
public function checkModuleVersion()
{
$module = \Module::getInstanceByName($this->getModuleName());
if ($module instanceof \Ps_accounts) {
return version_compare(
$module->version,
$this->moduleVersion,
'>='
);
}
return false;
}
/**
* @return string
*/
public function getModuleVersion()
{
return $this->moduleVersion;
}
/**
* @return string
*/
public function getModuleName()
{
return $this->moduleName;
}
/**
* Adapter for getAdminLink from prestashop link class
*
* @param string $controller controller name
* @param bool $withToken include or not the token in the url
* @param array $sfRouteParams
* @param array $params
*
* @return string
*
* @throws \PrestaShopException
*/
protected function getAdminLink($controller, $withToken = true, $sfRouteParams = [], $params = [])
{
if ($this->isShopVersion17()) {
return $this->link->getAdminLink($controller, $withToken, $sfRouteParams, $params);
}
$paramsAsString = '';
foreach ($params as $key => $value) {
$paramsAsString .= "&$key=$value";
}
return \Tools::getShopDomainSsl(true)
. __PS_BASE_URI__
. basename(_PS_ADMIN_DIR_)
. '/' . $this->link->getAdminLink($controller, $withToken)
. $paramsAsString;
}
}

View File

@@ -0,0 +1,75 @@
<?php
namespace PrestaShop\PsAccountsInstaller\Installer\Presenter;
use PrestaShop\PsAccountsInstaller\Installer\Installer;
class InstallerPresenter
{
/**
* @var Installer
*/
private $installer;
/**
* @var \Context
*/
private $context;
/**
* InstallerPresenter constructor.
*
* @param Installer $installer
* @param \Context|null $context
*/
public function __construct(Installer $installer, \Context $context = null)
{
$this->installer = $installer;
if (null === $context) {
$context = \Context::getContext();
}
$this->context = $context;
}
/**
* @return array
*
* @throws \Exception
*/
public function present()
{
// Fallback minimal Presenter
return [
'psIs17' => $this->installer->isShopVersion17(),
'psAccountsInstallLink' => $this->installer->getInstallLink(),
'psAccountsEnableLink' => $this->installer->getEnableLink(),
'psAccountsUpdateLink' => $this->installer->getUpgradeLink(),
'psAccountsIsInstalled' => $this->installer->isModuleInstalled(),
'psAccountsIsEnabled' => $this->installer->isModuleEnabled(),
'psAccountsIsUptodate' => $this->installer->checkModuleVersion(),
'onboardingLink' => null,
'user' => [
'email' => null,
'emailIsValidated' => false,
'isSuperAdmin' => $this->isEmployeeSuperAdmin(),
],
'currentShop' => null,
'shops' => [],
'superAdminEmail' => null,
'ssoResendVerificationEmail' => null,
'manageAccountLink' => null,
];
}
/**
* @return bool
*/
public function isEmployeeSuperAdmin()
{
return $this->context->employee->isSuperAdmin();
}
}

View File

@@ -0,0 +1,11 @@
<?php
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,11 @@
<?php
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,11 @@
<?php
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,23 @@
<?php
namespace PrestaShop\PsAccountsInstaller\Tests;
use Faker\Generator;
class TestCase extends \PHPUnit\Framework\TestCase
{
/**
* @var Generator
*/
public $faker;
/**
* @return void
*/
protected function setUp()
{
parent::setUp();
$this->faker = \Faker\Factory::create();
}
}

Some files were not shown because too many files have changed in this diff Show More