From c454db172f07cb6d027fe35978c9ce71684c4ff1 Mon Sep 17 00:00:00 2001 From: Akolzin Dmitry Date: Wed, 13 Jun 2018 16:13:08 +0300 Subject: [PATCH 1/6] Tests --- .gitignore | 5 +- .travis.yml | 45 + LICENSE | 2 +- README.md | 67 +- RoboFile.php | 159 + composer.json | 36 + composer.lock | 3197 +++++++++++++++++ phpunit.xml | 23 + .../controller/extension/module/retailcrm.php | 148 +- .../en-gb/extension/module/retailcrm.php | 4 +- .../ru-ru/extension/module/retailcrm.php | 4 +- .../model/extension/retailcrm/custom/.gitkeep | 0 .../model/extension/retailcrm/customer.php | 36 +- .../model/extension/retailcrm/history.php | 2 +- .../model/extension/retailcrm/history/v3.php | 27 +- .../extension/retailcrm/history/v4_5.php | 41 +- .../admin}/model/extension/retailcrm/icml.php | 0 .../model/extension/retailcrm/order.php | 91 +- .../model/extension/retailcrm/prices.php | 34 +- .../model/extension/retailcrm/references.php | 0 .../admin}/view/stylesheet/retailcrm.css | 0 .../template/extension/module/retailcrm.tpl | 0 .../template/extension/module/retailcrm.twig | 0 .../catalog}/controller/api/retailcrm.php | 8 +- .../extension/analytics/daemon_collector.php | 0 .../controller/extension/module/retailcrm.php | 66 +- .../model/extension/retailcrm/api.php | 0 .../model/extension/retailcrm/custom/.gitkeep | 0 .../model/extension/retailcrm/customer.php | 26 +- .../model/extension/retailcrm/order.php | 260 +- {system => src/upload/system}/cron/.htaccess | 0 .../upload/system}/cron/dispatch.php | 0 {system => src/upload/system}/cron/export.php | 0 .../upload/system}/cron/history.php | 0 {system => src/upload/system}/cron/icml.php | 0 {system => src/upload/system}/cron/prices.php | 0 .../library/retailcrm/CurlException.php | 0 .../retailcrm/InvalidJsonException.php | 0 .../library/retailcrm/OpencartApiClient.php | 4 +- .../library/retailcrm/RetailcrmApiClient3.php | 0 .../library/retailcrm/RetailcrmApiClient4.php | 0 .../library/retailcrm/RetailcrmApiClient5.php | 0 .../retailcrm/RetailcrmApiResponse.php | 0 .../retailcrm/RetailcrmHistoryHelper.php | 0 .../library/retailcrm/RetailcrmHttpClient.php | 0 .../library/retailcrm/RetailcrmProxy.php | 0 .../system}/library/retailcrm/bootstrap.php | 0 .../system}/library/retailcrm/objects.xml | 0 .../system}/library/retailcrm/retailcrm.php | 32 +- tests/admin/ControllerRetailcrmAdminTest.php | 57 + .../admin/ModelRetailcrmCustomerAdminTest.php | 59 + tests/admin/ModelRetailcrmOrderAdminTest.php | 185 + tests/admin/ModelRetailcrmPricesAdminTest.php | 51 + .../ControllerRetailcrmApiCatalogTest.php | 72 + .../ModelRetailcrmCustomerCatalogTest.php | 62 + .../ModelRetailcrmOrderCatalogTest.php | 191 + tests/opencart_sample_data.sql | 49 + 57 files changed, 4568 insertions(+), 475 deletions(-) create mode 100644 .travis.yml create mode 100644 RoboFile.php create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 phpunit.xml rename {admin => src/upload/admin}/controller/extension/module/retailcrm.php (89%) rename {admin => src/upload/admin}/language/en-gb/extension/module/retailcrm.php (97%) rename {admin => src/upload/admin}/language/ru-ru/extension/module/retailcrm.php (98%) rename {admin => src/upload/admin}/model/extension/retailcrm/custom/.gitkeep (100%) rename {admin => src/upload/admin}/model/extension/retailcrm/customer.php (80%) rename {admin => src/upload/admin}/model/extension/retailcrm/history.php (99%) rename {admin => src/upload/admin}/model/extension/retailcrm/history/v3.php (85%) rename {admin => src/upload/admin}/model/extension/retailcrm/history/v4_5.php (96%) rename {admin => src/upload/admin}/model/extension/retailcrm/icml.php (100%) rename {admin => src/upload/admin}/model/extension/retailcrm/order.php (78%) rename {admin => src/upload/admin}/model/extension/retailcrm/prices.php (87%) rename {admin => src/upload/admin}/model/extension/retailcrm/references.php (100%) rename {admin => src/upload/admin}/view/stylesheet/retailcrm.css (100%) rename {admin => src/upload/admin}/view/template/extension/module/retailcrm.tpl (100%) rename {admin => src/upload/admin}/view/template/extension/module/retailcrm.twig (100%) rename {catalog => src/upload/catalog}/controller/api/retailcrm.php (94%) rename {catalog => src/upload/catalog}/controller/extension/analytics/daemon_collector.php (100%) rename {catalog => src/upload/catalog}/controller/extension/module/retailcrm.php (74%) rename {catalog => src/upload/catalog}/model/extension/retailcrm/api.php (100%) rename {catalog => src/upload/catalog}/model/extension/retailcrm/custom/.gitkeep (100%) rename {catalog => src/upload/catalog}/model/extension/retailcrm/customer.php (83%) rename {catalog => src/upload/catalog}/model/extension/retailcrm/order.php (59%) rename {system => src/upload/system}/cron/.htaccess (100%) rename {system => src/upload/system}/cron/dispatch.php (100%) rename {system => src/upload/system}/cron/export.php (100%) rename {system => src/upload/system}/cron/history.php (100%) rename {system => src/upload/system}/cron/icml.php (100%) rename {system => src/upload/system}/cron/prices.php (100%) rename {system => src/upload/system}/library/retailcrm/CurlException.php (100%) rename {system => src/upload/system}/library/retailcrm/InvalidJsonException.php (100%) rename {system => src/upload/system}/library/retailcrm/OpencartApiClient.php (98%) rename {system => src/upload/system}/library/retailcrm/RetailcrmApiClient3.php (100%) rename {system => src/upload/system}/library/retailcrm/RetailcrmApiClient4.php (100%) rename {system => src/upload/system}/library/retailcrm/RetailcrmApiClient5.php (100%) rename {system => src/upload/system}/library/retailcrm/RetailcrmApiResponse.php (100%) rename {system => src/upload/system}/library/retailcrm/RetailcrmHistoryHelper.php (100%) rename {system => src/upload/system}/library/retailcrm/RetailcrmHttpClient.php (100%) rename {system => src/upload/system}/library/retailcrm/RetailcrmProxy.php (100%) rename {system => src/upload/system}/library/retailcrm/bootstrap.php (100%) rename {system => src/upload/system}/library/retailcrm/objects.xml (100%) rename {system => src/upload/system}/library/retailcrm/retailcrm.php (90%) create mode 100644 tests/admin/ControllerRetailcrmAdminTest.php create mode 100644 tests/admin/ModelRetailcrmCustomerAdminTest.php create mode 100644 tests/admin/ModelRetailcrmOrderAdminTest.php create mode 100644 tests/admin/ModelRetailcrmPricesAdminTest.php create mode 100644 tests/catalog/ControllerRetailcrmApiCatalogTest.php create mode 100644 tests/catalog/ModelRetailcrmCustomerCatalogTest.php create mode 100644 tests/catalog/ModelRetailcrmOrderCatalogTest.php create mode 100644 tests/opencart_sample_data.sql diff --git a/.gitignore b/.gitignore index e18f549..c534094 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ *.settings *.buildpath *.project - +/vendor +/www +/bin +.env diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d429c4c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,45 @@ +language: php + +sudo: false + +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - 7.1 + - 7.2 + +env: + - OC_DB_HOSTNAME=localhost + - OC_DB_USERNAME=root + - OC_DB_PASSWORD=root + - OC_DB_DATABASE=tests_opencart + - OC_DB_DRIVER=mysqli + - OC_USERNAME=admin + - OC_PASSWORD=admin + - OC_EMAIL=you@example.com + - SERVER_PORT=8000 + - SERVER_URL=http://localhost + +before_script: + # Change MySQL root password + - echo "USE mysql;\nUPDATE user SET password=PASSWORD('root') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root + + - composer install + - composer setup + - bin/robo project:deploy + - (php -S localhost:8000 -t www &) 2> /dev/null > /dev/null + - sleep 2 + +script: + - composer test + +deploy: + skip_cleanup: true + provider: script + script: make + on: + php: 7.2 + branch: master + condition: "$DEPLOY = true" \ No newline at end of file diff --git a/LICENSE b/LICENSE index 7942739..270b6f3 100644 --- a/LICENSE +++ b/LICENSE @@ -18,4 +18,4 @@ 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. +THE SOFTWARE \ No newline at end of file diff --git a/README.md b/README.md index 216764c..8050437 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,26 @@ -Opencart module -=============== +# OpenCart Project Template -Module allows integrate CMS Opencart >= 2.3 with [retailCRM](http://retailcrm.pro) +## Getting Started -### Previous versions: + 1. Create a new project: `composer create-project beyondit/opencart-project-template ./my/project/folder -s dev` + 2. Copy the `.env.sample` file to `.env` and set the configuration parameters respectively + 3. Run `bin/robo opencart:setup` and afterwards `bin/robo opencart:run` on command line (`bin/robo opencart:run &` to run in background) + 4. Open `http://localhost:8000` in your browser -[v1.x](https://github.com/retailcrm/opencart-module/tree/v1.x) +## Robo Commands -[v2.x (2.0, 2.1, 2.2)](https://github.com/retailcrm/opencart-module/tree/v2.2) + * `bin/robo opencart:setup` : Install OpenCart with configuration set in `.env` file + * `bin/robo opencart:run` : Run OpenCart on a php build-in web server on port 8000 + * `bin/robo project:deploy` : Mirror contents of the src folder to the OpenCart test environment + * `bin/robo project:watch` : Redeploy after changes inside the src/ folder or the composer.json file + * `bin/robo project:package`: Package a `build.ocmod.zip` inside the target/ folder + +## Writing Tests + + * Based on the [OpenCart Testing Suite](https://github.com/beyondit/opencart-test-suite) project tests can be written. + * After successful setup and deployment, tests can be executed by running the `bin/phpunit` command. + * Two examples inside the `/tests` folder are given, which can be executed as separat Testsuites by `bin/phpunit --testsuite admin-tests` or `bin/phpunit --testsuite catalog-tests` -#### Features: -* Export orders to retailCRM & fetch changes back -* Export product catalog into [ICML](http://www.retailcrm.pro/docs/Developers/ICML) format -#### Install -Copy files to the site root - -``` -unzip master.zip -cp -r opencart-module/* /path/to/site/root -``` - -#### Setup - -* Go to Admin -> Extensions -> Modules -> retailCRM -* Fill you api url & api key -* Specify directories matching - -#### Getting changes in orders - -Add to cron: - -``` -*/5 * * * * /usr/bin/php /path/to/opencart/system/cron/history.php >> /path/to/opencart/system/storage/logs/cronjob_history.log 2>&1 -``` - -#### Setting product catalog export - -Add to cron: - -``` -* */4 * * * /usr/bin/php /path/to/opencart/system/cron/icml.php >> /path/to/opencart/system/storage/logs/cronjob_icml.log 2>&1 -``` - -Your export file will be available by following url - -``` -http://youropencartsite.com/retailcrm.xml -``` - -#### Export existing orders and customers - -You want to run this command onecly: -/usr/bin/php /path/to/opencart/system/cron/export.php diff --git a/RoboFile.php b/RoboFile.php new file mode 100644 index 0000000..f044c4d --- /dev/null +++ b/RoboFile.php @@ -0,0 +1,159 @@ + $value) { + if (substr($option, 0, 3) === 'OC_') { + $option = strtolower(substr($option, 3)); + $this->opencart_config[$option] = $value; + } elseif ($option === 'SERVER_PORT') { + $this->server_port = (int) $value; + } elseif ($option === 'SERVER_URL') { + $this->server_url = $value; + } + } + + $this->opencart_config['http_server'] = $this->server_url.':'.$this->server_port.'/'; + + $required = array('db_username', 'password', 'email'); + $missing = array(); + foreach ($required as $config) { + if (empty($this->opencart_config[$config])) { + $missing[] = 'OC_'.strtoupper($config); + } + } + + if (!empty($missing)) { + $this->printTaskError(" Missing ".implode(', ', $missing)); + $this->printTaskError(" See .env.sample "); + die(); + } + } + + public function opencartSetup() + { + $this->taskDeleteDir('www')->run(); + $this->taskFileSystemStack() + ->mirror('vendor/opencart/opencart/upload', 'www') + ->copy('vendor/beyondit/opencart-test-suite/src/upload/system/config/test-config.php','www/system/config/test-config.php') + ->copy('vendor/beyondit/opencart-test-suite/src/upload/catalog/controller/startup/test_startup.php','www/catalog/controller/startup/test_startup.php') + ->chmod('www', 0777, 0000, true) + ->run(); + + // Create new database, drop if exists already + try { + $conn = new PDO("mysql:host=".$this->opencart_config['db_hostname'], $this->opencart_config['db_username'], $this->opencart_config['db_password']); + $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $conn->exec("DROP DATABASE IF EXISTS `" . $this->opencart_config['db_database'] . "`"); + $conn->exec("CREATE DATABASE `" . $this->opencart_config['db_database'] . "`"); + } + catch(PDOException $e) + { + $this->printTaskError(" Could not connect ot database..."); + } + + $install = $this->taskExec('php')->arg('www/install/cli_install.php')->arg('install'); + foreach ($this->opencart_config as $option => $value) { + $install->option($option, $value); + } + $install->run(); + $this->taskDeleteDir('www/install')->run(); + + $this->restoreSampleData($conn); + + $conn = null; + } + + public function opencartRun() + { + $this->taskServer($this->server_port) + ->dir('www') + ->run(); + } + + public function projectDeploy() + { + $this->taskFileSystemStack() + ->mirror('src/upload', 'www') +// ->copy('src/install.xml','www/system/install.ocmod.xml') if exist modification for OCMOD + ->run(); + } + + public function projectWatch() + { + $this->projectDeploy(); + + $this->taskWatch() + ->monitor('composer.json', function () { + $this->taskComposerUpdate()->run(); + $this->projectDeploy(); + })->monitor('src/', function () { + $this->projectDeploy(); + })->run(); + } + + public function projectPackage() + { + $this->taskDeleteDir('target')->run(); + $this->taskFileSystemStack()->mkdir('target')->run(); + + $zip = new ZipArchive(); + $filename = "target/build.ocmod.zip"; + + if ($zip->open($filename, ZipArchive::CREATE)!==TRUE) { + $this->printTaskError(" Could not create ZipArchive"); + exit(); + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator("src", \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST + ); + foreach ($iterator as $file) { + if ($file->isFile() && $file->isReadable()) { + $zip->addFile($file->getPathname(),substr($file->getPathname(),4)); + } + } + + $zip->close(); + } + + private function restoreSampleData($conn) + { + $sql = file_get_contents('tests/opencart_sample_data.sql'); + + $conn->exec("USE " . $this->opencart_config['db_database']); + + foreach (explode(";\n", $sql) as $sql) { + $sql = trim($sql); + + if ($sql) { + $conn->exec($sql); + } + } + } +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..b541a38 --- /dev/null +++ b/composer.json @@ -0,0 +1,36 @@ +{ + "name": "retailcrm/opencart-module", + "description": "Integration module for Opencart & RetailCRM", + "license": "GPL-3.0", + "type": "project", + "authors": [ + { + "name": "RetailDriverLLC", + "email": "integration@retailcrm.ru" + } + ], + "require-dev": { + "opencart/opencart" : "2.3.0.2", + "vlucas/phpdotenv": "~1.1.0", + "phpunit/phpunit" : "~4.0", + "beyondit/opencart-test-suite": "~2.3.0", + "consolidation/robo": "~1", + "henrikbjorn/lurker": "^1.2" + }, + "config": { + "bin-dir": "bin/", + "preferred-install": "source" + }, + "extra": { + "opencart-dir" : "www" + }, + "scripts" : { + "test-admin": "bin/phpunit --testsuite admin-tests --colors=always", + "test-catalog": "bin/phpunit --testsuite catalog-tests --colors=always", + "test": [ + "@test-admin", + "@test-catalog" + ], + "setup" : "bin/robo opencart:setup" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..4f6742b --- /dev/null +++ b/composer.lock @@ -0,0 +1,3197 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "d99f618b88f08898e6a4fef93d970c82", + "content-hash": "ca0e4df35c14fb6adac2eb994bcf9e44", + "packages": [], + "packages-dev": [ + { + "name": "beyondit/opencart-extension-installer", + "version": "2.3.2", + "source": { + "type": "git", + "url": "https://github.com/beyondit/opencart-extension-installer.git", + "reference": "eeb6d7b65924122b48a846814863ab2ec9b01638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beyondit/opencart-extension-installer/zipball/eeb6d7b65924122b48a846814863ab2ec9b01638", + "reference": "eeb6d7b65924122b48a846814863ab2ec9b01638", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0" + }, + "require-dev": { + "composer/composer": "^1.1", + "phpunit/phpunit": "~4" + }, + "type": "composer-plugin", + "extra": { + "class": "BeyondIT\\Composer\\OpenCartExtensionInstallerPlugin" + }, + "autoload": { + "psr-4": { + "BeyondIT\\Composer\\": "src/BeyondIT/Composer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL 3.0" + ], + "authors": [ + { + "name": "Stefan Huber", + "email": "stefan.huber@beyondit.at" + } + ], + "description": "Custom Composer Installer for installing OpenCart Extensions", + "time": "2017-08-18 08:14:10" + }, + { + "name": "beyondit/opencart-test-suite", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/beyondit/opencart-test-suite.git", + "reference": "066f980fcef884409e606302bf028d04157d83b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beyondit/opencart-test-suite/zipball/066f980fcef884409e606302bf028d04157d83b2", + "reference": "066f980fcef884409e606302bf028d04157d83b2", + "shasum": "" + }, + "require": { + "beyondit/opencart-extension-installer": "~2.3.0", + "phpunit/phpunit": "4.*" + }, + "require-dev": { + "consolidation/robo": "^1.0", + "opencart/opencart": "2.3.0.2", + "phpunit/phpunit": "4.*", + "vlucas/phpdotenv": "~1.1.0" + }, + "type": "opencart-extension", + "extra": { + "src-dir": "src/upload", + "mappings": [ + "system/config/test-config.php", + "catalog/controller/startup/test_startup.php" + ] + }, + "autoload": { + "files": [ + "src/OpenCartTest.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0" + ], + "authors": [ + { + "name": "Stefan Huber", + "email": "stefan.huber@beyondit.at", + "homepage": "http://www.beyondit.at", + "role": "Developer" + } + ], + "description": "Testing Suite for OpenCart Development", + "time": "2016-12-02 10:08:16" + }, + { + "name": "braintree/braintree_php", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/braintree/braintree_php.git", + "reference": "c7e0e2d1ae21d659cddb5507fb0bf181813b5733" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/braintree/braintree_php/zipball/c7e0e2d1ae21d659cddb5507fb0bf181813b5733", + "reference": "c7e0e2d1ae21d659cddb5507fb0bf181813b5733", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-dom": "*", + "ext-hash": "*", + "ext-openssl": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Braintree": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Braintree", + "homepage": "http://www.braintreepayments.com" + } + ], + "description": "Braintree PHP Client Library", + "time": "2015-07-15 15:07:13" + }, + { + "name": "cardinity/cardinity-sdk-php", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/cardinity/cardinity-sdk-php.git", + "reference": "f51f6fbacee393b4eeff7b80be2b1cee77896b4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cardinity/cardinity-sdk-php/zipball/f51f6fbacee393b4eeff7b80be2b1cee77896b4c", + "reference": "f51f6fbacee393b4eeff7b80be2b1cee77896b4c", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~5.1", + "guzzlehttp/log-subscriber": "~1.0", + "guzzlehttp/oauth-subscriber": "0.2.*", + "php": ">=5.4.0", + "symfony/validator": "~2.6" + }, + "require-dev": { + "monolog/monolog": "~1.0", + "phpspec/phpspec": "~2.1", + "phpunit/phpunit": "~4.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cardinity\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Client library for Cardinity credit card processing API", + "homepage": "http://cardinity.com", + "time": "2016-12-29 09:57:23" + }, + { + "name": "consolidation/annotated-command", + "version": "2.8.4", + "source": { + "type": "git", + "url": "https://github.com/consolidation/annotated-command.git", + "reference": "651541a0b68318a2a202bda558a676e5ad92223c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/651541a0b68318a2a202bda558a676e5ad92223c", + "reference": "651541a0b68318a2a202bda558a676e5ad92223c", + "shasum": "" + }, + "require": { + "consolidation/output-formatters": "^3.1.12", + "php": ">=5.4.0", + "psr/log": "^1", + "symfony/console": "^2.8|^3|^4", + "symfony/event-dispatcher": "^2.5|^3|^4", + "symfony/finder": "^2.5|^3|^4" + }, + "require-dev": { + "g1a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^6", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\AnnotatedCommand\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Initialize Symfony Console commands from annotated command class methods.", + "time": "2018-05-25 18:04:25" + }, + { + "name": "consolidation/config", + "version": "1.0.11", + "source": { + "type": "git", + "url": "https://github.com/consolidation/config.git", + "reference": "ede41d946078e97e7a9513aadc3352f1c26817af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/config/zipball/ede41d946078e97e7a9513aadc3352f1c26817af", + "reference": "ede41d946078e97e7a9513aadc3352f1c26817af", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^1.1.0", + "grasmash/expander": "^1", + "php": ">=5.4.0" + }, + "require-dev": { + "g1a/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4", + "satooshi/php-coveralls": "^1.0", + "squizlabs/php_codesniffer": "2.*", + "symfony/console": "^2.5|^3|^4", + "symfony/yaml": "^2.8.11|^3|^4" + }, + "suggest": { + "symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Provide configuration services for a commandline tool.", + "time": "2018-05-27 01:17:02" + }, + { + "name": "consolidation/log", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/consolidation/log.git", + "reference": "dfd8189a771fe047bf3cd669111b2de5f1c79395" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/log/zipball/dfd8189a771fe047bf3cd669111b2de5f1c79395", + "reference": "dfd8189a771fe047bf3cd669111b2de5f1c79395", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "psr/log": "~1.0", + "symfony/console": "^2.8|^3|^4" + }, + "require-dev": { + "g1a/composer-test-scenarios": "^1", + "phpunit/phpunit": "4.*", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.", + "time": "2018-05-25 18:14:39" + }, + { + "name": "consolidation/output-formatters", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/consolidation/output-formatters.git", + "reference": "d78ef59aea19d3e2e5a23f90a055155ee78a0ad5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/d78ef59aea19d3e2e5a23f90a055155ee78a0ad5", + "reference": "d78ef59aea19d3e2e5a23f90a055155ee78a0ad5", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "symfony/console": "^2.8|^3|^4", + "symfony/finder": "^2.5|^3|^4" + }, + "require-dev": { + "g1a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^5.7.27", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.7", + "symfony/console": "3.2.3", + "symfony/var-dumper": "^2.8|^3|^4", + "victorjonsson/markdowndocs": "^1.3" + }, + "suggest": { + "symfony/var-dumper": "For using the var_dump formatter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Consolidation\\OutputFormatters\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Format text by applying transformations provided by plug-in formatters.", + "time": "2018-05-25 18:02:34" + }, + { + "name": "consolidation/robo", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/consolidation/Robo.git", + "reference": "ac563abfadf7cb7314b4e152f2b5033a6c255f6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/ac563abfadf7cb7314b4e152f2b5033a6c255f6f", + "reference": "ac563abfadf7cb7314b4e152f2b5033a6c255f6f", + "shasum": "" + }, + "require": { + "consolidation/annotated-command": "^2.8.2", + "consolidation/config": "^1.0.10", + "consolidation/log": "~1", + "consolidation/output-formatters": "^3.1.13", + "grasmash/yaml-expander": "^1.3", + "league/container": "^2.2", + "php": ">=5.5.0", + "symfony/console": "^2.8|^3|^4", + "symfony/event-dispatcher": "^2.5|^3|^4", + "symfony/filesystem": "^2.5|^3|^4", + "symfony/finder": "^2.5|^3|^4", + "symfony/process": "^2.5|^3|^4" + }, + "replace": { + "codegyre/robo": "< 1.0" + }, + "require-dev": { + "codeception/aspect-mock": "^1|^2.1.1", + "codeception/base": "^2.3.7", + "codeception/verify": "^0.3.2", + "g1a/composer-test-scenarios": "^2", + "goaop/framework": "~2.1.2", + "goaop/parser-reflection": "^1.1.0", + "natxet/cssmin": "3.0.4", + "nikic/php-parser": "^3.1.5", + "patchwork/jsqueeze": "~2", + "pear/archive_tar": "^1.4.2", + "phpunit/php-code-coverage": "~2|~4", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.8" + }, + "suggest": { + "henrikbjorn/lurker": "For monitoring filesystem changes in taskWatch", + "natxet/CssMin": "For minifying CSS files in taskMinify", + "patchwork/jsqueeze": "For minifying JS files in taskMinify", + "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively." + }, + "bin": [ + "robo" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev", + "dev-state": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Robo\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Davert", + "email": "davert.php@resend.cc" + } + ], + "description": "Modern task runner", + "time": "2018-05-27 01:42:53" + }, + { + "name": "container-interop/container-interop", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "shasum": "" + }, + "require": { + "psr/container": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14 19:40:03" + }, + { + "name": "dflydev/dot-access-data", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/3fbd874921ab2c041e899d044585a2ab9795df8a", + "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Dflydev\\DotAccessData": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "time": "2017-01-20 21:14:22" + }, + { + "name": "divido/divido-php", + "version": "v1.15-stable", + "source": { + "type": "git", + "url": "git@github.com:DividoFinancialServices/divido-api-php.git", + "reference": "8edd902ec2be8151331985021107031292b41ca1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DividoFinancialServices/divido-api-php/zipball/8edd902ec2be8151331985021107031292b41ca1", + "reference": "8edd902ec2be8151331985021107031292b41ca1", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "master": "2.0-dev", + "v1.1.1": "1.1.1-dev" + } + }, + "autoload": { + "psr-0": { + "Divido": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Divido PHP library", + "homepage": "https://www.divido.com/", + "keywords": [ + "api", + "divido", + "finance", + "instalments", + "payment processing" + ], + "time": "2018-01-21 15:38:57" + }, + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "grasmash/expander", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/grasmash/expander.git", + "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/grasmash/expander/zipball/95d6037344a4be1dd5f8e0b0b2571a28c397578f", + "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^1.1.0", + "php": ">=5.4" + }, + "require-dev": { + "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4|^5.5.4", + "satooshi/php-coveralls": "^1.0.2|dev-master", + "squizlabs/php_codesniffer": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Grasmash\\Expander\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Grasmick" + } + ], + "description": "Expands internal property references in PHP arrays file.", + "time": "2017-12-21 22:14:55" + }, + { + "name": "grasmash/yaml-expander", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/grasmash/yaml-expander.git", + "reference": "3f0f6001ae707a24f4d9733958d77d92bf9693b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/grasmash/yaml-expander/zipball/3f0f6001ae707a24f4d9733958d77d92bf9693b1", + "reference": "3f0f6001ae707a24f4d9733958d77d92bf9693b1", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^1.1.0", + "php": ">=5.4", + "symfony/yaml": "^2.8.11|^3|^4" + }, + "require-dev": { + "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^4.8|^5.5.4", + "satooshi/php-coveralls": "^1.0.2|dev-master", + "squizlabs/php_codesniffer": "^2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Grasmash\\YamlExpander\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Grasmick" + } + ], + "description": "Expands internal property references in a yaml file.", + "time": "2017-12-16 16:06:03" + }, + { + "name": "guzzlehttp/guzzle", + "version": "5.3.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f9acb4761844317e626a32259205bec1f1bc60d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f9acb4761844317e626a32259205bec1f1bc60d2", + "reference": "f9acb4761844317e626a32259205bec1f1bc60d2", + "shasum": "" + }, + "require": { + "guzzlehttp/ringphp": "^1.1", + "php": ">=5.4.0", + "react/promise": "^2.2" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-01-15 07:18:01" + }, + { + "name": "guzzlehttp/log-subscriber", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/log-subscriber.git", + "reference": "99c3c0004165db721d8ef7bbef60c996210e538a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/log-subscriber/zipball/99c3c0004165db721d8ef7bbef60c996210e538a", + "reference": "99c3c0004165db721d8ef7bbef60c996210e538a", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~4.0 | ~5.0", + "php": ">=5.4.0", + "psr/log": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Subscriber\\Log\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Logs HTTP requests and responses as they are sent over the wire (Guzzle 4+)", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "log", + "plugin" + ], + "time": "2014-10-13 03:31:43" + }, + { + "name": "guzzlehttp/oauth-subscriber", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/oauth-subscriber.git", + "reference": "03f1ebe31d3112526106d0570c80eba6820e86e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/oauth-subscriber/zipball/03f1ebe31d3112526106d0570c80eba6820e86e5", + "reference": "03f1ebe31d3112526106d0570c80eba6820e86e5", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~4.0|~5.0", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Subscriber\\Oauth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle OAuth 1.0 subscriber", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "oauth" + ], + "time": "2014-10-23 22:19:02" + }, + { + "name": "guzzlehttp/ringphp", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/RingPHP.git", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "shasum": "" + }, + "require": { + "guzzlehttp/streams": "~3.0", + "php": ">=5.4.0", + "react/promise": "~2.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Guzzle will use specific adapters if cURL is present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Ring\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "time": "2015-05-20 03:37:09" + }, + { + "name": "guzzlehttp/streams", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/streams.git", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple abstraction over streams of data", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "stream" + ], + "time": "2014-10-12 19:18:40" + }, + { + "name": "henrikbjorn/lurker", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/flint/Lurker.git", + "reference": "712d3ef19bef161daa2ba0e0237c6b875587a089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/flint/Lurker/zipball/712d3ef19bef161daa2ba0e0237c6b875587a089", + "reference": "712d3ef19bef161daa2ba0e0237c6b875587a089", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/config": "^2.2|^3.0", + "symfony/event-dispatcher": "^2.2|^3.0" + }, + "suggest": { + "ext-inotify": ">=0.1.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Lurker": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Yaroslav Kiliba", + "email": "om.dattaya@gmail.com" + }, + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com" + }, + { + "name": "Henrik Bjrnskov", + "email": "henrik@bjrnskov.dk" + } + ], + "description": "Resource Watcher.", + "keywords": [ + "filesystem", + "resource", + "watching" + ], + "time": "2016-03-16 15:22:20" + }, + { + "name": "klarna/kco_rest", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/klarna/kco_rest_php.git", + "reference": "8a2142a2ebb087bb61901d51d1bb9698790e78c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/klarna/kco_rest_php/zipball/8a2142a2ebb087bb61901d51d1bb9698790e78c5", + "reference": "8a2142a2ebb087bb61901d51d1bb9698790e78c5", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": ">=4.2,<6.0", + "php": ">=5.4.0" + }, + "require-dev": { + "apigen/apigen": "4.0.*", + "klarna/apigen-theme": "~1.0", + "phploc/phploc": "2.0.*", + "phpmd/phpmd": "2.1.*", + "phpunit/phpunit": "4.2.*", + "satooshi/php-coveralls": "0.6.*", + "sebastian/phpcpd": "2.0.*", + "squizlabs/php_codesniffer": "1.5.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Klarna AB", + "email": "integration@klarna.com" + } + ], + "description": "Klarna Checkout PHP SDK", + "homepage": "http://developers.klarna.com", + "time": "2015-12-07 09:51:35" + }, + { + "name": "leafo/scssphp", + "version": "v0.0.12", + "source": { + "type": "git", + "url": "https://github.com/leafo/scssphp.git", + "reference": "ff76df3e45af45e808f3fcd516a2cb5cbc77f45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/leafo/scssphp/zipball/ff76df3e45af45e808f3fcd516a2cb5cbc77f45e", + "reference": "ff76df3e45af45e808f3fcd516a2cb5cbc77f45e", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "php": ">=5.3.0", + "phpunit/phpunit": "3.7.*" + }, + "bin": [ + "pscss" + ], + "type": "library", + "autoload": { + "classmap": [ + "scss.inc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT", + "GPL-3.0" + ], + "authors": [ + { + "name": "Leaf Corcoran", + "email": "leafot@gmail.com", + "homepage": "http://leafo.net" + } + ], + "description": "scssphp is a compiler for SCSS written in PHP.", + "homepage": "http://leafo.net/scssphp/", + "time": "2014-07-07 01:51:39" + }, + { + "name": "league/container", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/container.git", + "reference": "43f35abd03a12977a60ffd7095efd6a7808488c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/container/zipball/43f35abd03a12977a60ffd7095efd6a7808488c0", + "reference": "43f35abd03a12977a60ffd7095efd6a7808488c0", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.2", + "php": "^5.4.0 || ^7.0" + }, + "provide": { + "container-interop/container-interop-implementation": "^1.2", + "psr/container-implementation": "^1.0" + }, + "replace": { + "orno/di": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Container\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Phil Bennett", + "email": "philipobenito@gmail.com", + "homepage": "http://www.philipobenito.com", + "role": "Developer" + } + ], + "description": "A fast and intuitive dependency injection container.", + "homepage": "https://github.com/thephpleague/container", + "keywords": [ + "container", + "dependency", + "di", + "injection", + "league", + "provider", + "service" + ], + "time": "2017-05-10 09:20:27" + }, + { + "name": "opencart/opencart", + "version": "2.3.0.2", + "source": { + "type": "git", + "url": "https://github.com/opencart/opencart.git", + "reference": "85e0f35ae96197e0aa92a4aedd3aad76eebd2961" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opencart/opencart/zipball/85e0f35ae96197e0aa92a4aedd3aad76eebd2961", + "reference": "85e0f35ae96197e0aa92a4aedd3aad76eebd2961", + "shasum": "" + }, + "require": { + "braintree/braintree_php": "3.2.0", + "cardinity/cardinity-sdk-php": "^1.0", + "divido/divido-php": ">=1.1.1", + "klarna/kco_rest": "^2.2", + "leafo/scssphp": "0.0.12", + "php": ">=5.4.0" + }, + "type": "project", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0+" + ], + "description": "OpenCart", + "homepage": "http://www.opencart.com", + "keywords": [ + "ecommerce", + "framework", + "opencart", + "opensource" + ], + "time": "2016-08-01 13:43:14" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11 18:02:19" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-30 07:14:17" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14 14:27:02" + }, + { + "name": "phpspec/prophecy", + "version": "1.7.6", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2018-04-18 13:57:24" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-10-06 15:47:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2017-11-27 13:52:08" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26 11:10:40" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.12", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2017-12-04 08:55:13" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.36", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.2.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2017-06-21 08:07:12" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-10-02 06:51:40" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14 16:28:37" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10 12:19:37" + }, + { + "name": "react/promise", + "version": "v2.6.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "5e60e5596a5422287f9d2205f405bef2ae0cef4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/5e60e5596a5422287f9d2205f405bef2ae0cef4b", + "reference": "5e60e5596a5422287f9d2205f405bef2ae0cef4b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "time": "2018-06-11 11:05:43" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-01-29 09:50:25" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2017-05-22 07:24:03" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-08-18 05:49:44" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-06-17 09:04:28" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-10-03 07:41:43" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, + { + "name": "symfony/config", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "73e055cf2e6467715f187724a0347ea32079967c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/73e055cf2e6467715f187724a0347ea32079967c", + "reference": "73e055cf2e6467715f187724a0347ea32079967c", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/dependency-injection": "<3.3", + "symfony/finder": "<3.3" + }, + "require-dev": { + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0", + "symfony/finder": "~3.3|~4.0", + "symfony/yaml": "~3.0|~4.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2018-05-14 16:49:53" + }, + { + "name": "symfony/console", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "36f83f642443c46f3cf751d4d2ee5d047d757a27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/36f83f642443c46f3cf751d4d2ee5d047d757a27", + "reference": "36f83f642443c46f3cf751d4d2ee5d047d757a27", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-05-16 08:49:21" + }, + { + "name": "symfony/debug", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/b28fd73fefbac341f673f5efd707d539d6a19f68", + "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2018-05-16 14:03:39" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fdd5abcebd1061ec647089c6c41a07ed60af09f8", + "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/dependency-injection": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2018-04-06 07:35:25" + }, + { + "name": "symfony/filesystem", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0", + "reference": "8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2018-05-16 08:49:21" + }, + { + "name": "symfony/finder", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/472a92f3df8b247b49ae364275fb32943b9656c6", + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2018-05-16 08:49:21" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30 19:57:29" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "3296adf6a6454a050679cde90f95350ad604b171" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-04-26 10:06:28" + }, + { + "name": "symfony/process", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "4cbf2db9abcb01486a21b7a059e03a62fae63187" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/4cbf2db9abcb01486a21b7a059e03a62fae63187", + "reference": "4cbf2db9abcb01486a21b7a059e03a62fae63187", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2018-05-16 08:49:21" + }, + { + "name": "symfony/translation", + "version": "v3.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/eee6c664853fd0576f21ae25725cfffeafe83f26", + "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.8" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/intl": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2016-07-30 07:22:48" + }, + { + "name": "symfony/validator", + "version": "v2.8.41", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "96bbfd5534d2e07ba45255bad27ee90d3bc121a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/96bbfd5534d2e07ba45255bad27ee90d3bc121a3", + "reference": "96bbfd5534d2e07ba45255bad27ee90d3bc121a3", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation": "~2.4|~3.0.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "egulias/email-validator": "^1.2.1", + "symfony/config": "~2.2|~3.0.0", + "symfony/expression-language": "~2.4|~3.0.0", + "symfony/http-foundation": "~2.3|~3.0.0", + "symfony/intl": "~2.7.25|^2.8.18|~3.2.5", + "symfony/property-access": "~2.3|~3.0.0", + "symfony/yaml": "^2.0.5|~3.0.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "egulias/email-validator": "Strict (RFC compliant) email validation", + "symfony/config": "", + "symfony/expression-language": "For using the 2.4 Expression validator", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For using the 2.4 Validator API", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Validator Component", + "homepage": "https://symfony.com", + "time": "2018-05-07 06:57:27" + }, + { + "name": "symfony/yaml", + "version": "v3.4.11", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2018-05-03 23:18:14" + }, + { + "name": "vlucas/phpdotenv", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa", + "reference": "0cac554ce06277e33ddf9f0b7ade4b8bbf2af3fa", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Dotenv": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "homepage": "http://github.com/vlucas/phpdotenv", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2015-05-30 15:59:26" + }, + { + "name": "webmozart/assert", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2018-01-29 19:49:41" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..90272e8 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,23 @@ + + + + + ./tests/catalog/ + + + ./tests/admin/ + + + + + + \ No newline at end of file diff --git a/admin/controller/extension/module/retailcrm.php b/src/upload/admin/controller/extension/module/retailcrm.php similarity index 89% rename from admin/controller/extension/module/retailcrm.php rename to src/upload/admin/controller/extension/module/retailcrm.php index b55fd02..b6e08aa 100644 --- a/admin/controller/extension/module/retailcrm.php +++ b/src/upload/admin/controller/extension/module/retailcrm.php @@ -12,7 +12,7 @@ class ControllerExtensionModuleRetailcrm extends Controller { private $_error = array(); - protected $log, $statuses, $payments, $deliveryTypes, $retailcrmApiClient; + protected $log, $statuses, $payments, $deliveryTypes, $retailcrmApiClient, $moduleTitle, $tokenTitle; public $children, $template; public function __construct($registry) @@ -20,6 +20,7 @@ class ControllerExtensionModuleRetailcrm extends Controller parent::__construct($registry); $this->load->library('retailcrm/retailcrm'); $this->moduleTitle = $this->retailcrm->getModuleTitle(); + $this->tokenTitle = $this->retailcrm->getTokenTitle(); } /** @@ -31,12 +32,13 @@ class ControllerExtensionModuleRetailcrm extends Controller { $this->load->model('setting/setting'); - $this->model_setting_setting - ->editSetting($this->moduleTitle, array( - $this->moduleTitle . '_status' => 1, - $this->moduleTitle . '_country' => array($this->config->get('config_country_id')) - ) - ); + $this->model_setting_setting->editSetting( + $this->moduleTitle, + array( + $this->moduleTitle . '_status' => 1, + $this->moduleTitle . '_country' => array($this->config->get('config_country_id')) + ) + ); $this->addEvents(); } @@ -50,8 +52,10 @@ class ControllerExtensionModuleRetailcrm extends Controller { $this->uninstall_collector(); $this->load->model('setting/setting'); - $this->model_setting_setting - ->editSetting($this->moduleTitle, array($this->moduleTitle . '_status' => 0)); + $this->model_setting_setting->editSetting( + $this->moduleTitle, + array($this->moduleTitle . '_status' => 0) + ); $this->model_setting_setting->deleteSetting('retailcrm_history'); $this->deleteEvents(); } @@ -90,7 +94,7 @@ class ControllerExtensionModuleRetailcrm extends Controller * @return void */ public function index() - { + { $this->loadModels(); $this->load->model('localisation/country'); $this->load->model('setting/setting'); @@ -99,10 +103,9 @@ class ControllerExtensionModuleRetailcrm extends Controller $this->document->setTitle($this->language->get('heading_title')); $this->document->addStyle('/admin/view/stylesheet/retailcrm.css'); - $tokenTitle = $this->retailcrm->getTokenTitle(); $collector = $this->getCollectorTitle(); $history_setting = $this->model_setting_setting->getSetting('retailcrm_history'); - + if ($this->request->server['REQUEST_METHOD'] == 'POST' && $this->validate()) { if ($this->checkEvents() === false) { $this->deleteEvents(); @@ -110,22 +113,24 @@ class ControllerExtensionModuleRetailcrm extends Controller } $analytics = $this->{'model_' . $this->modelExtension}->getInstalled('analytics'); - - if ($this->request->post[$this->moduleTitle . '_collector_active'] == 1 && - !in_array($collector, $analytics)) { + + if ($this->request->post[$this->moduleTitle . '_collector_active'] == 1 + && !in_array($collector, $analytics) + ) { $this->install_collector(); - } elseif ($this->request->post[$this->moduleTitle . '_collector_active'] == 0 && - in_array($collector, $analytics)) { + } elseif ($this->request->post[$this->moduleTitle . '_collector_active'] == 0 + && in_array($collector, $analytics) + ) { $this->uninstall_collector(); } if (parse_url($this->request->post[$this->moduleTitle . '_url'])) { $crm_url = parse_url($this->request->post[$this->moduleTitle . '_url'], PHP_URL_HOST); - $this->request->post[$this->moduleTitle . '_url'] = 'https://'.$crm_url; + $this->request->post[$this->moduleTitle . '_url'] = 'https://' . $crm_url; } - - if (isset($this->request->post[$this->moduleTitle . '_custom_field_active']) && - $this->request->post[$this->moduleTitle . '_custom_field_active'] == 0 + + if (isset($this->request->post[$this->moduleTitle . '_custom_field_active']) + && $this->request->post[$this->moduleTitle . '_custom_field_active'] == 0 ) { unset($this->request->post[$this->moduleTitle . '_custom_field']); } @@ -181,7 +186,7 @@ class ControllerExtensionModuleRetailcrm extends Controller $this->session->data['success'] = $this->language->get('text_success'); $redirect = $this->url->link( - 'extension/module/retailcrm', $tokenTitle . '=' . $this->session->data[$tokenTitle], + 'extension/module/retailcrm', $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], 'SSL' ); @@ -311,7 +316,7 @@ class ControllerExtensionModuleRetailcrm extends Controller 'text' => $this->language->get('text_home'), 'href' => $this->url->link( 'common/home', - $tokenTitle . '=' . $this->session->data[$tokenTitle], 'SSL' + $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], 'SSL' ), 'separator' => false ); @@ -320,7 +325,7 @@ class ControllerExtensionModuleRetailcrm extends Controller 'text' => $this->language->get('text_module'), 'href' => $this->url->link( 'extension/extension/module', - $tokenTitle . '=' . $this->session->data[$tokenTitle], 'SSL' + $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], 'SSL' ), 'separator' => ' :: ' ); @@ -329,19 +334,19 @@ class ControllerExtensionModuleRetailcrm extends Controller 'text' => $this->language->get('retailcrm_title'), 'href' => $this->url->link( 'extension/module/retailcrm', - $tokenTitle . '=' . $this->session->data[$tokenTitle], 'SSL' + $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], 'SSL' ), 'separator' => ' :: ' ); $_data['action'] = $this->url->link( 'extension/module/retailcrm', - $tokenTitle . '=' . $this->session->data[$tokenTitle], 'SSL' + $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], 'SSL' ); $_data['cancel'] = $this->url->link( version_compare(VERSION, '3.0', '<') ? 'extension/extension' : 'marketplace/extension', - $tokenTitle . '=' . $this->session->data[$tokenTitle], 'SSL' + $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], 'SSL' ); $_data['modules'] = array(); @@ -360,7 +365,7 @@ class ControllerExtensionModuleRetailcrm extends Controller $_data['footer'] = $this->load->controller('common/footer'); $_data['countries'] = $this->model_localisation_country->getCountries(); $_data['catalog'] = $this->request->server['HTTPS'] ? HTTPS_CATALOG : HTTP_CATALOG; - $_data[$tokenTitle] = $this->request->get[$tokenTitle]; + $_data[$this->tokenTitle] = $this->request->get[$this->tokenTitle]; if(file_exists(DIR_SYSTEM . '/cron/export_done')) { $_data['export_file'] = false; @@ -393,8 +398,8 @@ class ControllerExtensionModuleRetailcrm extends Controller $_data['logs']['oc_error'] = $this->language->get('text_error_log'); } - $_data['clear_retailcrm'] = $this->url->link('extension/module/retailcrm/clear_retailcrm', $tokenTitle . '=' . $this->session->data[$tokenTitle], true); - $_data['clear_opencart'] = $this->url->link('extension/module/retailcrm/clear_opencart', $tokenTitle . '=' . $this->session->data[$tokenTitle], true); + $_data['clear_retailcrm'] = $this->url->link('extension/module/retailcrm/clear_retailcrm', $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], true); + $_data['clear_opencart'] = $this->url->link('extension/module/retailcrm/clear_opencart', $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], true); $_data['button_clear'] = $this->language->get('button_clear'); $this->response->setOutput( @@ -416,18 +421,18 @@ class ControllerExtensionModuleRetailcrm extends Controller if ($settings[$this->moduleTitle . '_apiversion'] == 'v3') { if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/history/v3.php')) { $this->load->model('extension/retailcrm/custom/history/v3'); - $this->model_extension_retailcrm_custom_history_v3->request(); + $this->model_extension_retailcrm_custom_history_v3->request($this->retailcrm->getApiClient()); } else { $this->load->model('extension/retailcrm/history/v3'); - $this->model_extension_retailcrm_history_v3->request(); + $this->model_extension_retailcrm_history_v3->request($this->retailcrm->getApiClient()); } } else { if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/history/v4-5.php')) { $this->load->model('extension/retailcrm/custom/history/v4-5'); - $this->model_extension_retailcrm_custom_history_v4_5->request(); + $this->model_extension_retailcrm_custom_history_v4_5->request($this->retailcrm->getApiClient()); } else { $this->load->model('extension/retailcrm/history/v4_5'); - $this->model_extension_retailcrm_history_v4_5->request(); + $this->model_extension_retailcrm_history_v4_5->request($this->retailcrm->getApiClient()); } } } @@ -448,35 +453,11 @@ class ControllerExtensionModuleRetailcrm extends Controller } } - /** - * Create order on event - * - * @param int $order_id order identificator - * - * @return void - */ - public function order_create($order_id) - { - $this->load->model('checkout/order'); - $this->load->model('account/order'); - - $data = $this->model_checkout_order->getOrder($order_id); - $data['products'] = $this->model_account_order->getOrderProducts($order_id); - - if (!isset($data['fromApi'])) { - $this->load->model('setting/setting'); - $status = $this->model_setting_setting->getSetting('retailcrm'); - $data['order_status'] = $status['retailcrm_status'][$data['order_status_id']]; - - $this->load->model('extension/retailcrm/order'); - $this->model_extension_retailcrm_order->sendToCrm($data, $data['order_id']); - } - } - /** * Update customer on event * - * @param int $customer_id customer identificator + * @param string $route + * @param int $customer customer identificator * * @return void */ @@ -508,7 +489,7 @@ class ControllerExtensionModuleRetailcrm extends Controller } $this->load->model('extension/retailcrm/customer'); - $this->model_extension_retailcrm_customer->changeInCrm($customer); + $this->model_extension_retailcrm_customer->changeInCrm($customer, $this->retailcrm->getApiClient()); } /** @@ -525,13 +506,17 @@ class ControllerExtensionModuleRetailcrm extends Controller $data['products'] = $this->model_sale_order->getOrderProducts($order_id); $data['totals'] = $this->model_sale_order->getOrderTotals($order_id); + foreach ($data['products'] as $key => $product) { + $data['products'][$key]['option'] = $this->model_sale_order->getOrderOptions($product['order_id'], $product['order_product_id']); + } + if (!isset($data['fromApi'])) { $this->load->model('setting/setting'); $status = $this->model_setting_setting->getSetting($this->moduleTitle); $data['order_status'] = $status[$this->moduleTitle . '_status'][$data['order_status_id']]; $this->load->model('extension/retailcrm/order'); - $response = $this->model_extension_retailcrm_order->uploadOrder($data); + $response = $this->model_extension_retailcrm_order->uploadOrder($data, $this->retailcrm->getApiClient()); } if (!$response->isSuccessful()) { @@ -550,7 +535,7 @@ class ControllerExtensionModuleRetailcrm extends Controller ) ); } else { - $this->response->setOutPut( + $this->response->setOutput( json_encode( array( 'status_code' => $response->getStatusCode() @@ -568,37 +553,36 @@ class ControllerExtensionModuleRetailcrm extends Controller public function export() { $this->load->model('customer/customer'); - $customers = $this->model_customer_customer->getCustomers(); - $this->load->model('extension/retailcrm/customer'); - $this->model_extension_retailcrm_customer->uploadToCrm($customers); - + $this->load->model('extension/retailcrm/order'); $this->load->model('sale/order'); + + $customers = $this->model_customer_customer->getCustomers(); + $this->model_extension_retailcrm_customer->uploadToCrm($customers, $this->retailcrm->getApiClient()); $orders = $this->model_sale_order->getOrders(); $fullOrders = array(); - foreach($orders as $order) { + foreach ($orders as $order) { $fullOrder = $this->model_sale_order->getOrder($order['order_id']); - $fullOrder['order_total'] = $this->model_sale_order->getOrderTotals($order['order_id']); + $fullOrder['totals'] = $this->model_sale_order->getOrderTotals($order['order_id']); $fullOrder['products'] = $this->model_sale_order->getOrderProducts($order['order_id']); - foreach($fullOrder['products'] as $key=>$product) { + foreach($fullOrder['products'] as $key => $product) { $fullOrder['products'][$key]['option'] = $this->model_sale_order->getOrderOptions($product['order_id'], $product['order_product_id']); } $fullOrders[] = $fullOrder; } - $this->load->model('extension/retailcrm/order'); - $this->model_extension_retailcrm_order->uploadToCrm($fullOrders); + $this->model_extension_retailcrm_order->uploadToCrm($fullOrders, $this->retailcrm->getApiClient()); fopen(DIR_SYSTEM . '/cron/export_done', "x"); } /** * Promotional price upload - * + * * @return void */ public function prices() @@ -608,10 +592,10 @@ class ControllerExtensionModuleRetailcrm extends Controller if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/prices.php')) { $this->load->model('extension/retailcrm/custom/prices'); - $this->model_extension_retailcrm_custom_prices->uploadPrices($products); + $this->model_extension_retailcrm_custom_prices->uploadPrices($products, $this->retailcrm->getApiClient()); } else { $this->load->model('extension/retailcrm/prices'); - $this->model_extension_retailcrm_prices->uploadPrices($products); + $this->model_extension_retailcrm_prices->uploadPrices($products, $this->retailcrm->getApiClient()); } } @@ -672,8 +656,6 @@ class ControllerExtensionModuleRetailcrm extends Controller */ public function clear_retailcrm() { - $tokenTitle = $this->getTokenTitle(); - if ($this->user->hasPermission('modify', 'extension/module/retailcrm')) { $file = DIR_LOGS . 'retailcrm.log'; @@ -682,7 +664,7 @@ class ControllerExtensionModuleRetailcrm extends Controller fclose($handle); } - $this->response->redirect($this->url->link('extension/module/retailcrm', $tokenTitle . '=' . $this->session->data[$tokenTitle], true)); + $this->response->redirect($this->url->link('extension/module/retailcrm', $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], true)); } /** @@ -691,9 +673,7 @@ class ControllerExtensionModuleRetailcrm extends Controller * @return void */ public function clear_opencart() - { - $tokenTitle = $this->getTokenTitle(); - + { if ($this->user->hasPermission('modify', 'extension/module/retailcrm')) { $file = DIR_LOGS . 'opencartapi.log'; @@ -702,11 +682,11 @@ class ControllerExtensionModuleRetailcrm extends Controller fclose($handle); } - $this->response->redirect($this->url->link('extension/module/retailcrm', $tokenTitle . '=' . $this->session->data[$tokenTitle], true)); + $this->response->redirect($this->url->link('extension/module/retailcrm', $this->tokenTitle . '=' . $this->session->data[$this->tokenTitle], true)); } /** - * Method for load modelds + * Method for load models * * @return void */ @@ -829,7 +809,7 @@ class ControllerExtensionModuleRetailcrm extends Controller private function checkEvents() { $events = $this->{'model_' . $this->modelEvent}->getEvent( - 'retailcrm', + $this->moduleTitle, 'catalog/model/checkout/order/addOrder/after', 'extension/module/retailcrm/order_create' ); diff --git a/admin/language/en-gb/extension/module/retailcrm.php b/src/upload/admin/language/en-gb/extension/module/retailcrm.php similarity index 97% rename from admin/language/en-gb/extension/module/retailcrm.php rename to src/upload/admin/language/en-gb/extension/module/retailcrm.php index 0fe71fc..3e2f71c 100644 --- a/admin/language/en-gb/extension/module/retailcrm.php +++ b/src/upload/admin/language/en-gb/extension/module/retailcrm.php @@ -1,8 +1,8 @@ moduleTitle = $this->retailcrm->getModuleTitle(); $this->settings = $this->model_setting_setting->getSetting($this->moduleTitle); - $this->retailcrmApiClient = $this->retailcrm->getApiClient(); } /** * Upload customers * * @param array $customers - * - * @return void + * @param \RetailcrmProxy $retailcrmApiClient + * + * @return mixed */ - public function uploadToCrm($customers) + public function uploadToCrm($customers, $retailcrmApiClient) { - if ($this->retailcrmApiClient === false || empty($customers)) { - return; + if ($retailcrmApiClient === false || empty($customers)) { + return false; } $customersToCrm = array(); @@ -38,26 +38,31 @@ class ModelExtensionRetailcrmCustomer extends Model { $chunkedCustomers = array_chunk($customersToCrm, 50); foreach($chunkedCustomers as $customersPart) { - $this->retailcrmApiClient->customersUpload($customersPart); + $retailcrmApiClient->customersUpload($customersPart); } + + return $chunkedCustomers; } /** * Edit customer * * @param array $customer - * - * @return void + * @param \RetailcrmProxy $retailcrmApiClient + * + * @return mixed */ - public function changeInCrm($customer) + public function changeInCrm($customer, $retailcrmApiClient) { - if ($this->retailcrmApiClient === false || empty($customer)) { - return; + if ($retailcrmApiClient === false || empty($customer)) { + return false; } $customerToCrm = $this->process($customer); - - $this->retailcrmApiClient->customersEdit($customerToCrm); + + $retailcrmApiClient->customersEdit($customerToCrm); + + return $customerToCrm; } /** @@ -69,7 +74,6 @@ class ModelExtensionRetailcrmCustomer extends Model { */ private function process($customer) { - $customerToCrm = array( 'externalId' => $customer['customer_id'], 'firstName' => $customer['firstname'], @@ -92,7 +96,7 @@ class ModelExtensionRetailcrmCustomer extends Model { 'text' => $customer['address']['address_1'] . ' ' . $customer['address']['address_2'] ); } - + if (isset($this->settings[$this->moduleTitle . '_custom_field']) && $customer['custom_field']) { $customFields = json_decode($customer['custom_field']); diff --git a/admin/model/extension/retailcrm/history.php b/src/upload/admin/model/extension/retailcrm/history.php similarity index 99% rename from admin/model/extension/retailcrm/history.php rename to src/upload/admin/model/extension/retailcrm/history.php index f73e1b7..7a46524 100644 --- a/admin/model/extension/retailcrm/history.php +++ b/src/upload/admin/model/extension/retailcrm/history.php @@ -66,7 +66,7 @@ class ModelExtensionRetailcrmHistory extends Model public function addOrderProducts($order_id, $products) { foreach ($products as $product) { - $this->db->query("INSERT INTO " . DB_PREFIX . "order_product SET order_id = '" . (int)$order_id . "', product_id = '" . (int)$product['product_id'] . "', name = '" . $this->db->escape($product['name']) . "', model = '" . $this->db->escape($product['model']) . "', quantity = '" . (int)$product['quantity'] . "', price = '" . (float)$product['price'] . "', total = '" . (float)$product['total'] . "'"); + $this->db->query("INSERT INTO " . DB_PREFIX . "order_product SET order_id = '" . (int)$order_id . "', product_id = '" . (int)$product['product_id'] . "', name = '" . $this->db->escape($product['name']) . "', model = '" . $this->db->escape($product['model']) . "', quantity = '" . (int)$product['quantity'] . "', price = '" . (float)$product['price'] . "', total = '" . (float)$product['total'] . "', reward = '" . (float)$product['reward'] . "'"); $order_product_id = $this->db->getLastId(); diff --git a/admin/model/extension/retailcrm/history/v3.php b/src/upload/admin/model/extension/retailcrm/history/v3.php similarity index 85% rename from admin/model/extension/retailcrm/history/v3.php rename to src/upload/admin/model/extension/retailcrm/history/v3.php index debeec6..25fadb0 100644 --- a/admin/model/extension/retailcrm/history/v3.php +++ b/src/upload/admin/model/extension/retailcrm/history/v3.php @@ -6,14 +6,14 @@ class ModelExtensionRetailcrmHistoryV3 extends ModelExtensionRetailcrmHistoryV45 { protected $createResult; - private $opencartApiClient; - /** * Getting changes from RetailCRM - * + * + * @param \RetailcrmProxy $retailcrmApiClient + * * @return boolean */ - public function request() + public function request($retailcrmApiClient) { $moduleTitle = $this->retailcrm->getModuleTitle(); $this->load->model('setting/setting'); @@ -40,18 +40,11 @@ class ModelExtensionRetailcrmHistoryV3 extends ModelExtensionRetailcrmHistoryV45 return false; } - $crm = new RetailcrmProxy( - $settings[$moduleTitle . '_url'], - $settings[$moduleTitle . '_apikey'], - DIR_SYSTEM . 'storage/logs/retailcrm.log', - $settings[$moduleTitle . '_apiversion'] - ); - $lastRun = !empty($history['retailcrm_history_datetime']) ? new DateTime($history['retailcrm_history_datetime']) : new DateTime(date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))); - $packsOrders = $crm->ordersHistory($lastRun); + $packsOrders = $retailcrmApiClient->ordersHistory($lastRun); if(!$packsOrders->isSuccessful() && count($packsOrders['orders']) <= 0) { return false; @@ -96,14 +89,14 @@ class ModelExtensionRetailcrmHistoryV3 extends ModelExtensionRetailcrmHistoryV45 unset($orders); if (!empty($newOrders)) { - $orders = $crm->ordersList($filter = array('ids' => $newOrders)); + $orders = $retailcrmApiClient->ordersList($filter = array('ids' => $newOrders)); if ($orders) { $this->createResult = $this->createOrders($orders['orders']); } } if (!empty($updatedOrders)) { - $orders = $crm->ordersList($filter = array('ids' => $updatedOrders)); + $orders = $retailcrmApiClient->ordersList($filter = array('ids' => $updatedOrders)); if ($orders) { $this->updateOrders($orders['orders']); } @@ -112,11 +105,13 @@ class ModelExtensionRetailcrmHistoryV3 extends ModelExtensionRetailcrmHistoryV45 $this->model_setting_setting->editSetting('retailcrm_history', array('retailcrm_history_datetime' => $generatedAt)); if (!empty($this->createResult['customers'])) { - $crm->customersFixExternalIds($this->createResult['customers']); + $retailcrmApiClient->customersFixExternalIds($this->createResult['customers']); } if (!empty($this->createResult['orders'])) { - $crm->ordersFixExternalIds($this->createResult['orders']); + $retailcrmApiClient->ordersFixExternalIds($this->createResult['orders']); } + + return true; } } diff --git a/admin/model/extension/retailcrm/history/v4_5.php b/src/upload/admin/model/extension/retailcrm/history/v4_5.php similarity index 96% rename from admin/model/extension/retailcrm/history/v4_5.php rename to src/upload/admin/model/extension/retailcrm/history/v4_5.php index b424e81..8d82b3f 100644 --- a/admin/model/extension/retailcrm/history/v4_5.php +++ b/src/upload/admin/model/extension/retailcrm/history/v4_5.php @@ -7,8 +7,8 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory protected $createResult; protected $settings; protected $moduleTitle; + protected $opencartApiClient; - private $opencartApiClient; private $customFieldSetting; public function __construct($registry) @@ -21,13 +21,13 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory /** * Getting changes from RetailCRM - * + * @param \RetailcrmProxy $retailcrmApiClient + * * @return boolean */ - public function request() + public function request($retailcrmApiClient) { $this->load->library('retailcrm/retailcrm'); - $this->moduleTitle = $this->retailcrm->getModuleTitle(); $this->load->model('setting/setting'); $this->load->model('setting/store'); $this->load->model('user/api'); @@ -52,22 +52,13 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory return false; } - $this->opencartApiClient = new OpencartApiClient($this->registry); - - $crm = new RetailcrmProxy( - $settings[$this->moduleTitle . '_url'], - $settings[$this->moduleTitle . '_apikey'], - DIR_SYSTEM . 'storage/logs/retailcrm.log', - $settings[$this->moduleTitle . '_apiversion'] - ); - $sinceIdOrders = $history['retailcrm_history_orders'] ? $history['retailcrm_history_orders'] : null; $sinceIdCustomers = $history['retailcrm_history_customers'] ? $history['retailcrm_history_customers'] : null; - $packsOrders = $crm->ordersHistory(array( + $packsOrders = $retailcrmApiClient->ordersHistory(array( 'sinceId' => $sinceIdOrders ? $sinceIdOrders : 0 ), 1, 100); - $packsCustomers = $crm->customersHistory(array( + $packsCustomers = $retailcrmApiClient->customersHistory(array( 'sinceId' => $sinceIdCustomers ? $sinceIdCustomers : 0 ), 1, 100); @@ -150,21 +141,21 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory unset($customers); if (!empty($updateCustomers)) { - $customers = $crm->customersList($filter = array('ids' => $updateCustomers)); + $customers = $retailcrmApiClient->customersList($filter = array('ids' => $updateCustomers)); if ($customers) { $this->updateCustomers($customers['customers']); } } if (!empty($newOrders)) { - $orders = $crm->ordersList($filter = array('ids' => $newOrders)); + $orders = $retailcrmApiClient->ordersList($filter = array('ids' => $newOrders)); if ($orders) { $this->createResult = $this->createOrders($orders['orders']); } } if (!empty($updatedOrders)) { - $orders = $crm->ordersList($filter = array('ids' => $updatedOrders)); + $orders = $retailcrmApiClient->ordersList($filter = array('ids' => $updatedOrders)); if ($orders) { $this->updateOrders($orders['orders']); } @@ -180,12 +171,14 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory ); if (!empty($this->createResult['customers'])) { - $crm->customersFixExternalIds($this->createResult['customers']); + $retailcrmApiClient->customersFixExternalIds($this->createResult['customers']); } if (!empty($this->createResult['orders'])) { - $crm->ordersFixExternalIds($this->createResult['orders']); + $retailcrmApiClient->ordersFixExternalIds($this->createResult['orders']); } + + return true; } /** @@ -394,6 +387,7 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory } $product = $this->model_catalog_product->getProduct($productId); + $rewards = $this->model_catalog_product->getProductRewards($productId); $data['order_product'][] = array( 'name' => $product['name'], @@ -402,7 +396,8 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory 'total' => (float)($item['initialPrice'] * $item['quantity']), 'product_id' => $productId, 'quantity' => $item['quantity'], - 'option' => $options + 'option' => $options, + 'reward' => $rewards[$data['customer_group_id']]['points'] * $item['quantity'] ); } @@ -711,6 +706,7 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory } $product = $this->model_catalog_product->getProduct($productId); + $rewards = $this->model_catalog_product->getProductRewards($productId); $data['order_product'][] = array( 'name' => $product['name'], @@ -719,7 +715,8 @@ class ModelExtensionRetailcrmHistoryV45 extends ModelExtensionRetailcrmHistory 'total' => (float)($item['initialPrice'] * $item['quantity']), 'product_id' => $productId, 'quantity' => $item['quantity'], - 'option' => $options + 'option' => $options, + 'reward' => $rewards[$data['customer_group_id']]['points'] * $item['quantity'] ); } diff --git a/admin/model/extension/retailcrm/icml.php b/src/upload/admin/model/extension/retailcrm/icml.php similarity index 100% rename from admin/model/extension/retailcrm/icml.php rename to src/upload/admin/model/extension/retailcrm/icml.php diff --git a/admin/model/extension/retailcrm/order.php b/src/upload/admin/model/extension/retailcrm/order.php similarity index 78% rename from admin/model/extension/retailcrm/order.php rename to src/upload/admin/model/extension/retailcrm/order.php index 98f23d0..178b9f1 100644 --- a/admin/model/extension/retailcrm/order.php +++ b/src/upload/admin/model/extension/retailcrm/order.php @@ -13,53 +13,56 @@ class ModelExtensionRetailcrmOrder extends Model { $this->moduleTitle = $this->retailcrm->getModuleTitle(); $this->settings = $this->model_setting_setting->getSetting($this->moduleTitle); - $this->retailcrmApiClient = $this->retailcrm->getApiClient(); } /** * Upload orders to CRM - * + * * @param array $orders - * - * @return void + * @param \RetailcrmProxy $retailcrmApiClient + * + * @return mixed */ - public function uploadToCrm($orders) + public function uploadToCrm($orders, $retailcrmApiClient) { - if ($this->retailcrmApiClient === false) { - return; + if ($retailcrmApiClient === false) { + return false; } $ordersToCrm = array(); - foreach($orders as $order) { + foreach ($orders as $order) { $ordersToCrm[] = $this->process($order); } $chunkedOrders = array_chunk($ordersToCrm, 50); foreach($chunkedOrders as $ordersPart) { - $this->retailcrmApiClient->ordersUpload($ordersPart); + $retailcrmApiClient->ordersUpload($ordersPart); } + + return $chunkedOrders; } /** * Send one order by id * * @param array $order_data - * - * @return object $result + * @param \RetailcrmProxy $retailcrmApiClient + * + * @return mixed */ - public function uploadOrder($order_data) + public function uploadOrder($order_data, $retailcrmApiClient) { - if ($this->retailcrmApiClient === false) { - return; + if ($retailcrmApiClient === false) { + return false; } - if(isset($this->request->post['fromApi'])) { - return; + if (isset($this->request->post['fromApi'])) { + return false; } - $customers = $this->retailcrmApiClient->customersList( + $customers = $retailcrmApiClient->customersList( array( 'name' => $order_data['telephone'], 'email' => $order_data['email'] @@ -78,13 +81,9 @@ class ModelExtensionRetailcrmOrder extends Model { unset($customers); - $result = $this->retailcrmApiClient->ordersCreate($order); + $retailcrmApiClient->ordersCreate($order); - if ($this->settings[$this->moduleTitle . '_apiversion'] == 'v5' && $result->isSuccessful()) { - $this->createPayment($order_data, $order_data['order_id']); - } - - return $result; + return $order; } /** @@ -98,7 +97,6 @@ class ModelExtensionRetailcrmOrder extends Model { $order = array(); $this->load->model('catalog/product'); - $payment_code = $order_data['payment_code']; if (!empty($order_data['payment_code']) && isset($this->settings[$this->moduleTitle . '_payment'][$order_data['payment_code']])) { $payment_code = $this->settings[$this->moduleTitle . '_payment'][$order_data['payment_code']]; @@ -124,7 +122,7 @@ class ModelExtensionRetailcrmOrder extends Model { $order['phone'] = $order_data['telephone']; $order['customerComment'] = $order_data['comment']; - if(!empty($order_data['email'])) { + if (!empty($order_data['email'])) { $order['email'] = $order_data['email']; } @@ -148,16 +146,14 @@ class ModelExtensionRetailcrmOrder extends Model { } $country = (isset($order_data['shipping_country'])) ? $order_data['shipping_country'] : '' ; - $order['delivery'] = array( - 'code' => $delivery_code, + 'code' => isset($delivery_code) ? $delivery_code : '', 'cost' => $deliveryCost, 'address' => array( 'index' => $order_data['shipping_postcode'], 'city' => $order_data['shipping_city'], - 'country' => $order_data['shipping_country_id'], - 'region' => $order_data['shipping_zone_id'], + 'region' => $order_data['shipping_zone'], 'text' => implode(', ', array( $order_data['shipping_postcode'], $country, @@ -174,7 +170,7 @@ class ModelExtensionRetailcrmOrder extends Model { foreach ($orderProducts as $product) { $offerId = ''; - if(!empty($product['option'])) { + if (!empty($product['option'])) { $options = array(); $productOptions = $this->model_catalog_product->getProductOptions($product['product_id']); @@ -188,7 +184,7 @@ class ModelExtensionRetailcrmOrder extends Model { ); } - if(!in_array($option['type'], $offerOptions)) continue; + if (!in_array($option['type'], $offerOptions)) continue; foreach($productOptions as $productOption) { if($productOption['product_option_id'] = $option['product_option_id']) { foreach($productOption['product_option_value'] as $productOptionValue) { @@ -250,7 +246,7 @@ class ModelExtensionRetailcrmOrder extends Model { $customFields = json_decode($order_data['custom_field']); foreach ($customFields as $key => $value) { - if (isset($this->settings[$moduleTitle . '_custom_field']['o_' . $key])) { + if (isset($this->settings[$this->moduleTitle . '_custom_field']['o_' . $key])) { $customFieldsToCrm[$this->settings[$this->moduleTitle . '_custom_field']['o_' . $key]] = $value; } } @@ -262,35 +258,4 @@ class ModelExtensionRetailcrmOrder extends Model { return $order; } - - /** - * Create payment - * - * @param array $order - * @param int $order_id - * - * @return void - */ - protected function createPayment($order, $order_id) - { - $payment_code = $order['payment_code']; - - foreach ($order['totals'] as $total) { - if ($total['code'] == 'total') { - $amount = $total['value']; - } - } - - $payment = array( - 'externalId' => $order_id, - 'type' => $this->settings[$this->moduleTitle . '_payment'][$payment_code], - 'amount' => $amount - ); - - $payment['order'] = array( - 'externalId' => $order_id - ); - - $this->retailcrmApiClient->ordersPaymentCreate($payment); - } } diff --git a/admin/model/extension/retailcrm/prices.php b/src/upload/admin/model/extension/retailcrm/prices.php similarity index 87% rename from admin/model/extension/retailcrm/prices.php rename to src/upload/admin/model/extension/retailcrm/prices.php index f190861..5c6c303 100644 --- a/admin/model/extension/retailcrm/prices.php +++ b/src/upload/admin/model/extension/retailcrm/prices.php @@ -2,7 +2,6 @@ class ModelExtensionRetailcrmPrices extends Model { - protected $retailcrmApiClient; protected $settings; protected $moduleTitle; private $options; @@ -22,25 +21,30 @@ class ModelExtensionRetailcrmPrices extends Model $this->moduleTitle = $this->retailcrm->getModuleTitle(); $this->settings = $this->model_setting_setting->getSetting($this->moduleTitle); - $this->retailcrmApiClient = $this->retailcrm->getApiClient(); } /** * Upload prices to CRM * * @param array $products - * - * @return void + * @param \RetailcrmProxy $retailcrmApiClient + * @return mixed bool | array */ - public function uploadPrices($products) + public function uploadPrices($products, $retailcrmApiClient) { - $prices = $this->getPrices($products); + $prices = $this->getPrices($products, $retailcrmApiClient); + + if ($retailcrmApiClient === false || !$prices) { + return false; + } $pricesUpload = array_chunk($prices, 250); foreach ($pricesUpload as $priceUpload) { - $this->retailcrmApiClient->storePricesUpload($priceUpload); + $retailcrmApiClient->storePricesUpload($priceUpload); } + + return $pricesUpload; } /** @@ -48,17 +52,17 @@ class ModelExtensionRetailcrmPrices extends Model * * @param array $products * - * @return array $prices + * @return mixed */ - protected function getPrices($products) + protected function getPrices($products, $retailcrmApiClient) { $prices = array(); - $site = $this->getSite(); + $site = $this->getSite($retailcrmApiClient); if (!isset($this->settings[$this->moduleTitle . '_special']) || $this->settings[$this->moduleTitle . '_apiversion'] == 'v3' ) { - return; + return false; } foreach ($products as $product) { @@ -182,12 +186,14 @@ class ModelExtensionRetailcrmPrices extends Model /** * Get site - * + * + * @param \RetailcrmProxy $retailcrmApiClient + * * @return mixed boolean | string */ - private function getSite() + private function getSite($retailcrmApiClient) { - $response = $this->retailcrmApiClient->sitesList(); + $response = $retailcrmApiClient->sitesList(); if ($response && $response->isSuccessful()) { $sites = $response->sites; diff --git a/admin/model/extension/retailcrm/references.php b/src/upload/admin/model/extension/retailcrm/references.php similarity index 100% rename from admin/model/extension/retailcrm/references.php rename to src/upload/admin/model/extension/retailcrm/references.php diff --git a/admin/view/stylesheet/retailcrm.css b/src/upload/admin/view/stylesheet/retailcrm.css similarity index 100% rename from admin/view/stylesheet/retailcrm.css rename to src/upload/admin/view/stylesheet/retailcrm.css diff --git a/admin/view/template/extension/module/retailcrm.tpl b/src/upload/admin/view/template/extension/module/retailcrm.tpl similarity index 100% rename from admin/view/template/extension/module/retailcrm.tpl rename to src/upload/admin/view/template/extension/module/retailcrm.tpl diff --git a/admin/view/template/extension/module/retailcrm.twig b/src/upload/admin/view/template/extension/module/retailcrm.twig similarity index 100% rename from admin/view/template/extension/module/retailcrm.twig rename to src/upload/admin/view/template/extension/module/retailcrm.twig diff --git a/catalog/controller/api/retailcrm.php b/src/upload/catalog/controller/api/retailcrm.php similarity index 94% rename from catalog/controller/api/retailcrm.php rename to src/upload/catalog/controller/api/retailcrm.php index e8164fa..baa97d7 100644 --- a/catalog/controller/api/retailcrm.php +++ b/src/upload/catalog/controller/api/retailcrm.php @@ -13,11 +13,13 @@ class ControllerApiRetailcrm extends Controller $this->load->model('setting/setting'); $this->load->library('retailcrm/retailcrm'); $moduleTitle = $this->retailcrm->getModuleTitle(); - $countries = $this->model_setting_setting->getSetting($moduleTitle)[$moduleTitle . '_country']; + $setting = $this->model_setting_setting->getSetting($moduleTitle); $response = array(); - foreach ($countries as $country) { - $response = array_merge($response, $this->getDeliveryTypesByZones($country)); + if (isset($setting[$moduleTitle . '_country']) && $setting[$moduleTitle . '_country']) { + foreach ($setting[$moduleTitle . '_country'] as $country) { + $response = array_merge($response, $this->getDeliveryTypesByZones($country)); + } } } diff --git a/catalog/controller/extension/analytics/daemon_collector.php b/src/upload/catalog/controller/extension/analytics/daemon_collector.php similarity index 100% rename from catalog/controller/extension/analytics/daemon_collector.php rename to src/upload/catalog/controller/extension/analytics/daemon_collector.php diff --git a/catalog/controller/extension/module/retailcrm.php b/src/upload/catalog/controller/extension/module/retailcrm.php similarity index 74% rename from catalog/controller/extension/module/retailcrm.php rename to src/upload/catalog/controller/extension/module/retailcrm.php index b726187..21a1daf 100644 --- a/catalog/controller/extension/module/retailcrm.php +++ b/src/upload/catalog/controller/extension/module/retailcrm.php @@ -7,49 +7,57 @@ * @package RetailCrm * @author RetailCrm * @license https://opensource.org/licenses/MIT MIT License - * @link http://www.retailcrm.ru/docs/Developers/ApiVersion3 + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion5 */ -class ControllerExtensionModuleRetailcrm extends Controller -{ +class ControllerExtensionModuleRetailcrm extends Controller { + + private $retailcrmApiClient; + + public function __construct() + { + $this->load->library('retailcrm/retailcrm'); + $this->retailcrmApiClient = $this->retailcrm->getApiClient(); + } + /** * Create order on event * + * @param string $trigger + * @param array $data * @param int $order_id order identificator * * @return void */ - public function order_create($parameter1, $parameter2 = null, $parameter3 = null) - { - $this->load->model('checkout/order'); + public function order_create($trigger, $data, $order_id = null) { $this->load->model('account/order'); $this->load->library('retailcrm/retailcrm'); $moduleTitle = $this->retailcrm->getModuleTitle(); - $order_id = $parameter3; - $data = $this->model_checkout_order->getOrder($order_id); - $data['totals'] = $this->model_account_order->getOrderTotals($order_id); - $data['products'] = $this->model_account_order->getOrderProducts($order_id); - foreach($data['products'] as $key => $product) { + foreach ($data['products'] as $key => $product) { $productOptions = $this->model_account_order->getOrderOptions($order_id, $product['order_product_id']); - if(!empty($productOptions)) + if (!empty($productOptions)) { $data['products'][$key]['option'] = $productOptions; + } } if (!isset($data['fromApi'])) { $this->load->model('setting/setting'); $status = $this->model_setting_setting->getSetting($moduleTitle); - if ($data['order_status_id'] > 0) { + + if (isset($data['order_status_id']) && $data['order_status_id'] > 0) { $data['order_status'] = $status[$moduleTitle . '_status'][$data['order_status_id']]; } if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/order.php')) { $this->load->model('extension/retailcrm/custom/order'); - $this->model_extension_retailcrm_custom_order->sendToCrm($data, $data['order_id']); + $order = $this->model_extension_retailcrm_custom_order->processOrder($data); + $this->model_extension_retailcrm_custom_order->sendToCrm($order, $this->retailcrmApiClient); } else { $this->load->model('extension/retailcrm/order'); - $this->model_extension_retailcrm_order->sendToCrm($data, $data['order_id']); + $order = $this->model_extension_retailcrm_order->processOrder($data); + $this->model_extension_retailcrm_order->sendToCrm($order, $this->retailcrmApiClient); } } } @@ -57,11 +65,12 @@ class ControllerExtensionModuleRetailcrm extends Controller /** * Update order on event * - * @param int $order_id order identificator + * @param string $trigger + * @param array $parameter2 * * @return void */ - public function order_edit($parameter1, $parameter2 = null) { + public function order_edit($trigger, $parameter2 = null) { $order_id = $parameter2[0]; $this->load->model('checkout/order'); @@ -71,16 +80,19 @@ class ControllerExtensionModuleRetailcrm extends Controller $moduleTitle = $this->retailcrm->getModuleTitle(); $data = $this->model_checkout_order->getOrder($order_id); - if($data['order_status_id'] == 0) return; + if ($data['order_status_id'] == 0) { + return; + } $data['products'] = $this->model_account_order->getOrderProducts($order_id); $data['totals'] = $this->model_account_order->getOrderTotals($order_id); - foreach($data['products'] as $key => $product) { + foreach ($data['products'] as $key => $product) { $productOptions = $this->model_account_order->getOrderOptions($order_id, $product['order_product_id']); - if(!empty($productOptions)) + if (!empty($productOptions)) { $data['products'][$key]['option'] = $productOptions; + } } if (!isset($data['fromApi'])) { @@ -93,10 +105,12 @@ class ControllerExtensionModuleRetailcrm extends Controller if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/order.php')) { $this->load->model('extension/retailcrm/custom/order'); - $this->model_extension_retailcrm_custom_order->changeInCrm($data, $data['order_id']); + $order = $this->model_extension_retailcrm_custom_order->processOrder($data, false); + $this->model_extension_retailcrm_custom_order->sendToCrm($order, $this->retailcrmApiClient, false); } else { $this->load->model('extension/retailcrm/order'); - $this->model_extension_retailcrm_order->changeInCrm($data, $data['order_id']); + $order = $this->model_extension_retailcrm_order->processOrder($data, false); + $this->model_extension_retailcrm_order->sendToCrm($order, $this->retailcrmApiClient, false); } } } @@ -132,10 +146,10 @@ class ControllerExtensionModuleRetailcrm extends Controller if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/customer.php')) { $this->load->model('extension/retailcrm/custom/customer'); - $this->model_extension_retailcrm_custom_customer->sendToCrm($customer); + $this->model_extension_retailcrm_custom_customer->sendToCrm($customer, $this->retailcrmApiClient); } else { $this->load->model('extension/retailcrm/customer'); - $this->model_extension_retailcrm_customer->sendToCrm($customer); + $this->model_extension_retailcrm_customer->sendToCrm($customer, $this->retailcrmApiClient); } } @@ -157,10 +171,10 @@ class ControllerExtensionModuleRetailcrm extends Controller if (file_exists(DIR_APPLICATION . 'model/extension/retailcrm/custom/customer.php')) { $this->load->model('extension/retailcrm/custom/customer'); - $this->model_extension_retailcrm_custom_customer->changeInCrm($customer); + $this->model_extension_retailcrm_custom_customer->changeInCrm($customer, $this->retailcrmApiClient); } else { $this->load->model('extension/retailcrm/customer'); - $this->model_extension_retailcrm_customer->changeInCrm($customer); + $this->model_extension_retailcrm_customer->changeInCrm($customer, $this->retailcrmApiClient); } } } diff --git a/catalog/model/extension/retailcrm/api.php b/src/upload/catalog/model/extension/retailcrm/api.php similarity index 100% rename from catalog/model/extension/retailcrm/api.php rename to src/upload/catalog/model/extension/retailcrm/api.php diff --git a/catalog/model/extension/retailcrm/custom/.gitkeep b/src/upload/catalog/model/extension/retailcrm/custom/.gitkeep similarity index 100% rename from catalog/model/extension/retailcrm/custom/.gitkeep rename to src/upload/catalog/model/extension/retailcrm/custom/.gitkeep diff --git a/catalog/model/extension/retailcrm/customer.php b/src/upload/catalog/model/extension/retailcrm/customer.php similarity index 83% rename from catalog/model/extension/retailcrm/customer.php rename to src/upload/catalog/model/extension/retailcrm/customer.php index 82a5002..fd586e0 100644 --- a/catalog/model/extension/retailcrm/customer.php +++ b/src/upload/catalog/model/extension/retailcrm/customer.php @@ -3,7 +3,6 @@ class ModelExtensionRetailcrmCustomer extends Model { protected $settings; protected $moduleTitle; - protected $retailcrmApiClient; public function __construct($registry) { @@ -13,7 +12,6 @@ class ModelExtensionRetailcrmCustomer extends Model { $this->moduleTitle = $this->retailcrm->getModuleTitle(); $this->settings = $this->model_setting_setting->getSetting($this->moduleTitle); - $this->retailcrmApiClient = $this->retailcrm->getApiClient(); } /** @@ -21,17 +19,19 @@ class ModelExtensionRetailcrmCustomer extends Model { * * @param array $customer * - * @return void + * @return mixed */ - public function sendToCrm($customer) + public function sendToCrm($customer, $retailcrmApiClient) { - if(empty($customer) || $this->retailcrmApiClient === false) { + if (empty($customer) || $retailcrmApiClient === false) { return false; } $customerToCrm = $this->process($customer); - $this->retailcrmApiClient->customersCreate($customerToCrm); + $retailcrmApiClient->customersCreate($customerToCrm); + + return $customerToCrm; } /** @@ -39,24 +39,26 @@ class ModelExtensionRetailcrmCustomer extends Model { * * @param array $customer * - * @return void + * @return mixed */ - public function changeInCrm($customer) + public function changeInCrm($customer, $retailcrmApiClient) { - if(empty($customer) || $this->retailcrmApiClient === false) { + if (empty($customer) || $retailcrmApiClient === false) { return false; } $customerToCrm = $this->process($customer); - $this->retailcrmApiClient->customersEdit($customerToCrm); + $retailcrmApiClient->customersEdit($customerToCrm); + + return $customerToCrm; } /** * Process customer - * + * * @param array $customer - * + * * @return array $customerToCrm */ private function process($customer) { diff --git a/catalog/model/extension/retailcrm/order.php b/src/upload/catalog/model/extension/retailcrm/order.php similarity index 59% rename from catalog/model/extension/retailcrm/order.php rename to src/upload/catalog/model/extension/retailcrm/order.php index d370cbe..73fff67 100644 --- a/catalog/model/extension/retailcrm/order.php +++ b/src/upload/catalog/model/extension/retailcrm/order.php @@ -3,131 +3,66 @@ class ModelExtensionRetailcrmOrder extends Model { protected $settings; protected $moduleTitle; - protected $retailcrmApiClient; - public function __construct($registry) - { + public function __construct($registry) { parent::__construct($registry); $this->load->model('setting/setting'); $this->load->library('retailcrm/retailcrm'); $this->moduleTitle = $this->retailcrm->getModuleTitle(); $this->settings = $this->model_setting_setting->getSetting($this->moduleTitle); - $this->retailcrmApiClient = $this->retailcrm->getApiClient(); } /** * Create order in CRM - * - * @param array $order_data - * @param int $order_id - * - * @return void + * + * @param array $order + * @param \RetailcrmProxy $retailcrmApiClient + * @param bool $create (default = true) + * + * @return mixed */ - public function sendToCrm($order_data, $order_id) - { - if(isset($this->request->post['fromApi']) || $this->retailcrmApiClient === false) { - return; + public function sendToCrm($order, $retailcrmApiClient, $create = true) { + if (isset($this->request->post['fromApi']) || $retailcrmApiClient === false) { + return false; } - $order = $this->processOrder($order_data, $order_id); + if (!isset($order['customer']['externalId'])) { + $customer = $this->searchCustomer($order['phone'], $order['email'], $retailcrmApiClient); - $customers = $this->retailcrmApiClient->customersList( - array( - 'name' => $order_data['telephone'], - 'email' => $order_data['email'] - ), - 1, - 100 - ); - - if($customers) { - foreach ($customers['customers'] as $customer) { + if ($customer) { $order['customer']['id'] = $customer['id']; } } - unset($customers); + if ($create) { + $retailcrmApiClient->ordersCreate($order); + } else { + $order_payment = reset($order['payments']); + unset($order['payments']); + $response = $retailcrmApiClient->ordersEdit($order); - $response = $this->retailcrmApiClient->ordersCreate($order); - - if ($this->settings[$this->moduleTitle . '_apiversion'] == 'v5' && $response->isSuccessful()) { - $this->createPayment($order_data, $order_id); - } - } - - /** - * Edit order in CRM - * - * @param array $order_data - * @param int $order_id - * - * @return void - */ - public function changeInCrm($order_data, $order_id) - { - if(isset($this->request->post['fromApi']) || $this->retailcrmApiClient === false) { - return; - } - - $order = $this->processOrder($order_data, $order_id); - - $customers = $this->retailcrmApiClient->customersList( - array( - 'name' => $order_data['telephone'], - 'email' => $order_data['email'] - ), - 1, - 100 - ); - - if($customers) { - foreach ($customers['customers'] as $customer) { - $order['customer']['id'] = $customer['id']; + if ($this->settings[$this->moduleTitle . '_apiversion'] == 'v5' && $response->isSuccessful()) { + $this->updatePayment($order_payment, $order['externalId'], $retailcrmApiClient); } } - unset($customers); - - $response = $this->retailcrmApiClient->ordersEdit($order); - - if ($this->settings[$this->moduleTitle . '_apiversion'] == 'v5' && $response->isSuccessful()) { - $response_order = $this->retailcrmApiClient->ordersGet($order_id); - if ($response_order->isSuccessful()) { - $order_info = $response_order['order']; - } - - foreach ($order_info['payments'] as $payment_data) { - if (isset($payment_data['externalId']) && $payment_data['externalId'] == $order_id) { - $payment = $payment_data; - } - } - - if (isset($payment) && $payment['type'] != $this->settings[$this->moduleTitle . '_payment'][$order_data['payment_code']]) { - $response = $this->retailcrmApiClient->ordersPaymentDelete($payment['id']); - - if ($response->isSuccessful()) { - $this->createPayment($order_data, $order_id); - } - } elseif (isset($payment) && $payment['type'] == $this->settings[$this->moduleTitle . '_payment'][$order_data['payment_code']]) { - $this->editPayment($order_data, $order_id); - } - } + return $order; } /** * Process order - * + * * @param array $order_data - * @param int $order_id - * + * @param bool $create (default = true) + * * @return array $order */ - protected function processOrder($order_data, $order_id) - { + public function processOrder($order_data, $create = true) { $this->load->model('setting/setting'); $this->load->model('catalog/product'); $this->settings = $this->model_setting_setting->getSetting($this->moduleTitle); + $order_id = $order_data['order_id']; if (!empty($order_data['payment_code']) && isset($this->settings[$this->moduleTitle . '_payment'][$order_data['payment_code']])) { $payment_code = $this->settings[$this->moduleTitle . '_payment'][$order_data['payment_code']]; @@ -153,7 +88,11 @@ class ModelExtensionRetailcrmOrder extends Model { $order['phone'] = $order_data['telephone']; $order['customerComment'] = $order_data['comment']; - if(!empty($order_data['email'])) { + if ($order_data['customer_id']) { + $order['customer']['externalId'] = $order_data['customer_id']; + } + + if (!empty($order_data['email'])) { $order['email'] = $order_data['email']; } @@ -161,18 +100,18 @@ class ModelExtensionRetailcrmOrder extends Model { $couponTotal = 0; $orderTotals = isset($order_data['totals']) ? $order_data['totals'] : $order_data['order_total'] ; - foreach ($orderTotals as $totals) { - if ($totals['code'] == 'shipping') { - $deliveryCost = $totals['value']; - } + $totals = $this->explodeTotals($orderTotals); - if ($totals['code'] == 'coupon') { - $couponTotal += abs($totals['value']); - } + if (isset($totals['shipping'])) { + $deliveryCost = $totals['shipping']; + } - if ($totals['code'] == 'reward') { - $couponTotal += abs($totals['value']); - } + if (isset($totals['coupon'])) { + $couponTotal += abs($totals['coupon']); + } + + if (isset($totals['reward'])) { + $couponTotal += abs($totals['reward']); } $order['createdAt'] = $order_data['date_added']; @@ -188,10 +127,10 @@ class ModelExtensionRetailcrmOrder extends Model { } } - $country = (isset($order_data['shipping_country'])) ? $order_data['shipping_country'] : '' ; + $country = isset($order_data['shipping_country']) ? $order_data['shipping_country'] : '' ; $order['delivery'] = array( - 'code' => $delivery_code, + 'code' => isset($delivery_code) ? $delivery_code : '', 'address' => array( 'index' => $order_data['shipping_postcode'], 'city' => $order_data['shipping_city'], @@ -207,10 +146,10 @@ class ModelExtensionRetailcrmOrder extends Model { ) ); - if(!empty($deliveryCost)){ + if (!empty($deliveryCost)){ $order['delivery']['cost'] = $deliveryCost; } - + $orderProducts = isset($order_data['products']) ? $order_data['products'] : $order_data['order_product']; $offerOptions = array('select', 'radio'); @@ -222,7 +161,7 @@ class ModelExtensionRetailcrmOrder extends Model { $productOptions = $this->model_catalog_product->getProductOptions($product['product_id']); - foreach($product['option'] as $option) { + foreach ($product['option'] as $option) { if ($option['type'] == 'checkbox') { $properties[] = array( 'code' => $option['product_option_value_id'], @@ -231,7 +170,7 @@ class ModelExtensionRetailcrmOrder extends Model { ); } - if(!in_array($option['type'], $offerOptions)) continue; + if (!in_array($option['type'], $offerOptions)) continue; foreach($productOptions as $productOption) { if($productOption['product_option_id'] = $option['product_option_id']) { foreach($productOption['product_option_value'] as $productOptionValue) { @@ -246,7 +185,7 @@ class ModelExtensionRetailcrmOrder extends Model { ksort($options); $offerId = array(); - foreach($options as $optionKey => $optionValue) { + foreach ($options as $optionKey => $optionValue) { $offerId[] = $optionKey.'-'.$optionValue; } $offerId = implode('_', $offerId); @@ -295,64 +234,89 @@ class ModelExtensionRetailcrmOrder extends Model { } } + $payment = array( + 'externalId' => $order_id, + 'type' => $payment_code, + 'amount' => $totals['total'] + ); + + if (!$create) { + $payment['order'] = array( + 'externalId' => $order_id + ); + } + + $order['payments'][] = $payment; + return $order; } /** - * Create payment - * - * @param array $order - * @param int $order_id - * + * Update payment in CRM + * + * @param array $order_payment + * @param int $orderId + * * @return void */ - protected function createPayment($order, $order_id) - { - $payment_code = $order['payment_code']; + private function updatePayment($order_payment, $orderId, $retailcrmApiClient) { + $response_order = $retailcrmApiClient->ordersGet($orderId); - foreach ($order['totals'] as $total) { - if ($total['code'] == 'total') { - $amount = $total['value']; + if ($response_order->isSuccessful()) { + $order_info = $response_order['order']; + } + + foreach ($order_info['payments'] as $payment_data) { + if (isset($payment_data['externalId']) && $payment_data['externalId'] == $orderId) { + $payment = $payment_data; } } - $payment = array( - 'externalId' => $order_id, - 'type' => $this->settings[$this->moduleTitle . '_payment'][$payment_code], - 'amount' => $amount + if (isset($payment) && $payment['type'] != $order_payment['type']) { + $response = $retailcrmApiClient->ordersPaymentDelete($payment['id']); + + if ($response->isSuccessful()) { + $retailcrmApiClient->ordersPaymentCreate($order_payment); + } + } elseif (isset($payment) && $payment['type'] == $order_payment['type']) { + $retailcrmApiClient->ordersPaymentEdit($order_payment); + } + } + + private function searchCustomer($phone, $email, $retailcrmApiClient) { + $customer = array(); + + $response = $retailcrmApiClient->customersList( + array( + 'name' => $phone, + 'email' => $email + ), + 1, + 100 ); - $payment['order'] = array( - 'externalId' => $order_id - ); + if ($response->isSuccessful()) { + if ($response['customers']) { + $customer = end($response['customers']); + } + } - $this->retailcrmApiClient->ordersPaymentCreate($payment); + return $customer; } /** - * Edit payment - * - * @param array $order - * @param int $order_id - * - * @return void + * @param $totals + * + * @return array */ - protected function editPayment($order, $order_id) + private function explodeTotals($totals) { - $payment_code = $order['payment_code']; + $resultTotals = array(); - foreach ($order['totals'] as $total) { - if ($total['code'] == 'total') { - $amount = $total['value']; - } + foreach ($totals as $total) { + $resultTotals[$total['code']] = $total['value']; } - $payment = array( - 'externalId' => $order_id, - 'type' => $this->settings[$this->moduleTitle . '_payment'][$payment_code], - 'amount' => $amount - ); - - $this->retailcrmApiClient->ordersPaymentEdit($payment); + return $resultTotals; } } diff --git a/system/cron/.htaccess b/src/upload/system/cron/.htaccess similarity index 100% rename from system/cron/.htaccess rename to src/upload/system/cron/.htaccess diff --git a/system/cron/dispatch.php b/src/upload/system/cron/dispatch.php similarity index 100% rename from system/cron/dispatch.php rename to src/upload/system/cron/dispatch.php diff --git a/system/cron/export.php b/src/upload/system/cron/export.php similarity index 100% rename from system/cron/export.php rename to src/upload/system/cron/export.php diff --git a/system/cron/history.php b/src/upload/system/cron/history.php similarity index 100% rename from system/cron/history.php rename to src/upload/system/cron/history.php diff --git a/system/cron/icml.php b/src/upload/system/cron/icml.php similarity index 100% rename from system/cron/icml.php rename to src/upload/system/cron/icml.php diff --git a/system/cron/prices.php b/src/upload/system/cron/prices.php similarity index 100% rename from system/cron/prices.php rename to src/upload/system/cron/prices.php diff --git a/system/library/retailcrm/CurlException.php b/src/upload/system/library/retailcrm/CurlException.php similarity index 100% rename from system/library/retailcrm/CurlException.php rename to src/upload/system/library/retailcrm/CurlException.php diff --git a/system/library/retailcrm/InvalidJsonException.php b/src/upload/system/library/retailcrm/InvalidJsonException.php similarity index 100% rename from system/library/retailcrm/InvalidJsonException.php rename to src/upload/system/library/retailcrm/InvalidJsonException.php diff --git a/system/library/retailcrm/OpencartApiClient.php b/src/upload/system/library/retailcrm/OpencartApiClient.php similarity index 98% rename from system/library/retailcrm/OpencartApiClient.php rename to src/upload/system/library/retailcrm/OpencartApiClient.php index 28813fc..8f92be2 100644 --- a/system/library/retailcrm/OpencartApiClient.php +++ b/src/upload/system/library/retailcrm/OpencartApiClient.php @@ -30,8 +30,8 @@ class OpencartApiClient { $cookieFile = explode("\n", $cookieFile); $cookies = array(); - foreach($cookieFile as $line) { - if(empty($line) OR $line{0} == '#') { + foreach ($cookieFile as $line) { + if (empty($line) OR $line{0} == '#') { continue; } diff --git a/system/library/retailcrm/RetailcrmApiClient3.php b/src/upload/system/library/retailcrm/RetailcrmApiClient3.php similarity index 100% rename from system/library/retailcrm/RetailcrmApiClient3.php rename to src/upload/system/library/retailcrm/RetailcrmApiClient3.php diff --git a/system/library/retailcrm/RetailcrmApiClient4.php b/src/upload/system/library/retailcrm/RetailcrmApiClient4.php similarity index 100% rename from system/library/retailcrm/RetailcrmApiClient4.php rename to src/upload/system/library/retailcrm/RetailcrmApiClient4.php diff --git a/system/library/retailcrm/RetailcrmApiClient5.php b/src/upload/system/library/retailcrm/RetailcrmApiClient5.php similarity index 100% rename from system/library/retailcrm/RetailcrmApiClient5.php rename to src/upload/system/library/retailcrm/RetailcrmApiClient5.php diff --git a/system/library/retailcrm/RetailcrmApiResponse.php b/src/upload/system/library/retailcrm/RetailcrmApiResponse.php similarity index 100% rename from system/library/retailcrm/RetailcrmApiResponse.php rename to src/upload/system/library/retailcrm/RetailcrmApiResponse.php diff --git a/system/library/retailcrm/RetailcrmHistoryHelper.php b/src/upload/system/library/retailcrm/RetailcrmHistoryHelper.php similarity index 100% rename from system/library/retailcrm/RetailcrmHistoryHelper.php rename to src/upload/system/library/retailcrm/RetailcrmHistoryHelper.php diff --git a/system/library/retailcrm/RetailcrmHttpClient.php b/src/upload/system/library/retailcrm/RetailcrmHttpClient.php similarity index 100% rename from system/library/retailcrm/RetailcrmHttpClient.php rename to src/upload/system/library/retailcrm/RetailcrmHttpClient.php diff --git a/system/library/retailcrm/RetailcrmProxy.php b/src/upload/system/library/retailcrm/RetailcrmProxy.php similarity index 100% rename from system/library/retailcrm/RetailcrmProxy.php rename to src/upload/system/library/retailcrm/RetailcrmProxy.php diff --git a/system/library/retailcrm/bootstrap.php b/src/upload/system/library/retailcrm/bootstrap.php similarity index 100% rename from system/library/retailcrm/bootstrap.php rename to src/upload/system/library/retailcrm/bootstrap.php diff --git a/system/library/retailcrm/objects.xml b/src/upload/system/library/retailcrm/objects.xml similarity index 100% rename from system/library/retailcrm/objects.xml rename to src/upload/system/library/retailcrm/objects.xml diff --git a/system/library/retailcrm/retailcrm.php b/src/upload/system/library/retailcrm/retailcrm.php similarity index 90% rename from system/library/retailcrm/retailcrm.php rename to src/upload/system/library/retailcrm/retailcrm.php index f6ae4d5..472e45e 100644 --- a/system/library/retailcrm/retailcrm.php +++ b/src/upload/system/library/retailcrm/retailcrm.php @@ -12,35 +12,41 @@ class Retailcrm { { $this->registry = $registry; } + public function __get($name) { return $this->registry->get($name); } /** * Get api client object - * + * * @param string $apiUrl (default = null) * @param string $apiKey (default = null) * @param string $apiVersion (default = null) - * + * * @return mixed object | boolean */ public function getApiClient($apiUrl = null, $apiKey = null, $apiVersion = null) { $this->load->model('setting/setting'); - + $setting = $this->model_setting_setting->getSetting($this->getModuleTitle()); + if (!$setting) { + return false; + } + if ($apiUrl === null && $apiKey === null) { - $apiUrl = $setting[$this->getModuleTitle() . '_url']; - $apiKey = $setting[$this->getModuleTitle() . '_apikey']; - $apiVersion = $setting[$this->getModuleTitle() . '_apiversion']; + $apiUrl = isset($setting[$this->getModuleTitle() . '_url']) + ? $setting[$this->getModuleTitle() . '_url'] : ''; + $apiKey = isset($setting[$this->getModuleTitle() . '_apikey']) + ? $setting[$this->getModuleTitle() . '_apikey'] : ''; + $apiVersion = isset($setting[$this->getModuleTitle() . '_apiversion']) + ? $setting[$this->getModuleTitle() . '_apiversion'] : ''; } if ($apiUrl && $apiKey) { - $this->apiClient = new \RetailcrmProxy($apiUrl, $apiKey, DIR_LOGS . 'retailcrm.log', $apiVersion); - - return $this->apiClient; + return new \RetailcrmProxy($apiUrl, $apiKey, DIR_LOGS . 'retailcrm.log', $apiVersion); } return false; @@ -48,9 +54,9 @@ class Retailcrm { /** * Get opencart api client - * + * * @param object $registry - * + * * @return \OpencartApiClient */ public function getOcApiClient($registry) @@ -60,7 +66,7 @@ class Retailcrm { /** * Get module title for this version - * + * * @return string $title */ public function getModuleTitle() @@ -76,7 +82,7 @@ class Retailcrm { /** * Get token param name - * + * * @return string $token */ public function getTokenTitle() diff --git a/tests/admin/ControllerRetailcrmAdminTest.php b/tests/admin/ControllerRetailcrmAdminTest.php new file mode 100644 index 0000000..bc8dd01 --- /dev/null +++ b/tests/admin/ControllerRetailcrmAdminTest.php @@ -0,0 +1,57 @@ +db->query("SELECT permission from ".DB_PREFIX."user_group WHERE name = 'Administrator'"); + $permissions = json_decode($query->row['permission'],true); + + if (!in_array('extension/module/retailcrm',$permissions['access'])) { + $permissions['access'][] = 'extension/module/retailcrm'; + $this->db->query("UPDATE ".DB_PREFIX."user_group SET permission='".$this->db->escape(json_encode($permissions))."' WHERE name = 'Administrator'"); + } + + $this->retailcrm = $this->getMockBuilder('\retailcrm\Retailcrm') + ->disableOriginalConstructor() + ->getMock(); + } + + public function testIndex() + { + $this->login('admin', 'admin'); + + $response = $this->dispatchAction('extension/module/retailcrm'); + $this->assertRegExp('/Connection settings/', $response->getOutput()); + } + + public function testIcml() + { + $this->login('admin', 'admin'); + + $response = $this->dispatchAction('extension/module/retailcrm/icml'); + + $this->assertRegExp('/Connection settings/', $response->getOutput()); + $this->assertFileExists(DIR_SYSTEM . '../' . 'retailcrm.xml'); + } + + public function testInstallCollector() + { + $this->login('admin', 'admin'); + + $response = $this->dispatchAction('extension/module/retailcrm/install_collector'); + + $this->assertRegExp('/Connection settings/', $response->getOutput()); + } + + public function testUnnstallCollector() + { + $this->login('admin', 'admin'); + + $response = $this->dispatchAction('extension/module/retailcrm/uninstall_collector'); + + $this->assertRegExp('/Connection settings/', $response->getOutput()); + } +} diff --git a/tests/admin/ModelRetailcrmCustomerAdminTest.php b/tests/admin/ModelRetailcrmCustomerAdminTest.php new file mode 100644 index 0000000..80bf169 --- /dev/null +++ b/tests/admin/ModelRetailcrmCustomerAdminTest.php @@ -0,0 +1,59 @@ +customerModel = $this->loadModel('extension/retailcrm/customer'); + + $this->apiClientMock = $this->getMockBuilder(\RetailcrmProxy::class) + ->disableOriginalConstructor() + ->setMethods(array( + 'customersUpload', + 'customersEdit' + )) + ->getMock(); + } + + public function testUploadToCrm() + { + $customerModel = $this->loadModel('customer/customer'); + $customers = $customerModel->getCustomers(); + + $customersSend = $this->customerModel->uploadToCrm($customers, $this->apiClientMock); + $customer = $customersSend[0][0]; + + $this->assertInternalType('array', $customersSend); + $this->assertInternalType('array', $customersSend[0]); + $this->assertArrayHasKey('externalId', $customer); + $this->assertArrayHasKey('firstName', $customer); + $this->assertArrayHasKey('lastName', $customer); + $this->assertArrayHasKey('email', $customer); + } + + public function testChangeInCrm() + { + $customerModel = $this->loadModel('customer/customer'); + $customer = $customerModel->getCustomer(self::CUSTOMER_ID); + + $customerSend = $this->customerModel->changeInCrm($customer, $this->apiClientMock); + + $this->assertArrayHasKey('externalId', $customerSend); + $this->assertEquals(self::CUSTOMER_ID, $customerSend['externalId']); + $this->assertArrayHasKey('firstName', $customerSend); + $this->assertEquals('Test', $customerSend['firstName']); + $this->assertArrayHasKey('lastName', $customerSend); + $this->assertEquals('Test', $customerSend['lastName']); + $this->assertArrayHasKey('email', $customerSend); + $this->assertEquals('test@mail.ru', $customerSend['email']); + $this->assertArrayHasKey('phones', $customerSend); + $this->assertEquals('+7 (000) 000-00-00', $customerSend['phones'][0]['number']); + } +} diff --git a/tests/admin/ModelRetailcrmOrderAdminTest.php b/tests/admin/ModelRetailcrmOrderAdminTest.php new file mode 100644 index 0000000..8658edb --- /dev/null +++ b/tests/admin/ModelRetailcrmOrderAdminTest.php @@ -0,0 +1,185 @@ +orderModel = $this->loadModel('extension/retailcrm/order'); + + $this->apiClientMock = $this->getMockBuilder(\RetailcrmProxy::class) + ->disableOriginalConstructor() + ->setMethods(array( + 'ordersUpload', + 'customersList', + 'ordersCreate', + 'ordersPaymentCreate' + )) + ->getMock(); + + $this->settingModel = $this->loadModel('setting/setting'); + $this->retailcrm = new \retailcrm\Retailcrm(self::$registry); + + $this->settingModel->editSetting( + $this->retailcrm->getModuleTitle(), + array( + $this->retailcrm->getModuleTitle() . '_apiversion' => 'v5', + $this->retailcrm->getModuleTitle() . '_status' => array( + 1 => 'new' + ), + $this->retailcrm->getModuleTitle() . '_delivery' => array( + 'flat.flat' => 'flat' + ), + $this->retailcrm->getModuleTitle() . '_payment' => array( + 'cod' => 'cod' + ) + ) + ); + } + + public function testUploadToCrm() + { + $saleOrderModel = $this->loadModel('sale/order'); + $orders = $saleOrderModel->getOrders(); + $fullOrders = array(); + + foreach ($orders as $order) { + $fullOrder = $saleOrderModel->getOrder($order['order_id']); + + $fullOrder['order_total'] = $saleOrderModel->getOrderTotals($order['order_id']); + $fullOrder['products'] = $saleOrderModel->getOrderProducts($order['order_id']); + + foreach($fullOrder['products'] as $key => $product) { + $fullOrder['products'][$key]['option'] = $saleOrderModel->getOrderOptions($product['order_id'], $product['order_product_id']); + } + + $fullOrders[] = $fullOrder; + } + + $chunkedOrders = $this->orderModel->uploadToCrm($fullOrders, $this->apiClientMock); + + $order = $chunkedOrders[0][0]; + + $this->assertInternalType('array', $chunkedOrders); + $this->assertInternalType('array', $chunkedOrders[0]); + $this->assertNotEmpty($chunkedOrders[0]); + $this->assertArrayHasKey('externalId', $order); + $this->assertArrayHasKey('number', $order); + $this->assertArrayHasKey('firstName', $order); + $this->assertArrayHasKey('lastName', $order); + $this->assertArrayHasKey('email', $order); + $this->assertArrayHasKey('phone', $order); + $this->assertArrayHasKey('createdAt', $order); + $this->assertArrayHasKey('delivery', $order); + $this->assertArrayHasKey('status', $order); + $this->assertArrayHasKey('items', $order); + $this->assertArrayHasKey('payments', $order); + $this->assertNotEmpty($order['payments']); + } + + public function testUploadWithCustomerTest() + { + $saleOrderModel = $this->loadModel('sale/order'); + $order = $saleOrderModel->getOrder(self::ORDER_WITH_CUST_ID); + + $order['totals'] = $saleOrderModel->getOrderTotals($order['order_id']); + $order['products'] = $saleOrderModel->getOrderProducts($order['order_id']); + + foreach($order['products'] as $key => $product) { + $order['products'][$key]['option'] = $saleOrderModel->getOrderOptions($product['order_id'], $product['order_product_id']); + } + + $response = new \RetailcrmApiResponse( + 201, + json_encode( + array( + 'success' => true, + 'id' => 1 + ) + ) + ); + + $this->apiClientMock->expects($this->any())->method('ordersCreate')->willReturn($response); + $orderSend = $this->orderModel->uploadOrder($order, $this->apiClientMock); + + $this->assertArrayHasKey('status', $orderSend); + $this->assertEquals('new', $orderSend['status']); + $this->assertArrayHasKey('externalId', $orderSend); + $this->assertArrayHasKey('number', $orderSend); + $this->assertArrayHasKey('firstName', $orderSend); + $this->assertEquals('Test', $orderSend['firstName']); + $this->assertArrayHasKey('lastName', $orderSend); + $this->assertEquals('Test', $orderSend['lastName']); + $this->assertArrayHasKey('email', $orderSend); + $this->assertEquals('test@mail.ru', $orderSend['email']); + $this->assertArrayHasKey('phone', $orderSend); + $this->assertEquals('+7 (000) 000-00-00', $orderSend['phone']); + $this->assertArrayHasKey('createdAt', $orderSend); + $this->assertArrayHasKey('delivery', $orderSend); + $this->assertInternalType('array', $orderSend['delivery']); + $this->assertEquals('flat', $orderSend['delivery']['code']); + $this->assertEquals('Test', $orderSend['delivery']['address']['city']); + $this->assertEquals('Rostov-na-Donu', $orderSend['delivery']['address']['region']); + $this->assertEquals('111111', $orderSend['delivery']['address']['index']); + $this->assertArrayHasKey('items', $orderSend); + $this->assertArrayHasKey('customerComment', $orderSend); + $this->assertArrayHasKey('customer', $orderSend); + $this->assertArrayHasKey('externalId', $orderSend['customer']); + $this->assertEquals(self::CUSTOMER_ID, $orderSend['customer']['externalId']); + $this->assertArrayHasKey('payments', $orderSend); + $this->assertEquals('cod', $orderSend['payments'][0]['type']); + $this->assertNotEmpty($orderSend['payments']); + } + + public function testUploadWithoutCustomerTest() + { + $saleOrderModel = $this->loadModel('sale/order'); + $order = $saleOrderModel->getOrder(self::ORDER_ID); + + $order['totals'] = $saleOrderModel->getOrderTotals($order['order_id']); + $order['products'] = $saleOrderModel->getOrderProducts($order['order_id']); + + foreach($order['products'] as $key => $product) { + $order['products'][$key]['option'] = $saleOrderModel->getOrderOptions($product['order_id'], $product['order_product_id']); + } + + $response = new \RetailcrmApiResponse( + 201, + json_encode( + array( + 'success' => true, + 'id' => 1 + ) + ) + ); + + $this->apiClientMock->expects($this->any())->method('ordersCreate')->willReturn($response); + $orderSend = $this->orderModel->uploadOrder($order, $this->apiClientMock); + + $this->assertArrayHasKey('status', $orderSend); + $this->assertArrayHasKey('externalId', $orderSend); + $this->assertArrayHasKey('number', $orderSend); + $this->assertArrayHasKey('firstName', $orderSend); + $this->assertArrayHasKey('lastName', $orderSend); + $this->assertArrayHasKey('email', $orderSend); + $this->assertArrayHasKey('phone', $orderSend); + $this->assertArrayHasKey('createdAt', $orderSend); + $this->assertArrayHasKey('delivery', $orderSend); + $this->assertArrayHasKey('items', $orderSend); + $this->assertContains('#', $orderSend['items'][0]['offer']['externalId']); + $this->assertArrayHasKey('payments', $orderSend); + $this->assertArrayHasKey('customerComment', $orderSend); + $this->assertArrayNotHasKey('customer', $orderSend); + $this->assertNotEmpty($orderSend['payments']); + } +} diff --git a/tests/admin/ModelRetailcrmPricesAdminTest.php b/tests/admin/ModelRetailcrmPricesAdminTest.php new file mode 100644 index 0000000..150cfee --- /dev/null +++ b/tests/admin/ModelRetailcrmPricesAdminTest.php @@ -0,0 +1,51 @@ +pricesModel = $this->loadModel('extension/retailcrm/prices'); + + $this->apiClientMock = $this->getMockBuilder(\RetailcrmProxy::class) + ->disableOriginalConstructor() + ->setMethods(array( + 'storePricesUpload', + 'sitesList' + )) + ->getMock(); + + $this->settingModel = $this->loadModel('setting/setting'); + $this->retailcrm = new \retailcrm\Retailcrm(self::$registry); + + $this->settingModel->editSetting( + $this->retailcrm->getModuleTitle(), + array( + $this->retailcrm->getModuleTitle() . '_apiversion' => 'v5', + $this->retailcrm->getModuleTitle() . '_special' => 'special' + ) + ); + } + + public function testUploadPrices() + { + $productModel = $this->loadModel('catalog/product'); + $products = $productModel->getProducts(); + $prices = $this->pricesModel->uploadPrices($products, $this->apiClientMock); + $price = $prices[0][0]; + + $this->assertInternalType('array', $prices); + $this->assertInternalType('array', $prices[0]); + $this->assertInternalType('array', $price); + $this->assertArrayHasKey('externalId', $price); + $this->assertArrayHasKey('site', $price); + $this->assertArrayHasKey('prices', $price); + $this->assertInternalType('array', $price['prices']); + } +} \ No newline at end of file diff --git a/tests/catalog/ControllerRetailcrmApiCatalogTest.php b/tests/catalog/ControllerRetailcrmApiCatalogTest.php new file mode 100644 index 0000000..6afaff5 --- /dev/null +++ b/tests/catalog/ControllerRetailcrmApiCatalogTest.php @@ -0,0 +1,72 @@ +db->query("SELECT * FROM `" . DB_PREFIX . "api` WHERE api_id = 1"); + $api = $query->row; + $this->apiKey = $api['key']; + $this->retailcrm = new \retailcrm\Retailcrm(self::$registry); + + $this->setSetting( + $this->retailcrm->getModuleTitle(), + array( + $this->retailcrm->getModuleTitle() . '_country' => array(1), + ) + ); + + if (isset($this->request->get['key'])) { + unset($this->request->get['key']); + } + } + + public function testGetDeliveryTypes() + { + $response = $this->dispatchAction('api/retailcrm/getDeliveryTypes'); + $data = json_decode($response->getOutput()); + + $this->assertEquals('Not found api key', $data->error); + + $this->request->get['key'] = $this->apiKey; + $response = $this->dispatchAction('api/retailcrm/getDeliveryTypes'); + $data = json_decode($response->getOutput()); + + $this->assertNotEmpty($data); + } + + public function testAddOrderHistory() + { + $response = $this->dispatchAction('api/retailcrm/addOrderHistory'); + $data = json_decode($response->getOutput()); + + $this->assertEquals('Not found api key', $data->error); + + $this->request->get['key'] = $this->apiKey; + $response = $this->dispatchAction('api/retailcrm/addOrderHistory'); + $data = json_decode($response->getOutput()); + + $this->assertEquals('Not found data', $data->error); + } + + protected function setSetting($code, $data, $store_id = 0) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE store_id = '" . (int)$store_id . "' AND `code` = '" . $this->db->escape($code) . "'"); + + foreach ($data as $key => $value) { + if (substr($key, 0, strlen($code)) == $code) { + if (!is_array($value)) { + $this->db->query("INSERT INTO " . DB_PREFIX . "setting SET store_id = '" . (int)$store_id . "', `code` = '" . $this->db->escape($code) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape($value) . "'"); + } else { + $this->db->query("INSERT INTO " . DB_PREFIX . "setting SET store_id = '" . (int)$store_id . "', `code` = '" . $this->db->escape($code) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape(json_encode($value, true)) . "', serialized = '1'"); + } + } + } + } +} diff --git a/tests/catalog/ModelRetailcrmCustomerCatalogTest.php b/tests/catalog/ModelRetailcrmCustomerCatalogTest.php new file mode 100644 index 0000000..9101a0a --- /dev/null +++ b/tests/catalog/ModelRetailcrmCustomerCatalogTest.php @@ -0,0 +1,62 @@ +customerModel = $this->loadModel('extension/retailcrm/customer'); + + $this->apiClientMock = $this->getMockBuilder(\RetailcrmProxy::class) + ->disableOriginalConstructor() + ->setMethods(array( + 'customersCreate', + 'customersEdit' + )) + ->getMock(); + } + + public function testSendToCrm() + { + $customerModel = $this->loadModel('account/customer'); + $customer = $customerModel->getCustomer(self::CUSTOMER_ID); + + $customerSend = $this->customerModel->sendToCrm($customer, $this->apiClientMock); + + $this->assertArrayHasKey('externalId', $customerSend); + $this->assertEquals(self::CUSTOMER_ID, $customerSend['externalId']); + $this->assertArrayHasKey('firstName', $customerSend); + $this->assertEquals('Test', $customerSend['firstName']); + $this->assertArrayHasKey('lastName', $customerSend); + $this->assertEquals('Test', $customerSend['lastName']); + $this->assertArrayHasKey('email', $customerSend); + $this->assertEquals('test@mail.ru', $customerSend['email']); + $this->assertArrayHasKey('phones', $customerSend); + $this->assertEquals('+7 (000) 000-00-00', $customerSend['phones'][0]['number']); + } + + public function testChangeInCrm() + { + $customerModel = $this->loadModel('account/customer'); + $customer = $customerModel->getCustomer(self::CUSTOMER_ID); + + $customerSend = $this->customerModel->changeInCrm($customer, $this->apiClientMock); + + $this->assertArrayHasKey('externalId', $customerSend); + $this->assertEquals(self::CUSTOMER_ID, $customerSend['externalId']); + $this->assertArrayHasKey('firstName', $customerSend); + $this->assertEquals('Test', $customerSend['firstName']); + $this->assertArrayHasKey('lastName', $customerSend); + $this->assertEquals('Test', $customerSend['lastName']); + $this->assertArrayHasKey('email', $customerSend); + $this->assertEquals('test@mail.ru', $customerSend['email']); + $this->assertArrayHasKey('phones', $customerSend); + $this->assertEquals('+7 (000) 000-00-00', $customerSend['phones'][0]['number']); + } +} \ No newline at end of file diff --git a/tests/catalog/ModelRetailcrmOrderCatalogTest.php b/tests/catalog/ModelRetailcrmOrderCatalogTest.php new file mode 100644 index 0000000..903592a --- /dev/null +++ b/tests/catalog/ModelRetailcrmOrderCatalogTest.php @@ -0,0 +1,191 @@ +orderModel = $this->loadModel('extension/retailcrm/order'); + + $this->apiClientMock = $this->getMockBuilder(\RetailcrmProxy::class) + ->disableOriginalConstructor() + ->setMethods(array( + 'ordersCreate', + 'ordersEdit', + 'ordersGet', + 'ordersPaymentEdit', + 'customersList' + )) + ->getMock(); + + $this->retailcrm = new \retailcrm\Retailcrm(self::$registry); + + $this->setSetting( + $this->retailcrm->getModuleTitle(), + array( + $this->retailcrm->getModuleTitle() . '_apiversion' => 'v5', + $this->retailcrm->getModuleTitle() . '_status' => array( + 1 => 'new' + ), + $this->retailcrm->getModuleTitle() . '_delivery' => array( + 'flat.flat' => 'flat' + ), + $this->retailcrm->getModuleTitle() . '_payment' => array( + 'cod' => 'cod' + ) + ) + ); + } + + public function testCreateOrderWithCustomer() + { + $orderCheckoutModel = $this->loadModel('checkout/order'); + $orderAccountModel = $this->loadModel('account/order'); + $order_id = self::ORDER_WITH_CUST_ID; + $order = $orderCheckoutModel->getOrder($order_id); + $order['products'] = $orderAccountModel->getOrderProducts($order_id); + $order['totals'] = $orderAccountModel->getOrderTotals($order_id); + + foreach ($order['products'] as $key => $product) { + $productOptions = $orderAccountModel->getOrderOptions($order_id, $product['order_product_id']); + + if (!empty($productOptions)) { + $order['products'][$key]['option'] = $productOptions; + } + } + + $orderProcess = $this->orderModel->processOrder($order); + $orderSend = $this->orderModel->sendToCrm($orderProcess, $this->apiClientMock); + + $this->assertArrayHasKey('status', $orderSend); + $this->assertEquals('new', $orderSend['status']); + $this->assertArrayHasKey('externalId', $orderSend); + $this->assertArrayHasKey('number', $orderSend); + $this->assertArrayHasKey('firstName', $orderSend); + $this->assertEquals('Test', $orderSend['firstName']); + $this->assertArrayHasKey('lastName', $orderSend); + $this->assertEquals('Test', $orderSend['lastName']); + $this->assertArrayHasKey('email', $orderSend); + $this->assertEquals('test@mail.ru', $orderSend['email']); + $this->assertArrayHasKey('phone', $orderSend); + $this->assertEquals('+7 (000) 000-00-00', $orderSend['phone']); + $this->assertArrayHasKey('createdAt', $orderSend); + $this->assertArrayHasKey('delivery', $orderSend); + $this->assertInternalType('array', $orderSend['delivery']); + $this->assertEquals('flat', $orderSend['delivery']['code']); + $this->assertEquals('Test', $orderSend['delivery']['address']['city']); + $this->assertEquals('Rostov-na-Donu', $orderSend['delivery']['address']['region']); + $this->assertEquals('111111', $orderSend['delivery']['address']['index']); + $this->assertArrayHasKey('items', $orderSend); + $this->assertArrayHasKey('customerComment', $orderSend); + $this->assertArrayHasKey('customer', $orderSend); + $this->assertArrayHasKey('externalId', $orderSend['customer']); + $this->assertEquals(self::CUSTOMER_ID, $orderSend['customer']['externalId']); + $this->assertArrayHasKey('payments', $orderSend); + $this->assertEquals('cod', $orderSend['payments'][0]['type']); + $this->assertNotEmpty($orderSend['payments']); + } + + public function testEditOrderWithCustomer() + { + $orderCheckoutModel = $this->loadModel('checkout/order'); + $orderAccountModel = $this->loadModel('account/order'); + $order_id = self::ORDER_WITH_CUST_ID; + $order = $orderCheckoutModel->getOrder($order_id); + $order['products'] = $orderAccountModel->getOrderProducts($order_id); + $order['totals'] = $orderAccountModel->getOrderTotals($order_id); + + foreach ($order['products'] as $key => $product) { + $productOptions = $orderAccountModel->getOrderOptions($order_id, $product['order_product_id']); + + if (!empty($productOptions)) { + $order['products'][$key]['option'] = $productOptions; + } + } + + $orderEditResponse = new \RetailcrmApiResponse( + 200, + json_encode( + array( + 'success' => true, + 'id' => 1 + ) + ) + ); + + $ordersGetResponse = new \RetailcrmApiResponse( + 200, + json_encode( + array( + 'success' => true, + 'order' => $this->getOrder($order_id) + ) + ) + ); + + $this->apiClientMock->expects($this->any())->method('ordersEdit')->willReturn($orderEditResponse); + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn($ordersGetResponse); + $orderProcess = $this->orderModel->processOrder($order); + $orderSend = $this->orderModel->sendToCrm($orderProcess, $this->apiClientMock, false); + + $this->assertArrayHasKey('status', $orderSend); + $this->assertEquals('new', $orderSend['status']); + $this->assertArrayHasKey('externalId', $orderSend); + $this->assertArrayHasKey('number', $orderSend); + $this->assertArrayHasKey('firstName', $orderSend); + $this->assertEquals('Test', $orderSend['firstName']); + $this->assertArrayHasKey('lastName', $orderSend); + $this->assertEquals('Test', $orderSend['lastName']); + $this->assertArrayHasKey('email', $orderSend); + $this->assertEquals('test@mail.ru', $orderSend['email']); + $this->assertArrayHasKey('phone', $orderSend); + $this->assertEquals('+7 (000) 000-00-00', $orderSend['phone']); + $this->assertArrayHasKey('createdAt', $orderSend); + $this->assertArrayHasKey('delivery', $orderSend); + $this->assertInternalType('array', $orderSend['delivery']); + $this->assertEquals('flat', $orderSend['delivery']['code']); + $this->assertEquals('Test', $orderSend['delivery']['address']['city']); + $this->assertEquals('Rostov-na-Donu', $orderSend['delivery']['address']['region']); + $this->assertEquals('111111', $orderSend['delivery']['address']['index']); + $this->assertArrayHasKey('items', $orderSend); + $this->assertArrayHasKey('customerComment', $orderSend); + } + + protected function setSetting($code, $data, $store_id = 0) { + $this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE store_id = '" . (int)$store_id . "' AND `code` = '" . $this->db->escape($code) . "'"); + + foreach ($data as $key => $value) { + if (substr($key, 0, strlen($code)) == $code) { + if (!is_array($value)) { + $this->db->query("INSERT INTO " . DB_PREFIX . "setting SET store_id = '" . (int)$store_id . "', `code` = '" . $this->db->escape($code) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape($value) . "'"); + } else { + $this->db->query("INSERT INTO " . DB_PREFIX . "setting SET store_id = '" . (int)$store_id . "', `code` = '" . $this->db->escape($code) . "', `key` = '" . $this->db->escape($key) . "', `value` = '" . $this->db->escape(json_encode($value, true)) . "', serialized = '1'"); + } + } + } + } + + private function getOrder($id) + { + return array( + 'payments' => array( + array( + 'id' => 1, + 'status' => 'not-paid', + 'type' => 'cod', + 'externalId' => $id, + 'amount' => '100' + ) + ) + ); + } +} diff --git a/tests/opencart_sample_data.sql b/tests/opencart_sample_data.sql new file mode 100644 index 0000000..cb4812d --- /dev/null +++ b/tests/opencart_sample_data.sql @@ -0,0 +1,49 @@ +TRUNCATE TABLE `oc_customer`; +INSERT INTO `oc_customer` (`customer_id`, `customer_group_id`, `store_id`, `language_id`, `firstname`, `lastname`, `email`, `telephone`, `fax`, `password`, `salt`, `cart`, `wishlist`, `newsletter`, `address_id`, `custom_field`, `ip`, `status`, `approved`, `safe`, `token`, `code`, `date_added`) VALUES ('1', '1', '0', '1', 'Test', 'Test', 'test@mail.ru', '+7 (000) 000-00-00', '', 'ed3798da75d6cdd695e99e87a60d587a10aa95ff', '51TalnrgH', '', '', '0', '1', '', '172.21.0.1', '1', '1', '0', '', '', '2018-06-07 13:50:08'); + +TRUNCATE TABLE `oc_customer_activity`; +TRUNCATE TABLE `oc_customer_group`; +INSERT INTO `oc_customer_group` (`customer_group_id`, `approval`, `sort_order`) VALUES ('1', '0', '1'); + +TRUNCATE TABLE `oc_customer_group_description`; +INSERT INTO `oc_customer_group_description` (`customer_group_id`, `language_id`, `name`, `description`) VALUES ('1', '1', 'Default', 'test'); + +TRUNCATE TABLE `oc_customer_history`; +TRUNCATE TABLE `oc_customer_ip`; +INSERT INTO `oc_customer_ip` (`customer_ip_id`, `customer_id`, `ip`, `date_added`) VALUES ('4', '1', '172.21.0.1', '2018-06-07 13:50:29'); + +TRUNCATE TABLE `oc_customer_login`; +TRUNCATE TABLE `oc_customer_online`; +TRUNCATE TABLE `oc_customer_reward`; +TRUNCATE TABLE `oc_customer_search`; +TRUNCATE TABLE `oc_customer_transaction`; +TRUNCATE TABLE `oc_customer_wishlist`; +TRUNCATE TABLE `oc_order`; + +INSERT INTO `oc_order` (`order_id`, `invoice_no`, `invoice_prefix`, `store_id`, `store_name`, `store_url`, `customer_id`, `customer_group_id`, `firstname`, `lastname`, `email`, `telephone`, `fax`, `custom_field`, `payment_firstname`, `payment_lastname`, `payment_company`, `payment_address_1`, `payment_address_2`, `payment_city`, `payment_postcode`, `payment_country`, `payment_country_id`, `payment_zone`, `payment_zone_id`, `payment_address_format`, `payment_custom_field`, `payment_method`, `payment_code`, `shipping_firstname`, `shipping_lastname`, `shipping_company`, `shipping_address_1`, `shipping_address_2`, `shipping_city`, `shipping_postcode`, `shipping_country`, `shipping_country_id`, `shipping_zone`, `shipping_zone_id`, `shipping_address_format`, `shipping_custom_field`, `shipping_method`, `shipping_code`, `comment`, `total`, `order_status_id`, `affiliate_id`, `commission`, `marketing_id`, `tracking`, `language_id`, `currency_id`, `currency_code`, `currency_value`, `ip`, `forwarded_ip`, `user_agent`, `accept_language`, `date_added`, `date_modified`) VALUES ('1', '0', 'INV-2016-00', '0', 'Opencart', 'http://localhost:8000/', '1', '1', 'Test', 'Test', 'test@mail.ru', '+7 (000) 000-00-00', '', '', 'Test', 'Test', '', 'Address', 'Address 2', 'Test', '111111', 'Russian Federation', '176', 'Rostov-na-Donu', '99', '', '[]', 'Cash on delivery', 'cod', 'Test', 'Test', '', 'Address', 'Address 2', 'Test', '111111', 'Russian Federation', '176', 'Rostov-na-Donu', '99', '', '[]', 'Flat Rate', 'flat.flat', '', '106.0000', '1', '0', '0.0000', '0', '', '1', '1', 'USD', '1.00000000', '172.21.0.1', '', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36', 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', '2018-06-07 13:51:10', '2018-06-07 13:51:23'); +INSERT INTO `oc_order` (`order_id`, `invoice_no`, `invoice_prefix`, `store_id`, `store_name`, `store_url`, `customer_id`, `customer_group_id`, `firstname`, `lastname`, `email`, `telephone`, `fax`, `custom_field`, `payment_firstname`, `payment_lastname`, `payment_company`, `payment_address_1`, `payment_address_2`, `payment_city`, `payment_postcode`, `payment_country`, `payment_country_id`, `payment_zone`, `payment_zone_id`, `payment_address_format`, `payment_custom_field`, `payment_method`, `payment_code`, `shipping_firstname`, `shipping_lastname`, `shipping_company`, `shipping_address_1`, `shipping_address_2`, `shipping_city`, `shipping_postcode`, `shipping_country`, `shipping_country_id`, `shipping_zone`, `shipping_zone_id`, `shipping_address_format`, `shipping_custom_field`, `shipping_method`, `shipping_code`, `comment`, `total`, `order_status_id`, `affiliate_id`, `commission`, `marketing_id`, `tracking`, `language_id`, `currency_id`, `currency_code`, `currency_value`, `ip`, `forwarded_ip`, `user_agent`, `accept_language`, `date_added`, `date_modified`) VALUES ('2', '0', 'INV-2016-00', '0', 'Opencart', 'http://localhost:8000/', '0', '1', 'Test', 'Test', 'test@mail.ru', '+7 (000) 000-00-00', '', '[]', 'Test', 'Test', '', 'Address', 'Address 2', 'Test', '111111', 'Russian Federation', '176', 'Rostov-na-Donu', '99', '', '[]', 'Cash on delivery', 'cod', 'Test', 'Test', '', 'Address', 'Address 2', 'Test', '111111', 'Russian Federation', '176', 'Rostov-na-Donu', '99', '', '[]', 'Flat Rate', 'flat.flat', '', '85.0000', '1', '0', '0.0000', '0', '', '1', '1', 'USD', '1.00000000', '172.21.0.1', '', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36', 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', '2018-06-07 13:53:50', '2018-06-07 13:54:00'); + +TRUNCATE TABLE `oc_order_custom_field`; +TRUNCATE TABLE `oc_order_history`; +INSERT INTO `oc_order_history` (`order_history_id`, `order_id`, `order_status_id`, `notify`, `comment`, `date_added`) VALUES ('19', '2', '1', '0', '', '2018-06-07 13:54:00'); +INSERT INTO `oc_order_history` (`order_history_id`, `order_id`, `order_status_id`, `notify`, `comment`, `date_added`) VALUES ('18', '1', '1', '0', '', '2018-06-07 13:51:23'); + +TRUNCATE TABLE `oc_order_option`; + +INSERT INTO `oc_order_option` (`order_option_id`, `order_id`, `order_product_id`, `product_option_id`, `product_option_value_id`, `name`, `value`, `type`) VALUES ('15', '2', '55', '226', '15', 'Select', 'Red', 'select'); + +TRUNCATE TABLE `oc_order_product`; +INSERT INTO `oc_order_product` (`order_product_id`, `order_id`, `product_id`, `name`, `model`, `quantity`, `price`, `total`, `tax`, `reward`) VALUES ('54', '1', '40', 'iPhone', 'product 11', '1', '101.0000', '101.0000', '18.0000', '20'); +INSERT INTO `oc_order_product` (`order_product_id`, `order_id`, `product_id`, `name`, `model`, `quantity`, `price`, `total`, `tax`, `reward`) VALUES ('55', '2', '30', 'Canon EOS 5D', 'Product 3', '1', '80.0000', '80.0000', '18.0000', '200'); + +TRUNCATE TABLE `oc_order_recurring`; +TRUNCATE TABLE `oc_order_recurring_transaction`; +TRUNCATE TABLE `oc_order_total`; +INSERT INTO `oc_order_total` (`order_total_id`, `order_id`, `code`, `title`, `value`, `sort_order`) VALUES ('162', '1', 'shipping', 'Flat Rate', '5.0000', '3'); +INSERT INTO `oc_order_total` (`order_total_id`, `order_id`, `code`, `title`, `value`, `sort_order`) VALUES ('161', '1', 'sub_total', 'Sub-Total', '101.0000', '1'); +INSERT INTO `oc_order_total` (`order_total_id`, `order_id`, `code`, `title`, `value`, `sort_order`) VALUES ('164', '2', 'sub_total', 'Sub-Total', '80.0000', '1'); +INSERT INTO `oc_order_total` (`order_total_id`, `order_id`, `code`, `title`, `value`, `sort_order`) VALUES ('165', '2', 'shipping', 'Flat Rate', '5.0000', '3'); +INSERT INTO `oc_order_total` (`order_total_id`, `order_id`, `code`, `title`, `value`, `sort_order`) VALUES ('163', '1', 'total', 'Total', '106.0000', '9'); +INSERT INTO `oc_order_total` (`order_total_id`, `order_id`, `code`, `title`, `value`, `sort_order`) VALUES ('166', '2', 'total', 'Total', '85.0000', '9'); + +TRUNCATE TABLE `oc_order_voucher`; \ No newline at end of file From c49070ea6f0cd13a7f9d41731ad0537c349366cd Mon Sep 17 00:00:00 2001 From: Akolzin Dmitry Date: Wed, 13 Jun 2018 16:19:33 +0300 Subject: [PATCH 2/6] Update readme --- README.md | 67 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8050437..216764c 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,57 @@ -# OpenCart Project Template +Opencart module +=============== -## Getting Started +Module allows integrate CMS Opencart >= 2.3 with [retailCRM](http://retailcrm.pro) - 1. Create a new project: `composer create-project beyondit/opencart-project-template ./my/project/folder -s dev` - 2. Copy the `.env.sample` file to `.env` and set the configuration parameters respectively - 3. Run `bin/robo opencart:setup` and afterwards `bin/robo opencart:run` on command line (`bin/robo opencart:run &` to run in background) - 4. Open `http://localhost:8000` in your browser +### Previous versions: -## Robo Commands +[v1.x](https://github.com/retailcrm/opencart-module/tree/v1.x) - * `bin/robo opencart:setup` : Install OpenCart with configuration set in `.env` file - * `bin/robo opencart:run` : Run OpenCart on a php build-in web server on port 8000 - * `bin/robo project:deploy` : Mirror contents of the src folder to the OpenCart test environment - * `bin/robo project:watch` : Redeploy after changes inside the src/ folder or the composer.json file - * `bin/robo project:package`: Package a `build.ocmod.zip` inside the target/ folder - -## Writing Tests - - * Based on the [OpenCart Testing Suite](https://github.com/beyondit/opencart-test-suite) project tests can be written. - * After successful setup and deployment, tests can be executed by running the `bin/phpunit` command. - * Two examples inside the `/tests` folder are given, which can be executed as separat Testsuites by `bin/phpunit --testsuite admin-tests` or `bin/phpunit --testsuite catalog-tests` +[v2.x (2.0, 2.1, 2.2)](https://github.com/retailcrm/opencart-module/tree/v2.2) +#### Features: +* Export orders to retailCRM & fetch changes back +* Export product catalog into [ICML](http://www.retailcrm.pro/docs/Developers/ICML) format +#### Install +Copy files to the site root + +``` +unzip master.zip +cp -r opencart-module/* /path/to/site/root +``` + +#### Setup + +* Go to Admin -> Extensions -> Modules -> retailCRM +* Fill you api url & api key +* Specify directories matching + +#### Getting changes in orders + +Add to cron: + +``` +*/5 * * * * /usr/bin/php /path/to/opencart/system/cron/history.php >> /path/to/opencart/system/storage/logs/cronjob_history.log 2>&1 +``` + +#### Setting product catalog export + +Add to cron: + +``` +* */4 * * * /usr/bin/php /path/to/opencart/system/cron/icml.php >> /path/to/opencart/system/storage/logs/cronjob_icml.log 2>&1 +``` + +Your export file will be available by following url + +``` +http://youropencartsite.com/retailcrm.xml +``` + +#### Export existing orders and customers + +You want to run this command onecly: +/usr/bin/php /path/to/opencart/system/cron/export.php From f006561d3e73435ecdb17607c00f6f80e60ba859 Mon Sep 17 00:00:00 2001 From: Akolzin Dmitry Date: Wed, 13 Jun 2018 16:26:07 +0300 Subject: [PATCH 3/6] Edit travis.yml --- .travis.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index d429c4c..b5f512d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,16 +11,17 @@ php: - 7.2 env: - - OC_DB_HOSTNAME=localhost - - OC_DB_USERNAME=root - - OC_DB_PASSWORD=root - - OC_DB_DATABASE=tests_opencart - - OC_DB_DRIVER=mysqli - - OC_USERNAME=admin - - OC_PASSWORD=admin - - OC_EMAIL=you@example.com - - SERVER_PORT=8000 - - SERVER_URL=http://localhost + global: + - OC_DB_HOSTNAME=localhost + - OC_DB_USERNAME=root + - OC_DB_PASSWORD=root + - OC_DB_DATABASE=tests_opencart + - OC_DB_DRIVER=mysqli + - OC_USERNAME=admin + - OC_PASSWORD=admin + - OC_EMAIL=you@example.com + - SERVER_PORT=8000 + - SERVER_URL=http://localhost before_script: # Change MySQL root password From a9c8a96101ef1c738a377e3fde0a07a6d3785b4e Mon Sep 17 00:00:00 2001 From: Akolzin Dmitry Date: Wed, 13 Jun 2018 17:18:06 +0300 Subject: [PATCH 4/6] Edit Robofile --- .travis.yml | 5 +---- RoboFile.php | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index b5f512d..516e2af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,6 @@ language: php sudo: false php: - - 5.4 - - 5.5 - - 5.6 - 7.0 - 7.1 - 7.2 @@ -19,7 +16,7 @@ env: - OC_DB_DRIVER=mysqli - OC_USERNAME=admin - OC_PASSWORD=admin - - OC_EMAIL=you@example.com + - OC_EMAIL=test@test.com - SERVER_PORT=8000 - SERVER_URL=http://localhost diff --git a/RoboFile.php b/RoboFile.php index f044c4d..6be3b39 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -27,15 +27,28 @@ class RoboFile extends \Robo\Tasks public function __construct() { - foreach ($_ENV as $option => $value) { - if (substr($option, 0, 3) === 'OC_') { - $option = strtolower(substr($option, 3)); - $this->opencart_config[$option] = $value; - } elseif ($option === 'SERVER_PORT') { - $this->server_port = (int) $value; - } elseif ($option === 'SERVER_URL') { - $this->server_url = $value; + if ($_ENV) { + foreach ($_ENV as $option => $value) { + if (substr($option, 0, 3) === 'OC_') { + $option = strtolower(substr($option, 3)); + $this->opencart_config[$option] = $value; + } elseif ($option === 'SERVER_PORT') { + $this->server_port = (int) $value; + } elseif ($option === 'SERVER_URL') { + $this->server_url = $value; + } } + } else { + $this->opencart_config = [ + 'db_hostname' => getenv('OC_DB_HOSTNAME'), + 'db_username' => getenv('OC_DB_USERNAME'), + 'db_password' => getenv('OC_DB_PASSWORD'), + 'db_database' => getenv('OC_DB_DATABASE'), + 'db_driver' => getenv('OC_DB_DRIVER'), + 'username' => getenv('OC_USERNAME'), + 'password' => getenv('OC_PASSWORD'), + 'email' => getenv('OC_EMAIL') + ]; } $this->opencart_config['http_server'] = $this->server_url.':'.$this->server_port.'/'; From 26a6a0731c8644b46e71b477d5af1613bcd5c731 Mon Sep 17 00:00:00 2001 From: Akolzin Dmitry Date: Wed, 13 Jun 2018 17:35:29 +0300 Subject: [PATCH 5/6] Makefile, edit travis.yml --- .travis.yml | 3 +-- Makefile | 14 ++++++++++++++ VERSION | 1 + phpunit.xml => phpunit.xml.dist | 0 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 Makefile create mode 100644 VERSION rename phpunit.xml => phpunit.xml.dist (100%) diff --git a/.travis.yml b/.travis.yml index 516e2af..c98c779 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ sudo: false php: - 7.0 - 7.1 - - 7.2 env: global: @@ -38,6 +37,6 @@ deploy: provider: script script: make on: - php: 7.2 + php: 7.1 branch: master condition: "$DEPLOY = true" \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..779039e --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +FILE = $(TRAVIS_BUILD_DIR)/VERSION +VERSION = `cat $(FILE)` +ARCHIVE_NAME = '/tmp/retailcrm-'$(VERSION)'.zip' + +all: build_archive send_to_ftp delete_archive + +build_archive: + zip -r $(ARCHIVE_NAME) ./src/* + +send_to_ftp: + curl -T $(ARCHIVE_NAME) -u $(FTP_USER):$(FTP_PASSWORD) ftp://$(FTP_HOST) + +delete_archive: + rm -f $(ARCHIVE_NAME) \ No newline at end of file diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..b38ebbf --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.0.4 \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml.dist similarity index 100% rename from phpunit.xml rename to phpunit.xml.dist From 2c4306dad1df6de6e247db679815a3f4c35d964b Mon Sep 17 00:00:00 2001 From: Akolzin Dmitry Date: Thu, 14 Jun 2018 11:26:15 +0300 Subject: [PATCH 6/6] Bug fix --- src/upload/catalog/controller/api/retailcrm.php | 12 ++++-------- .../controller/extension/module/retailcrm.php | 8 +++++++- .../catalog/model/extension/retailcrm/order.php | 8 +++++--- src/upload/system/library/retailcrm/retailcrm.php | 4 ---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/upload/catalog/controller/api/retailcrm.php b/src/upload/catalog/controller/api/retailcrm.php index baa97d7..6512dd5 100644 --- a/src/upload/catalog/controller/api/retailcrm.php +++ b/src/upload/catalog/controller/api/retailcrm.php @@ -147,20 +147,16 @@ class ControllerApiRetailcrm extends Controller if ( version_compare(VERSION, '3.0', '<')) { $api = $this->model_account_api->getApiByKey($this->request->get['key']); } else { - $api = $this->model_account_api->login($this->request->get['username'], $this->request->get['key']); - - if (empty($api)) { - $this->load->model('extension/retailcrm/api'); - $api = $this->model_extension_retailcrm_api->login($this->request->get['username'], $this->request->get['key']); - } + $this->load->model('extension/retailcrm/api'); + $api = $this->model_extension_retailcrm_api->login($this->request->get['username'], $this->request->get['key']); } if (!empty($api)) { return $api; } - - return array('error' => 'Invalid api key'); } + + return array('error' => 'Invalid api key'); } private function loadModels() diff --git a/src/upload/catalog/controller/extension/module/retailcrm.php b/src/upload/catalog/controller/extension/module/retailcrm.php index 21a1daf..faf73ae 100644 --- a/src/upload/catalog/controller/extension/module/retailcrm.php +++ b/src/upload/catalog/controller/extension/module/retailcrm.php @@ -13,8 +13,10 @@ class ControllerExtensionModuleRetailcrm extends Controller { private $retailcrmApiClient; - public function __construct() + public function __construct($registry) { + parent::__construct($registry); + $this->load->library('retailcrm/retailcrm'); $this->retailcrmApiClient = $this->retailcrm->getApiClient(); } @@ -29,9 +31,13 @@ class ControllerExtensionModuleRetailcrm extends Controller { * @return void */ public function order_create($trigger, $data, $order_id = null) { + $this->load->model('checkout/order'); $this->load->model('account/order'); $this->load->library('retailcrm/retailcrm'); + $data = $this->model_checkout_order->getOrder($order_id);; + $data['products'] = $this->model_account_order->getOrderProducts($order_id); + $data['totals'] = $this->model_account_order->getOrderTotals($order_id); $moduleTitle = $this->retailcrm->getModuleTitle(); foreach ($data['products'] as $key => $product) { diff --git a/src/upload/catalog/model/extension/retailcrm/order.php b/src/upload/catalog/model/extension/retailcrm/order.php index 73fff67..6c68084 100644 --- a/src/upload/catalog/model/extension/retailcrm/order.php +++ b/src/upload/catalog/model/extension/retailcrm/order.php @@ -295,9 +295,11 @@ class ModelExtensionRetailcrmOrder extends Model { 100 ); - if ($response->isSuccessful()) { - if ($response['customers']) { - $customer = end($response['customers']); + if ($response->isSuccessful() && isset($response['customers'])) { + $customers = $response['customers']; + + if ($customers) { + $customer = end($customers); } } diff --git a/src/upload/system/library/retailcrm/retailcrm.php b/src/upload/system/library/retailcrm/retailcrm.php index 472e45e..525a43b 100644 --- a/src/upload/system/library/retailcrm/retailcrm.php +++ b/src/upload/system/library/retailcrm/retailcrm.php @@ -32,10 +32,6 @@ class Retailcrm { $setting = $this->model_setting_setting->getSetting($this->getModuleTitle()); - if (!$setting) { - return false; - } - if ($apiUrl === null && $apiKey === null) { $apiUrl = isset($setting[$this->getModuleTitle() . '_url']) ? $setting[$this->getModuleTitle() . '_url'] : '';