diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index eb166266..28ba23fe 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -2,61 +2,6 @@ name: Build on: [push, pull_request] jobs: - deploy: - name: build dependencies & create artifact - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2.0.0 - - name: Install composer dependencies - run: composer install --no-dev -o - - name: Clean-up project - uses: PrestaShopCorp/github-action-clean-before-deploy@v1.0 - - name: Prepare auto-index tool - run: | - composer global require prestashop/autoindex - - name: Generate index.php - run: | - ~/.composer/vendor/bin/autoindex - - name: Create & upload artifact - uses: actions/upload-artifact@v1 - with: - name: ${{ github.event.repository.name }} - path: ../ - update_release_draft: - runs-on: ubuntu-latest - needs: [deploy] - if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' - steps: - - name: Download artifact - uses: actions/download-artifact@v1 - with: - name: ${{ github.event.repository.name }} - - id: release_info - uses: toolmantim/release-drafter@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Prepare for Release - run: | - cd ${{ github.event.repository.name }} - zip -r ${{ github.event.repository.name }}.zip ${{ github.event.repository.name }} - - name: Clean existing assets - shell: bash - run: | - curl -fsSL https://github.com/github/hub/raw/master/script/get | bash -s 2.14.1 - assets=`bin/hub api -t repos/${{ github.repository }}/releases/${{ steps.release_info.outputs.id }}/assets | awk '/\].url/ { print $2 }'` - for asset in $assets - do - bin/hub api -X DELETE $asset - done - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Publish to GitHub Release - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.release_info.outputs.upload_url }} - asset_path: ./${{ github.event.repository.name }}/${{ github.event.repository.name }}.zip - asset_name: ${{ github.event.repository.name }}.zip - asset_content_type: application/zip + build-and-release-draft: + name: Build & Release draft + uses: PrestaShop/.github/.github/workflows/build-release.yml@master diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 694b66ab..8fd1d400 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -3,14 +3,11 @@ on: [push, pull_request] jobs: # Check there is no syntax errors in the project php-linter: - name: PHP Syntax check 5.6 => 8.1 + name: PHP Syntax check 7.2 => 8.2 runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2.0.0 - - - name: PHP syntax checker 5.6 - uses: prestashop/github-action-php-lint/5.6@master + uses: actions/checkout@v3.1.0 - name: PHP syntax checker 7.2 uses: prestashop/github-action-php-lint/7.2@master @@ -27,6 +24,9 @@ jobs: - name: PHP syntax checker 8.1 uses: prestashop/github-action-php-lint/8.1@master + - name: PHP syntax checker 8.2 + uses: prestashop/github-action-php-lint/8.2@master + # Check the PHP code follow the coding standards php-cs-fixer: name: PHP-CS-Fixer @@ -38,10 +38,10 @@ jobs: php-version: '7.4' - name: Checkout - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v3.1.0 - name: Cache dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: vendor key: php-${{ hashFiles('composer.lock') }} @@ -50,7 +50,7 @@ jobs: run: composer install - name: Run PHP-CS-Fixer - run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no --diff-format udiff + run: ./vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no # Run PHPStan against the module and a PrestaShop release phpstan: @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - presta-versions: ['1.7.6', '1.7.7', '1.7.8', 'latest'] + presta-versions: ['1.7.7', '1.7.8', '8.0', 'latest'] steps: - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -66,18 +66,18 @@ jobs: php-version: '7.4' - name: Checkout - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v3.1.0 # Add vendor folder in cache to make next builds faster - name: Cache vendor folder - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: vendor key: php-${{ hashFiles('composer.lock') }} # Add composer local folder in cache to make next builds faster - name: Cache composer folder - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.composer/cache key: php-composer-cache diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 100% rename from .php_cs.dist rename to .php-cs-fixer.dist.php diff --git a/ProductComment.php b/ProductComment.php index 9d5cd015..f3fc56a6 100644 --- a/ProductComment.php +++ b/ProductComment.php @@ -190,6 +190,9 @@ public static function getRatings($id_product) return Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->getRow($sql); } + /** + * @deprecated 4.0.0 + */ public static function getAverageGrade($id_product) { $validate = Configuration::get('PRODUCT_COMMENTS_MODERATE'); @@ -235,6 +238,8 @@ public static function getAveragesByProduct($id_product, $id_lang) * Return number of comments and average grade by products * * @return int|false + * + * @deprecated 4.0.0 */ public static function getCommentNumber($id_product) { @@ -279,6 +284,8 @@ public static function getGradedCommentNumber($id_product) * Get comments by Validation * * @return array Comments + * + * @deprecated 6.0.0 */ public static function getByValidate($validate = '0', $deleted = false, $p = null, $limit = null, $skip_validate = false) { @@ -306,6 +313,8 @@ public static function getByValidate($validate = '0', $deleted = false, $p = nul * Get numbers of comments by Validation * * @return int Count of comments + * + * @deprecated 6.0.0 */ public static function getCountByValidate($validate = '0', $skip_validate = false) { @@ -360,6 +369,8 @@ public function validate($validate = '1') * Delete a comment, grade and report data * * @return bool succeed + * + * @deprecated 6.0.0 */ public function delete() { @@ -373,6 +384,8 @@ public function delete() * Delete Grades * * @return bool succeed + * + * @deprecated 6.0.0 */ public static function deleteGrades($id_product_comment) { @@ -389,6 +402,8 @@ public static function deleteGrades($id_product_comment) * Delete Reports * * @return bool succeed + * + * @deprecated 6.0.0 */ public static function deleteReports($id_product_comment) { @@ -405,6 +420,8 @@ public static function deleteReports($id_product_comment) * Delete usefulness * * @return bool succeed + * + * @deprecated 6.0.0 */ public static function deleteUsefulness($id_product_comment) { @@ -473,6 +490,8 @@ public static function isAlreadyUsefulness($id_product_comment, $id_customer) * Get reported comments * * @return array Comments + * + * @deprecated 6.0.0 */ public static function getReportedComments() { diff --git a/ProductCommentCriterion.php b/ProductCommentCriterion.php index e1c0e538..7e412aaa 100644 --- a/ProductCommentCriterion.php +++ b/ProductCommentCriterion.php @@ -130,6 +130,8 @@ public function addCategory($id_category) * Add grade to a criterion * * @return bool succeed + * + * @deprecated 4.0.0 */ public function addGrade($id_product_comment, $grade) { @@ -154,6 +156,8 @@ public function addGrade($id_product_comment, $grade) * Get criterion by Product * * @return array Criterion + * + * @deprecated 4.0.0 */ public static function getByProduct($id_product, $id_lang) { @@ -201,6 +205,8 @@ public static function getByProduct($id_product, $id_lang) * Get Criterions * * @return array Criterions + * + * @deprecated 6.0.0 */ public static function getCriterions($id_lang, $type = false, $active = false) { @@ -224,6 +230,9 @@ public static function getCriterions($id_lang, $type = false, $active = false) return $criterions; } + /** + * @deprecated 6.0.0 + */ public function getProducts() { $res = Db::getInstance()->executeS(' @@ -240,6 +249,9 @@ public function getProducts() return $products; } + /** + * @deprecated 6.0.0 + */ public function getCategories() { $res = Db::getInstance()->executeS(' @@ -256,6 +268,9 @@ public function getCategories() return $criterions; } + /** + * @deprecated 6.0.0 + */ public function deleteCategories() { return Db::getInstance()->execute(' @@ -263,6 +278,9 @@ public function deleteCategories() WHERE `id_product_comment_criterion` = ' . (int) $this->id); } + /** + * @deprecated 6.0.0 + */ public function deleteProducts() { return Db::getInstance()->execute(' @@ -270,6 +288,9 @@ public function deleteProducts() WHERE `id_product_comment_criterion` = ' . (int) $this->id); } + /** + * @deprecated 6.0.0 + */ public static function getTypes() { // Instance of module class for translations diff --git a/README.md b/README.md index f63e0cca..82825dc5 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,36 @@ Allow users to post reviews on your products and/or rate them based on specific criteria. +## Compatibility + +PrestaShop: `1.7.7` or newer + ## Multistore compatibility This module is partially compatible with the multistore feature. Some of its options might not be available. +## How to test + +Link to specs : https://docs.prestashop-project.org/functional-documentation/functional-documentation/ux-ui/back-office/improve/modules/product-comments-productcomments + +In BO, check that Configuration options work well +Check if reviews are displayed +Approve/delete reviews +Add a review criteria +In FO, add comments to products +Report/thumb up or down a comment +Check product comment in Quickview + ### Update dependency -The only dependency for this module (for now) is https://github.com/flaviusmatis/simplePagination.js.git -You can install/update it by launching the command +There is no JS dependency for this module (for now). +You can install PHP dependency by launching the command ``` -# yarn install +# composer install ``` -(We use yarn because this library is not served as a package for npm). - -This will install the library js in views/js folder. +This will install the PHP libraries in vendor folder. ## Reporting issues @@ -36,7 +50,7 @@ Just make sure to follow our [contribution guidelines][contribution-guidelines]. This module is released under the [Academic Free License 3.0][AFL-3.0] [report-issue]: https://github.com/PrestaShop/PrestaShop/issues/new/choose -[prestashop]: https://www.prestashop.com/ +[prestashop]: https://www.prestashop-project.org/ [contribution-guidelines]: https://devdocs.prestashop.com/1.7/contribute/contribution-guidelines/project-modules/ [AFL-3.0]: https://opensource.org/licenses/AFL-3.0 diff --git a/composer.json b/composer.json index a351ba13..81e84b58 100644 --- a/composer.json +++ b/composer.json @@ -10,19 +10,16 @@ } ], "require": { - "php": ">=5.6.0" + "php": ">=7.1.3" }, "require-dev": { - "prestashop/php-dev-tools": "^3.4" + "prestashop/php-dev-tools": "^4.3" }, "config": { "preferred-install": "dist", "classmap-authoritative": true, "optimize-autoloader": true, - "prepend-autoloader": false, - "platform": { - "php": "5.6" - } + "prepend-autoloader": false }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 2bbe96c1..a5ca29f0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,28 +4,99 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "12984396df2e940e604176b243d7bde5", + "content-hash": "8b03b0cfb726154b52b8caea005883ed", "packages": [], "packages-dev": [ + { + "name": "composer/pcre", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-21T20:24:37+00:00" + }, { "name": "composer/semver", - "version": "3.2.6", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "83e511e247de329283478496f7a1e114c9517506" + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506", - "reference": "83e511e247de329283478496f7a1e114c9517506", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.54", + "phpstan/phpstan": "^1.4", "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", @@ -70,7 +141,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.6" + "source": "https://github.com/composer/semver/tree/3.3.2" }, "funding": [ { @@ -86,29 +157,31 @@ "type": "tidelift" } ], - "time": "2021-10-25T11:34:17+00:00" + "time": "2022-04-01T19:23:25+00:00" }, { "name": "composer/xdebug-handler", - "version": "2.0.2", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339" + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339", - "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", "shasum": "" }, "require": { + "composer/pcre": "^1", "php": "^5.3.2 || ^7.0 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "phpstan/phpstan": "^0.12.55", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" }, "type": "library", "autoload": { @@ -134,7 +207,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.2" + "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" }, "funding": [ { @@ -150,36 +223,40 @@ "type": "tidelift" } ], - "time": "2021-07-31T17:03:58+00:00" + "time": "2022-02-24T20:20:32+00:00" }, { "name": "doctrine/annotations", - "version": "v1.4.0", + "version": "1.14.3", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" + "doctrine/lexer": "^1 || ^2", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.7" + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, + "type": "library", "autoload": { "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" @@ -190,6 +267,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -198,10 +279,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -212,7 +289,7 @@ } ], "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", "keywords": [ "annotations", "docblock", @@ -220,39 +297,86 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/v1.4.0" + "source": "https://github.com/doctrine/annotations/tree/1.14.3" }, - "time": "2017-02-24T16:22:25+00:00" + "time": "2023-02-01T09:20:38+00:00" }, { - "name": "doctrine/lexer", - "version": "1.0.2", + "name": "doctrine/deprecations", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" } }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "time": "2023-06-03T09:27:29+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -260,14 +384,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -284,91 +408,85 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.0.2" + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, - "time": "2019-06-08T11:03:04+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-14T08:49:07+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.19.3", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8" + "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/75ac86f33fab4714ea5a39a396784d83ae3b5ed8", - "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", + "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", "shasum": "" }, "require": { - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.2 || ^2.0", - "doctrine/annotations": "^1.2", + "composer/semver": "^3.2", + "composer/xdebug-handler": "^2.0", + "doctrine/annotations": "^1.12", "ext-json": "*", "ext-tokenizer": "*", - "php": "^5.6 || ^7.0 || ^8.0", - "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", - "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", - "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", - "symfony/finder": "^3.0 || ^4.0 || ^5.0", - "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", - "symfony/polyfill-php70": "^1.0", - "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0 || ^5.0", - "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" + "php": "^7.2.5 || ^8.0", + "php-cs-fixer/diff": "^2.0", + "symfony/console": "^4.4.20 || ^5.1.3 || ^6.0", + "symfony/event-dispatcher": "^4.4.20 || ^5.0 || ^6.0", + "symfony/filesystem": "^4.4.20 || ^5.0 || ^6.0", + "symfony/finder": "^4.4.20 || ^5.0 || ^6.0", + "symfony/options-resolver": "^4.4.20 || ^5.0 || ^6.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php80": "^1.23", + "symfony/polyfill-php81": "^1.23", + "symfony/process": "^4.4.20 || ^5.0 || ^6.0", + "symfony/stopwatch": "^4.4.20 || ^5.0 || ^6.0" }, "require-dev": { - "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.4", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.4.2", - "php-cs-fixer/accessible-object": "^1.0", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^1.5", + "mikey179/vfsstream": "^1.6.8", + "php-coveralls/php-coveralls": "^2.5.2", + "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy": "^1.15", "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", + "phpunit/phpunit": "^8.5.21 || ^9.5", "phpunitgoodpractices/polyfill": "^1.5", "phpunitgoodpractices/traits": "^1.9.1", - "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", - "symfony/phpunit-bridge": "^5.2.1", - "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + "symfony/phpunit-bridge": "^5.2.4 || ^6.0", + "symfony/yaml": "^4.4.20 || ^5.0 || ^6.0" }, "suggest": { "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters.", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", - "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + "ext-mbstring": "For handling non-UTF8 characters." }, "bin": [ "php-cs-fixer" ], "type": "application", - "extra": { - "branch-alias": { - "dev-master": "2.19-dev" - } - }, "autoload": { "psr-4": { "PhpCsFixer\\": "src/" - }, - "classmap": [ - "tests/Test/AbstractFixerTestCase.php", - "tests/Test/AbstractIntegrationCaseFactory.php", - "tests/Test/AbstractIntegrationTestCase.php", - "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/IntegrationCase.php", - "tests/Test/IntegrationCaseFactory.php", - "tests/Test/IntegrationCaseFactoryInterface.php", - "tests/Test/InternalIntegrationCaseFactory.php", - "tests/Test/IsIdenticalConstraint.php", - "tests/Test/TokensWithObservedTransformers.php", - "tests/TestCase.php" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -387,7 +505,7 @@ "description": "A tool to automatically fix PHP code style", "support": { "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.19.3" + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.4.0" }, "funding": [ { @@ -395,28 +513,29 @@ "type": "github" } ], - "time": "2021-11-15T17:17:55+00:00" + "time": "2021-12-11T16:25:08+00:00" }, { "name": "nikic/php-parser", - "version": "v3.1.5", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.5" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, "bin": [ "bin/php-parse" @@ -424,7 +543,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.9-dev" } }, "autoload": { @@ -448,76 +567,22 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v3.1.5" - }, - "time": "2018-02-28T20:30:58+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v2.0.20", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a", - "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2021-04-17T09:33:01+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "php-cs-fixer/diff", - "version": "v1.3.1", + "version": "v2.0.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" + "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", - "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3", + "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3", "shasum": "" }, "require": { @@ -545,41 +610,43 @@ { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" - }, - { - "name": "SpacePossum" } ], - "description": "sebastian/diff v2 backport support for PHP5.6", + "description": "sebastian/diff v3 backport support for PHP 5.6+", "homepage": "https://github.com/PHP-CS-Fixer", "keywords": [ "diff" ], "support": { "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" + "source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2" }, - "time": "2020-10-14T08:39:05+00:00" + "abandoned": true, + "time": "2020-10-14T08:32:19+00:00" }, { "name": "prestashop/autoindex", - "version": "v1.0.0", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/PrestaShopCorp/autoindex.git", - "reference": "92e10242f94a99163dece280f6bd7b7c2b79c158" + "reference": "235f3ec115432ffc32d582198ea498467b3946d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/autoindex/zipball/92e10242f94a99163dece280f6bd7b7c2b79c158", - "reference": "92e10242f94a99163dece280f6bd7b7c2b79c158", + "url": "https://api.github.com/repos/PrestaShopCorp/autoindex/zipball/235f3ec115432ffc32d582198ea498467b3946d0", + "reference": "235f3ec115432ffc32d582198ea498467b3946d0", "shasum": "" }, "require": { - "nikic/php-parser": "^3.1", - "php": ">=5.6", - "symfony/console": "^3.4", - "symfony/finder": "^3.4" + "nikic/php-parser": "^4.10", + "php": "^8.0 || ^7.2", + "symfony/console": "^3.4 || ~4.0 || ~5.0 || ~6.0", + "symfony/finder": "^3.4 || ~4.0 || ~5.0 || ~6.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.83", + "prestashop/php-dev-tools": "1.*" }, "bin": [ "bin/autoindex" @@ -603,31 +670,32 @@ "description": "Automatically add an 'index.php' in all the current or specified directories and all sub-directories.", "homepage": "https://github.com/PrestaShopCorp/autoindex", "support": { - "source": "https://github.com/PrestaShopCorp/autoindex/tree/v1.0.0" + "source": "https://github.com/PrestaShopCorp/autoindex/tree/v2.1.0" }, - "time": "2020-03-11T13:37:03+00:00" + "time": "2022-10-10T08:35:00+00:00" }, { "name": "prestashop/header-stamp", - "version": "v1.7", + "version": "v2.3", "source": { "type": "git", "url": "https://github.com/PrestaShopCorp/header-stamp.git", - "reference": "d77ce6d0a7f066670a4774be88f05e5f07b4b6fc" + "reference": "3104b69ad73b6039c7082dbba4af9dbeb0b936b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/header-stamp/zipball/d77ce6d0a7f066670a4774be88f05e5f07b4b6fc", - "reference": "d77ce6d0a7f066670a4774be88f05e5f07b4b6fc", + "url": "https://api.github.com/repos/PrestaShopCorp/header-stamp/zipball/3104b69ad73b6039c7082dbba4af9dbeb0b936b3", + "reference": "3104b69ad73b6039c7082dbba4af9dbeb0b936b3", "shasum": "" }, "require": { - "nikic/php-parser": "^3.1", - "php": ">=5.6", - "symfony/console": "^3.4 || ~4.0 || ~5.0", - "symfony/finder": "^3.4 || ~4.0 || ~5.0" + "nikic/php-parser": "^4.10", + "php": "^8.0 || ^7.2", + "symfony/console": "^3.4 || ~4.0 || ~5.0 || ~6.0", + "symfony/finder": "^3.4 || ~4.0 || ~5.0 || ~6.0" }, "require-dev": { + "phpstan/phpstan": "^0.12.83", "prestashop/php-dev-tools": "1.*" }, "bin": [ @@ -653,35 +721,32 @@ "homepage": "https://github.com/PrestaShopCorp/header-stamp", "support": { "issues": "https://github.com/PrestaShopCorp/header-stamp/issues", - "source": "https://github.com/PrestaShopCorp/header-stamp/tree/v1.7" + "source": "https://github.com/PrestaShopCorp/header-stamp/tree/v2.3" }, - "time": "2020-12-09T16:40:38+00:00" + "time": "2023-03-23T14:44:10+00:00" }, { "name": "prestashop/php-dev-tools", - "version": "v3.16.1", + "version": "v4.3.0", "source": { "type": "git", "url": "https://github.com/PrestaShop/php-dev-tools.git", - "reference": "785108c29ef6f580930372d88b8f551740fdee98" + "reference": "843275b19729ba810d8ba2b9c97b568e5bbabe03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/785108c29ef6f580930372d88b8f551740fdee98", - "reference": "785108c29ef6f580930372d88b8f551740fdee98", + "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/843275b19729ba810d8ba2b9c97b568e5bbabe03", + "reference": "843275b19729ba810d8ba2b9c97b568e5bbabe03", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^2.14", - "php": ">=5.6.0", - "prestashop/autoindex": "^1.0", - "prestashop/header-stamp": "^1.0", + "friendsofphp/php-cs-fixer": "^3.2", + "php": ">=7.2.5", + "prestashop/autoindex": "^2.0", + "prestashop/header-stamp": "^2.0", "squizlabs/php_codesniffer": "^3.4", - "symfony/console": "~3.2 || ~4.0 || ~5.0", - "symfony/filesystem": "~3.2 || ~4.0 || ~5.0" - }, - "conflict": { - "friendsofphp/php-cs-fixer": "2.18.3" + "symfony/console": "~3.2 || ~4.0 || ~5.0 || ~6.0", + "symfony/filesystem": "~3.2 || ~4.0 || ~5.0 || ~6.0" }, "bin": [ "bin/prestashop-coding-standards" @@ -699,22 +764,22 @@ "description": "PrestaShop coding standards", "support": { "issues": "https://github.com/PrestaShop/php-dev-tools/issues", - "source": "https://github.com/PrestaShop/php-dev-tools/tree/v3.16.1" + "source": "https://github.com/PrestaShop/php-dev-tools/tree/v4.3.0" }, - "time": "2021-10-18T07:48:21+00:00" + "time": "2022-10-18T14:19:51+00:00" }, { - "name": "psr/log", - "version": "1.1.4", + "name": "psr/cache", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", "shasum": "" }, "require": { @@ -723,12 +788,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -738,125 +803,95 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common interface for caching libraries", "keywords": [ - "log", + "cache", "psr", - "psr-3" + "psr-6" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/cache/tree/master" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2016-08-06T20:24:11+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "3.6.1", + "name": "psr/container", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e" + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f268ca40d54617c6e06757f83f699775c9b3ff2e", - "reference": "f268ca40d54617c6e06757f83f699775c9b3ff2e", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" + "php": ">=7.2.0" }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "phpcs", - "standards" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" }, - "time": "2021-10-11T04:00:11+00:00" + "time": "2021-03-05T17:36:06+00:00" }, { - "name": "symfony/console", - "version": "v3.4.47", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81", - "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "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" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "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": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "php": ">=7.2.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\EventDispatcher\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -864,26 +899,286 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], "support": { - "source": "https://github.com/symfony/console/tree/v3.4.47" + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2023-02-22T23:07:41+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.24", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "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": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.24" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-26T05:13:16+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.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": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" }, { @@ -891,40 +1186,408 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-01-02T09:53:40+00:00" }, { - "name": "symfony/debug", - "version": "v3.4.47", + "name": "symfony/event-dispatcher", + "version": "v5.4.22", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "ab42889de57fdfcfcc0759ab102e2fd4ea72dcae" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/ab42889de57fdfcfcc0759ab102e2fd4ea72dcae", - "reference": "ab42889de57fdfcfcc0759ab102e2fd4ea72dcae", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" }, "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-17T11:31:58+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "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": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.25", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "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": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.25" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-31T13:04:02+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "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": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-16T09:33:00+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -932,18 +1595,24 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Debug Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], "support": { - "source": "https://github.com/symfony/debug/tree/v3.4.47" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" }, "funding": [ { @@ -959,48 +1628,45 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v3.4.47", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "31fde73757b6bad247c54597beef974919ec6860" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/31fde73757b6bad247c54597beef974919ec6860", - "reference": "31fde73757b6bad247c54597beef974919ec6860", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", "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/debug": "~3.4|~4.4", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "php": ">=7.1" }, "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "ext-intl": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1008,18 +1674,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v3.4.47" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" }, "funding": [ { @@ -1035,33 +1709,47 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/filesystem", - "version": "v3.4.47", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "e58d7841cddfed6e846829040dca2cca0ebbbbb3" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/e58d7841cddfed6e846829040dca2cca0ebbbbb3", - "reference": "e58d7841cddfed6e846829040dca2cca0ebbbbb3", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1070,18 +1758,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/filesystem/tree/v3.4.47" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" }, "funding": [ { @@ -1097,33 +1793,48 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/finder", - "version": "v3.4.47", + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "b6b6ad3db3edb1b4b1c1896b1975fb684994de6e" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/b6b6ad3db3edb1b4b1c1896b1975fb684994de6e", - "reference": "b6b6ad3db3edb1b4b1c1896b1975fb684994de6e", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1131,18 +1842,25 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/finder/tree/v3.4.47" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" }, "funding": [ { @@ -1158,32 +1876,44 @@ "type": "tidelift" } ], - "time": "2020-11-16T17:02:08+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/options-resolver", - "version": "v3.4.47", + "name": "symfony/polyfill-php73", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "c7efc97a47b2ebaabc19d5b6c6b50f5c37c92744" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/c7efc97a47b2ebaabc19d5b6c6b50f5c37c92744", - "reference": "c7efc97a47b2ebaabc19d5b6c6b50f5c37c92744", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" + "Symfony\\Polyfill\\Php73\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1192,23 +1922,24 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony OptionsResolver Component", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ - "config", - "configuration", - "options" + "compatibility", + "polyfill", + "portable", + "shim" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v3.4.47" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" }, "funding": [ { @@ -1224,32 +1955,29 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.19.0", + "name": "symfony/polyfill-php80", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", - "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.19-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1257,11 +1985,14 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1270,24 +2001,28 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "ctype", "polyfill", - "portable" + "portable", + "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" }, "funding": [ { @@ -1303,32 +2038,29 @@ "type": "tidelift" } ], - "time": "2020-10-23T09:01:57+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.19.0", + "name": "symfony/polyfill-php81", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b5f7b932ee6fa802fc792eabd77c4c88084517ce", - "reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.19-dev" + "dev-main": "1.27-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1336,11 +2068,14 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, "files": [ "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1357,17 +2092,16 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.19.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" }, "funding": [ { @@ -1383,45 +2117,33 @@ "type": "tidelift" } ], - "time": "2020-10-23T09:01:57+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php70", - "version": "v1.19.0", + "name": "symfony/process", + "version": "v5.4.24", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "3fe414077251a81a1b15b1c709faf5c2fbae3d4e" + "url": "https://github.com/symfony/process.git", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3fe414077251a81a1b15b1c709faf5c2fbae3d4e", - "reference": "3fe414077251a81a1b15b1c709faf5c2fbae3d4e", + "url": "https://api.github.com/repos/symfony/process/zipball/e3c46cc5689c8782944274bb30702106ecbe3b64", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0|~9.99", - "php": ">=5.3.3" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.19-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" + "Symfony\\Component\\Process\\": "" }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1430,24 +2152,18 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-php70/tree/v1.19.0" + "source": "https://github.com/symfony/process/tree/v5.4.24" }, "funding": [ { @@ -1463,42 +2179,47 @@ "type": "tidelift" } ], - "time": "2020-10-23T09:01:57+00:00" + "time": "2023-05-17T11:26:05+00:00" }, { - "name": "symfony/polyfill-php72", - "version": "v1.19.0", + "name": "symfony/service-contracts", + "version": "v2.5.2", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "beecef6b463b06954638f02378f52496cb84bacc" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/beecef6b463b06954638f02378f52496cb84bacc", - "reference": "beecef6b463b06954638f02378f52496cb84bacc", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.19-dev" + "dev-main": "2.5-dev" }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] + "Symfony\\Contracts\\Service\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1514,16 +2235,18 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "description": "Generic abstractions related to writing services", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.19.0" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -1539,29 +2262,30 @@ "type": "tidelift" } ], - "time": "2020-10-23T09:01:57+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { - "name": "symfony/process", - "version": "v3.4.47", + "name": "symfony/stopwatch", + "version": "v5.4.21", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca" + "url": "https://github.com/symfony/stopwatch.git", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca", - "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Component\\Stopwatch\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1581,10 +2305,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v3.4.47" + "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" }, "funding": [ { @@ -1600,29 +2324,46 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2023-02-14T08:03:56+00:00" }, { - "name": "symfony/stopwatch", - "version": "v3.4.47", + "name": "symfony/string", + "version": "v5.4.22", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "298b81faad4ce60e94466226b2abbb8c9bca7462" + "url": "https://github.com/symfony/string.git", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/298b81faad4ce60e94466226b2abbb8c9bca7462", - "reference": "298b81faad4ce60e94466226b2abbb8c9bca7462", + "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" + "Symfony\\Component\\String\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1634,18 +2375,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Stopwatch Component", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], "support": { - "source": "https://github.com/symfony/stopwatch/tree/v3.4.47" + "source": "https://github.com/symfony/string/tree/v5.4.22" }, "funding": [ { @@ -1661,7 +2410,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T10:57:07+00:00" + "time": "2023-03-14T06:11:53+00:00" } ], "aliases": [], @@ -1670,11 +2419,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6.0" + "php": ">=7.1.3" }, "platform-dev": [], - "platform-overrides": { - "php": "5.6" - }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } diff --git a/config.xml b/config.xml index 7ed9bb20..cfa4704c 100644 --- a/config.xml +++ b/config.xml @@ -2,7 +2,7 @@ productcomments - + diff --git a/config/common.yml b/config/common.yml index b57877fa..67af6a71 100644 --- a/config/common.yml +++ b/config/common.yml @@ -5,12 +5,14 @@ services: product_comment_criterion_repository: class: PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository arguments: + - '@doctrine' - '@doctrine.dbal.default_connection' - '%database_prefix%' product_comment_repository: class: PrestaShop\Module\ProductComment\Repository\ProductCommentRepository arguments: + - '@doctrine' - '@doctrine.dbal.default_connection' - '%database_prefix%' - '@=service("prestashop.adapter.legacy.configuration").get("PRODUCT_COMMENTS_ALLOW_GUESTS")' diff --git a/package.json b/package.json index 506b5fce..b0230875 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "install": "cp node_modules/simplePagination.js/jquery.simplePagination.js views/js/jquery.simplePagination.js" + "install": "echo \"Error: no install specified\" && exit 1" }, "repository": { "type": "git", @@ -24,6 +24,5 @@ }, "homepage": "https://github.com/PrestaShop/productcomments#readme", "dependencies": { - "simplePagination.js": "https://github.com/flaviusmatis/simplePagination.js.git" } } diff --git a/productcomments.css b/productcomments.css deleted file mode 100644 index a48873cb..00000000 --- a/productcomments.css +++ /dev/null @@ -1,249 +0,0 @@ -/** - * Copyright since 2007 PrestaShop SA and Contributors - * PrestaShop is an International Registered Trademark & Property of PrestaShop SA - * - * NOTICE OF LICENSE - * - * This source file is subject to the Academic Free License 3.0 (AFL-3.0) - * that is bundled with this package in the file LICENSE.md. - * It is also available through the world-wide-web at this URL: - * https://opensource.org/licenses/AFL-3.0 - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@prestashop.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade PrestaShop to newer - * versions in the future. If you wish to customize PrestaShop for your - * needs please refer to https://devdocs.prestashop.com/ for more information. - * - * @author PrestaShop SA and Contributors - * @copyright Since 2007 PrestaShop SA and Contributors - * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) - */ - -#product_comments_block_extra { - padding:10px 0 0 0; - border-top:1px solid #ccc; - font-weight: bold; - font-size:12px; - line-height:18px -} - -#product_comments_block_extra a { - padding-left: 10px; - text-decoration: none; - background: url(img/bg_li.png) no-repeat scroll 1px 45% #fff; - -} - -#product_comments_block_extra a:hover {text-decoration: underline} - -#product_comments_block_extra .comments-note {margin-bottom:5px} -#product_comments_block_extra .comments-note span, -#product_comments_block_extra .star-content {float:left} -#product_comments_block_extra .star-content {margin-top:2px} - -#product_comments_block_extra div.star {background: url(img/star.gif) no-repeat scroll 0 0 transparent} - -#product_comments_block_extra div.star_on {background: url(img/star.gif) no-repeat scroll 0 -12px transparent} - -#product_comments_block_extra .comments_advices {clear:both;} - -/* pop-in add grade/advice ********************************************************************* */ -#fancybox-wrap { width:585px } -#fancybox-content { - width:585px; - border-width:0 -} - -#new_comment_form { - width:585px; - color: #333; - text-align: left; - background-color: #fff -} -#new_comment_form .title { - padding:10px; - font-size: 13px; - color: #fff; - text-transform: uppercase; - background: #333 -} -#new_comment_form ul.grade_content {list-style-type:none} -#new_comment_form .grade_content li {width:50%} -#new_comment_form .product {padding:15px} -#new_comment_form .product img { - float:left; - border: 1px solid #ccc; -} -#new_comment_form .product .product_desc { - float:left; - margin-left:15px; - width:300px; - line-height:18px; - color:#666 -} -#new_comment_form .product .product_desc .product_name { - padding-bottom:5px; - font-size:13px; - color:#000 -} - -#new_comment_form .grade_content {margin:0 0 20px 0} -#new_comment_form .grade_content span, -#new_comment_form .grade_content span { - display:inline-block; - padding:0 10px; - width:150px;/* 160 */ - font-weight:bold -} -#new_comment_form .grade_content .cancel {margin-right:5px} - -.new_comment_form_content { - padding:15px; - background:#f8f8f8 -} -.new_comment_form_content .intro_form { - padding-bottom: 10px; - font-weight: bold; - font-size: 12px -} - -#new_comment_form label { - display: block; - margin:12px 0 4px 0; - font-weight: bold; - font-size: 12px; -} -#new_comment_form input { - padding: 0 5px; - height: 28px; - width: 540px; - border: 1px solid #ccc; - background: #fff; -} -#new_comment_form textarea { - padding: 0 5px; - height: 80px; - width: 540px; - border: 1px solid #ccc; - background: #fff; -} - -#new_comment_form .submit { - margin-top:20px; - padding:0; - font-size:13px; - text-align:right -} -#new_comment_form button { - cursor: pointer; - cursor: pointer; - display: inline-block; - padding: 4px 7px 3px 7px; - border: 1px solid #CC9900; - border-radius: 3px 3px 3px 3px; - font-weight: bold; - color: #000; - background: url(img/bg_bt.gif) repeat-x scroll 0 0 #F4B61B -} - -#new_comment_form #criterions_list { - border-bottom: 1px solid #CCC; - padding-bottom: 15px; - list-style-type: none; -} - -#new_comment_form #criterions_list li { - margin-bottom: 10px; -} - -#new_comment_form #criterions_list label { - display: inline; - float: left; - margin: 0 0 0 60px; -} - -#new_comment_form #criterions_list .star-content { - float: right; - margin-right: 180px; -} - -#new_comment_form #new_comment_form_footer { - margin-top: 20px; - font-size: 12px; -} - -/* TAB COMMENTS ******************************************************************************** */ -#product_comments_block_tab {margin:0 0 20px 0} - -#product_comments_block_tab div.comment { - margin:0 0 10px 0; - padding: 5px; - border-bottom: 1px dotted #ccc -} - -#product_comments_block_tab div.comment div.comment_author { - float: left; - padding-right:25px; - width: 140px;/* 165 */ - line-height:18px -} -#product_comments_block_tab div.comment div.comment_author span {font-weight:bold;} -#product_comments_block_tab div.comment div.comment_author span, -#product_comments_block_tab div.comment .star-content { - float:left; -} -#product_comments_block_tab div.comment .star-content {margin: 0 0 0 5px} -#product_comments_block_tab div.star, -#product_comments_block_tab div.star_on { - background: url(img/star.gif) no-repeat 0 0 transparent -} -#product_comments_block_tab div.star_on {background-position: 0 -12px} -#product_comments_block_tab .comment_author_infos {clear:both} -#product_comments_block_tab .comment_author_infos em {color:#999} - -#product_comments_block_tab div.comment div.comment_details { - float: left; - overflow:hidden; - width: 360px -} -#product_comments_block_tab div.comment_details .title_block, #product_comments_block_tab div.comment_details h4 {padding-bottom:10px} -#product_comments_block_tab div.comment_details p {padding-bottom:10px} -#product_comments_block_tab div.comment_details ul { - list-style-type:none; - margin:0 -} -#product_comments_block_tab div.comment_details li { - padding:2px 0 2px 12px; - background:url(img/bg_li.png) no-repeat 1px 45% #fff -} - -#product_comments_block_tab a { - text-decoration: none; - font-weight: bold -} - -#product_comments_block_tab a:hover {text-decoration: underline} - -#product_comments_block_tab button.usefulness_btn { - cursor: pointer; - margin:0 0 0 5px; - display: inline-block; - padding: 0 2px; - border: 1px solid #CC9900; - border-radius: 3px 3px 3px 3px; - color: #000; - font-weight: bold; - background: url("img/bg_bt.gif") repeat-x scroll 0 0 #F4B61B -} -#product_comments_block_tab button.usefulness_btn:hover {background-position: left -50px} -#product_comments_block_tab button.usefulness_btn:active {background-position: left -100px} - -#product_comments_block_tab span.report_btn {cursor: pointer} -#product_comments_block_tab span.report_btn:hover {text-decoration:underline} - -.fl { float: left; } -.fr { float: right; } diff --git a/productcomments.php b/productcomments.php index fb9ee754..dd09373e 100644 --- a/productcomments.php +++ b/productcomments.php @@ -28,8 +28,7 @@ exit; } -use PrestaShop\Module\ProductComment\Repository\ProductCommentCriterionRepository; -use PrestaShop\Module\ProductComment\Repository\ProductCommentRepository; +use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; use PrestaShop\PrestaShop\Core\Module\WidgetInterface; class ProductComments extends Module implements WidgetInterface @@ -41,11 +40,14 @@ class ProductComments extends Module implements WidgetInterface private $_productCommentsCriterionTypes = []; private $_baseUrl; + private $langId; + private $shopId; + public function __construct() { $this->name = 'productcomments'; $this->tab = 'front_office_features'; - $this->version = '5.0.3'; + $this->version = '6.0.0'; $this->author = 'PrestaShop'; $this->need_instance = 0; $this->bootstrap = true; @@ -55,7 +57,10 @@ public function __construct() $this->displayName = $this->trans('Product Comments', [], 'Modules.Productcomments.Admin'); $this->description = $this->trans('Allow users to post reviews on your products and/or rate them based on specific criteria.', [], 'Modules.Productcomments.Admin'); - $this->ps_versions_compliancy = ['min' => '1.7.6', 'max' => _PS_VERSION_]; + $this->langId = $this->context->language->id; + $this->shopId = $this->context->shop->id ? $this->context->shop->id : Configuration::get('PS_SHOP_DEFAULT'); + + $this->ps_versions_compliancy = ['min' => '1.7.7', 'max' => _PS_VERSION_]; } public function install($keep = true) @@ -163,6 +168,10 @@ public function getCacheId($id_product = null) protected function _postProcess() { + $id_product_comment = (int) Tools::getValue('id_product_comment'); + $commentRepository = $this->get('product_comment_repository'); + $criterionRepository = $this->get('product_comment_criterion_repository'); + if (Tools::isSubmit('submitModerate')) { $errors = []; $productCommentsMinimalTime = Tools::getValue('PRODUCT_COMMENTS_MINIMAL_TIME'); @@ -193,76 +202,49 @@ protected function _postProcess() $this->_html .= $this->displayConfirmation($this->trans('Settings updated', [], 'Modules.Productcomments.Admin')); } } elseif (Tools::isSubmit('productcomments')) { - $id_product_comment = (int) Tools::getValue('id_product_comment'); - $comment = new ProductComment($id_product_comment); - $comment->validate(); - ProductComment::deleteReports($id_product_comment); + $comment = $commentRepository->find($id_product_comment); + $commentRepository->validate($comment, 1); + $commentRepository->deleteReports($id_product_comment); } elseif (Tools::isSubmit('deleteproductcomments')) { - $id_product_comment = (int) Tools::getValue('id_product_comment'); - $comment = new ProductComment($id_product_comment); - $comment->delete(); + $comment = $commentRepository->find($id_product_comment); + $commentRepository->delete($comment); } elseif (Tools::isSubmit('submitEditCriterion')) { - $criterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion')); - $criterion->id_product_comment_criterion_type = (int) Tools::getValue('id_product_comment_criterion_type'); - $criterion->active = Tools::getValue('active'); + $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion')); + $criterion->setType((int) Tools::getValue('id_product_comment_criterion_type')); + $criterion->setActive(Tools::getValue('active')); $languages = Language::getLanguages(); $name = []; foreach ($languages as $key => $value) { $name[$value['id_lang']] = Tools::getValue('name_' . $value['id_lang']); } - $criterion->name = $name; + $criterion->setNames($name); - if (!$criterion->validateFields(false) || !$criterion->validateFieldsLang(false)) { + if (!$criterion->isValid()) { $this->_html .= $this->displayError($this->trans('The criterion cannot be saved', [], 'Modules.Productcomments.Admin')); } else { - $criterion->save(); - - // Clear before reinserting data - $criterion->deleteCategories(); - $criterion->deleteProducts(); - if ($criterion->id_product_comment_criterion_type == 2) { - if ($categories = Tools::getValue('categoryBox')) { - if (count($categories)) { - foreach ($categories as $id_category) { - $criterion->addCategory((int) $id_category); - } - } - } - } elseif ($criterion->id_product_comment_criterion_type == 3) { - if ($products = Tools::getValue('ids_product')) { - if (count($products)) { - foreach ($products as $product) { - $criterion->addProduct((int) $product); - } - } - } - } - if ($criterion->save()) { + $criterion->setCategories(Tools::getValue('categoryBox')); + $criterion->setProducts(Tools::getValue('ids_product')); + if ($criterionRepository->update($criterion)) { Tools::redirectAdmin(Context::getContext()->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name, 'conf' => 4])); } else { $this->_html .= $this->displayError($this->trans('The criterion cannot be saved', [], 'Modules.Productcomments.Admin')); } } } elseif (Tools::isSubmit('deleteproductcommentscriterion')) { - $productCommentCriterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion')); - if ($productCommentCriterion->id) { - if ($productCommentCriterion->delete()) { - $this->_html .= $this->displayConfirmation($this->trans('Criterion deleted', [], 'Modules.Productcomments.Admin')); - } + $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion')); + if ($criterionRepository->delete($criterion)) { + $this->_html .= $this->displayConfirmation($this->trans('Criterion deleted', [], 'Modules.Productcomments.Admin')); } } elseif (Tools::isSubmit('statusproductcommentscriterion')) { - $criterion = new ProductCommentCriterion((int) Tools::getValue('id_product_comment_criterion')); - if ($criterion->id) { - $criterion->active = (int) (!$criterion->active); - $criterion->save(); - } + $criterion = $criterionRepository->findRelation((int) Tools::getValue('id_product_comment_criterion')); + $criterion->setActive(!$criterion->isActive()); Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name, 'tab_module' => $this->tab, 'conf' => 4, 'module_name' => $this->name])); } elseif ($id_product_comment = (int) Tools::getValue('approveComment')) { - $comment = new ProductComment($id_product_comment); - $comment->validate(); + $comment = $commentRepository->find($id_product_comment); + $commentRepository->validate($comment, 1); } elseif ($id_product_comment = (int) Tools::getValue('noabuseComment')) { - ProductComment::deleteReports($id_product_comment); + $commentRepository->deleteReports($id_product_comment); Tools::redirectAdmin($this->context->link->getAdminLink('AdminModules', true, [], ['configure' => $this->name])); } @@ -271,9 +253,6 @@ protected function _postProcess() public function getContent() { - include_once dirname(__FILE__) . '/ProductComment.php'; - include_once dirname(__FILE__) . '/ProductCommentCriterion.php'; - $this->_html = ''; if (Tools::isSubmit('updateproductcommentscriterion')) { $this->_html .= $this->renderCriterionForm((int) Tools::getValue('id_product_comment_criterion')); @@ -286,7 +265,7 @@ public function getContent() } $this->_setBaseUrl(); - $this->_productCommentsCriterionTypes = ProductCommentCriterion::getTypes(); + $this->_productCommentsCriterionTypes = $this->get('product_comment_criterion_repository')->getTypes(); $this->context->controller->addJs($this->_path . 'js/moderate.js'); @@ -423,7 +402,7 @@ public function renderConfigForm() $helper->tpl_vars = [ 'fields_value' => $this->getConfigFieldsValues(), 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id, + 'id_language' => $this->langId, ]; return $helper->generateForm([$fields_form_1]); @@ -432,9 +411,10 @@ public function renderConfigForm() public function renderModerateLists() { $return = null; + $commentRepository = $this->get('product_comment_repository'); if (Configuration::get('PRODUCT_COMMENTS_MODERATE')) { - $comments = ProductComment::getByValidate(0, false); + $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 0, false); $fields_list = $this->getStandardFieldList(); @@ -459,7 +439,7 @@ public function renderModerateLists() $return .= $helper->generateList($comments, $fields_list); } - $comments = ProductComment::getReportedComments(); + $comments = $commentRepository->getReportedComments($this->langId, $this->shopId); $fields_list = $this->getStandardFieldList(); @@ -526,7 +506,7 @@ public function displayNoabuseLink($token, $id, $name = null) public function renderCriterionList() { - $criterions = ProductCommentCriterion::getCriterions($this->context->language->id, false, false); + $criterions = $this->get('product_comment_criterion_repository')->getCriterions($this->langId, false, false); $fields_list = [ 'id_product_comment_criterion' => [ @@ -586,16 +566,17 @@ public function renderCommentsList() $helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name; $helper->no_link = true; - $page = ($page = Tools::getValue('submitFilter' . $helper->list_id)) ? $page : 1; - $pagination = ($pagination = Tools::getValue($helper->list_id . '_pagination')) ? $pagination : 50; + $page = ($page = Tools::getValue('submitFilter' . $helper->list_id)) ? (int) $page : 1; + $pagination = ($pagination = Tools::getValue($helper->list_id . '_pagination')) ? (int) $pagination : 50; $moderate = Configuration::get('PRODUCT_COMMENTS_MODERATE'); + $commentRepository = $this->get('product_comment_repository'); if (empty($moderate)) { - $comments = ProductComment::getByValidate(0, false, (int) $page, (int) $pagination, true); - $count = (int) ProductComment::getCountByValidate(0, true); + $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 0, false, $page, $pagination, true); + $count = $commentRepository->getCountByValidate(0, true); } else { - $comments = ProductComment::getByValidate(1, false, (int) $page, (int) $pagination); - $count = (int) ProductComment::getCountByValidate(1); + $comments = $commentRepository->getByValidate($this->langId, $this->shopId, 1, false, $page, $pagination); + $count = $commentRepository->getCountByValidate(1); } $helper->listTotal = $count; @@ -617,13 +598,14 @@ public function getConfigFieldsValues() public function getCriterionFieldsValues($id = 0) { - $criterion = new ProductCommentCriterion($id); + $criterionRepos = $this->get('product_comment_criterion_repository'); + $criterion = $criterionRepos->findRelation($id); return [ - 'name' => $criterion->name, - 'id_product_comment_criterion_type' => $criterion->id_product_comment_criterion_type, - 'active' => $criterion->active, - 'id_product_comment_criterion' => $criterion->id, + 'name' => $criterion->getNames(), + 'id_product_comment_criterion_type' => $criterion->getType(), + 'active' => $criterion->isActive(), + 'id_product_comment_criterion' => $criterion->getId(), ]; } @@ -703,7 +685,7 @@ public function renderAuthorName($value, $row) public function renderCriterionForm($id_criterion = 0) { - $types = ProductCommentCriterion::getTypes(); + $types = $this->get('product_comment_criterion_repository')->getTypes(); $query = []; foreach ($types as $key => $value) { $query[] = [ @@ -712,11 +694,14 @@ public function renderCriterionForm($id_criterion = 0) ]; } - $criterion = new ProductCommentCriterion((int) $id_criterion); - $selected_categories = $criterion->getCategories(); + $criterionRepository = $this->get('product_comment_criterion_repository'); + + $criterion = $criterionRepository->findRelation($id_criterion); + $selected_categories = $criterionRepository->getCategories($id_criterion); + + $product_table_values = Product::getSimpleProducts($this->langId); + $selected_products = $criterionRepository->getProducts($id_criterion); - $product_table_values = Product::getSimpleProducts($this->context->language->id); - $selected_products = $criterion->getProducts(); foreach ($product_table_values as $key => $product) { if (false !== array_search($product['id_product'], $selected_products)) { $product_table_values[$key]['selected'] = 1; @@ -830,7 +815,7 @@ public function renderCriterionForm($id_criterion = 0) $helper->tpl_vars = [ 'fields_value' => $this->getCriterionFieldsValues($id_criterion), 'languages' => $this->context->controller->getLanguages(), - 'id_language' => $this->context->language->id, + 'id_language' => $this->langId, ]; return $helper->generateForm([$fields_form_1]); @@ -846,8 +831,9 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) if ($id_criterion == 0) { $selected_cat = []; } else { - $pdc_object = new ProductCommentCriterion($id_criterion); - $selected_cat = $pdc_object->getCategories(); + $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterion = $criterionRepository->find((int) $id_criterion); + $selected_cat = $criterionRepository->getCategories($criterion); } if (Shop::getContext() == Shop::CONTEXT_SHOP && Tools::isSubmit('id_shop')) { @@ -855,7 +841,7 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) } else { $root_category = new Category($id_root); } - $root_category = ['id_category' => $root_category->id, 'name' => $root_category->name[$this->context->language->id]]; + $root_category = ['id_category' => $root_category->id, 'name' => $root_category->name[$this->langId]]; $helper = new Helper(); @@ -865,8 +851,7 @@ public function initCategoriesAssociation($id_root = null, $id_criterion = 0) public function hookActionDeleteGDPRCustomer($customer) { if (isset($customer['id'])) { - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); + $productCommentRepository = $this->get('product_comment_repository'); $productCommentRepository->cleanCustomerData($customer['id']); } @@ -876,9 +861,8 @@ public function hookActionDeleteGDPRCustomer($customer) public function hookActionExportGDPRData($customer) { if (isset($customer['id'])) { - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - $langId = isset($customer['id_lang']) ? $customer['id_lang'] : $this->context->language->id; + $productCommentRepository = $this->get('product_comment_repository'); + $langId = isset($customer['id_lang']) ? $customer['id_lang'] : $this->langId; return json_encode($productCommentRepository->getCustomerData($customer['id'], $langId)); } @@ -898,7 +882,6 @@ public function hookDisplayHeader() if ($this->context->controller instanceof ProductControllerCore) { $jsList[] = '/modules/productcomments/views/js/post-comment.js'; $jsList[] = '/modules/productcomments/views/js/list-comments.js'; - $jsList[] = '/modules/productcomments/views/js/jquery.simplePagination.js'; } foreach ($cssList as $cssUrl) { $this->context->controller->registerStylesheet(sha1($cssUrl), $cssUrl, ['media' => 'all', 'priority' => 80]); @@ -935,11 +918,9 @@ public function hookFilterProductContent(array $params) if (empty($params['object']->id)) { return $params; } - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - - $averageRating = $productCommentRepository->getAverageGrade($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); - $nbComments = $productCommentRepository->getCommentsNumber($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $commentRepository = $this->get('product_comment_repository'); + $averageRating = $commentRepository->getAverageGrade($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $nbComments = $commentRepository->getCommentsNumber($params['object']->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); /* @phpstan-ignore-next-line */ $params['object']->productComments = [ @@ -962,12 +943,17 @@ public function hookFilterProductContent(array $params) */ private function renderProductCommentsList($product) { - /** @var ProductCommentRepository $productCommentRepository */ - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - - $averageGrade = $productCommentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); - $commentsNb = $productCommentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); - $isPostAllowed = $productCommentRepository->isPostAllowed($product->id, (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); + $commentRepository = $this->get('product_comment_repository'); + $averageGrade = $commentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $commentsNb = $commentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $isPostAllowed = $commentRepository->isPostAllowed($product->id, (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); + + /* configure pagination */ + $commentsTotalPages = 0; + $commentsPerPage = (int) Configuration::get('PRODUCT_COMMENTS_COMMENTS_PER_PAGE'); + if ($commentsNb > 0) { + $commentsTotalPages = ceil($commentsNb / $commentsPerPage); + } $this->context->smarty->assign([ 'post_allowed' => $isPostAllowed, @@ -987,6 +973,7 @@ private function renderProductCommentsList($product) 'productcomments', 'ReportComment' ), + 'list_total_pages' => $commentsTotalPages, ]); return $this->context->smarty->fetch('module:productcomments/views/templates/hook/product-comments-list.tpl'); @@ -1004,9 +991,8 @@ private function renderProductCommentsList($product) */ private function renderProductCommentModal($product) { - /** @var ProductCommentCriterionRepository $criterionRepository */ - $criterionRepository = $this->context->controller->getContainer()->get('product_comment_criterion_repository'); - $criterions = $criterionRepository->getByProduct($product->id, $this->context->language->id); + $criterionRepository = $this->get('product_comment_criterion_repository'); + $criterions = $criterionRepository->getByProduct($product->id, $this->langId); $this->context->smarty->assign([ 'logged' => (bool) $this->context->cookie->id_customer, @@ -1026,10 +1012,10 @@ private function renderProductCommentModal($product) public function getWidgetVariables($hookName = null, array $configuration = []) { - $productCommentRepository = $this->context->controller->getContainer()->get('product_comment_repository'); - $averageGrade = $productCommentRepository->getAverageGrade($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); - $commentsNb = $productCommentRepository->getCommentsNumber($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); - $isPostAllowed = $productCommentRepository->isPostAllowed($configuration['id_product'], (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); + $commentRepository = $this->get('product_comment_repository'); + $averageGrade = $commentRepository->getAverageGrade($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $commentsNb = $commentRepository->getCommentsNumber($configuration['id_product'], Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $isPostAllowed = $commentRepository->isPostAllowed($configuration['id_product'], (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); return [ 'average_grade' => $averageGrade, diff --git a/src/Entity/ProductCommentCriterion.php b/src/Entity/ProductCommentCriterion.php index b3ea724b..b2421472 100644 --- a/src/Entity/ProductCommentCriterion.php +++ b/src/Entity/ProductCommentCriterion.php @@ -27,6 +27,8 @@ namespace PrestaShop\Module\ProductComment\Entity; use Doctrine\ORM\Mapping as ORM; +use Language; +use Validate; /** * @ORM\Table() @@ -34,6 +36,7 @@ */ class ProductCommentCriterion { + const NAME_MAX_LENGTH = 64; const ENTIRE_CATALOG_TYPE = 1; const CATEGORIES_TYPE = 2; const PRODUCTS_TYPE = 3; @@ -61,6 +64,95 @@ class ProductCommentCriterion */ private $active = false; + /** + * @var array + * + * Need to be implemented as ORM\OneToMany in the future + */ + private $names; + + /** + * @var array + * + * Need to be implemented as ORM\OneToMany in the future + */ + private $categories; + + /** + * @var array + * + * Need to be implemented as ORM\OneToMany in the future + */ + private $products; + + public function __construct() + { + $langIsoIds = Language::getIsoIds(); + foreach ($langIsoIds as $langIsoId) { + $this->names[$langIsoId['id_lang']] = $langIsoId['iso_code']; + } + } + + /** + * @return array + */ + public function getNames() + { + return $this->names; + } + + /** + * @param array $langNames + * + * @return ProductCommentCriterion + */ + public function setNames($langNames) + { + $this->names = $langNames; + + return $this; + } + + /** + * @return array + */ + public function getCategories() + { + return $this->categories; + } + + /** + * @param array $selectedCategories + * + * @return ProductCommentCriterion + */ + public function setCategories($selectedCategories) + { + $this->categories = $selectedCategories; + + return $this; + } + + /** + * @return array + */ + public function getProducts() + { + return $this->products; + } + + /** + * @param array $selectedProducts + * + * @return ProductCommentCriterion + */ + public function setProducts($selectedProducts) + { + $this->products = $selectedProducts; + + return $this; + } + /** * @return int */ @@ -108,4 +200,18 @@ public function setActive($active) return $this; } + + /** + * @return bool + */ + public function isValid() + { + foreach ($this->names as $value) { + if (!Validate::isGenericName($value)) { + return false; + } + } + + return true; + } } diff --git a/src/Repository/ProductCommentCriterionRepository.php b/src/Repository/ProductCommentCriterionRepository.php index 41f5fa5c..7446f671 100644 --- a/src/Repository/ProductCommentCriterionRepository.php +++ b/src/Repository/ProductCommentCriterionRepository.php @@ -26,12 +26,28 @@ namespace PrestaShop\Module\ProductComment\Repository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use PrestaShop\Module\ProductComment\Entity\ProductCommentCriterion; +use PrestaShop\PrestaShop\Adapter\SymfonyContainer; -class ProductCommentCriterionRepository +/** + * @extends ServiceEntityRepository + * + * @method ProductCommentCriterion|null find($id, $lockMode = null, $lockVersion = null) + * @method ProductCommentCriterion|null findOneBy(array $criteria, array $orderBy = null) + * @method ProductCommentCriterion[] findAll() + * @method ProductCommentCriterion[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ProductCommentCriterionRepository extends ServiceEntityRepository { + /** + * @var ManagerRegistry the Doctrine Registry + */ + private $registry; + /** * @var Connection the Database connection */ @@ -43,15 +59,164 @@ class ProductCommentCriterionRepository private $databasePrefix; /** + * @param ManagerRegistry $registry * @param Connection $connection * @param string $databasePrefix */ - public function __construct(Connection $connection, $databasePrefix) + public function __construct($registry, $connection, $databasePrefix) { + parent::__construct($registry, ProductCommentCriterion::class); $this->connection = $connection; $this->databasePrefix = $databasePrefix; } + public function add(ProductCommentCriterion $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(ProductCommentCriterion $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + private function deleteLangs($criterion): int + { + return $this->connection->executeUpdate(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_lang` + WHERE `id_product_comment_criterion` = ' . $criterion->getId()); + } + + private function deleteCategories($criterion): int + { + return $this->connection->executeUpdate(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_category` + WHERE `id_product_comment_criterion` = ' . $criterion->getId()); + } + + private function deleteProducts($criterion): int + { + return $this->connection->executeUpdate(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_product` + WHERE `id_product_comment_criterion` = ' . $criterion->getId()); + } + + private function deleteGrades($criterion): int + { + return $this->connection->executeUpdate(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_criterion_grade` + WHERE `id_product_comment_criterion` = ' . $criterion->getId()); + } + + /* Remove a criterion and Delete its manual relation _lang, _category, _product, _grade */ + public function delete(ProductCommentCriterion $criterion): int + { + $res = 0; + + $criterionType = $criterion->getType(); + + $this->remove($criterion, true); + + $res += $this->deleteLangs($criterion); + + if ($criterionType == ProductCommentCriterion::CATEGORIES_TYPE) { + $res += $this->deleteCategories($criterion); + } elseif ($criterionType == ProductCommentCriterion::PRODUCTS_TYPE) { + $res += $this->deleteProducts($criterion); + } + + $res += $this->deleteGrades($criterion); + + return $res; + } + + /* Update a criterion and Update its manual relation _lang, _category, _product, _grade */ + public function update(ProductCommentCriterion $criterion): int + { + $res = 0; + + $criterionType = $criterion->getType(); + + $this->getEntityManager()->persist($criterion); + $this->getEntityManager()->flush(); + + $res += $this->deleteLangs($criterion); + $res += $this->updateLangs($criterion); + + if ($criterionType == ProductCommentCriterion::CATEGORIES_TYPE) { + $res += $this->deleteCategories($criterion); + $res += $this->updateCategories($criterion); + } elseif ($criterionType == ProductCommentCriterion::PRODUCTS_TYPE) { + $res += $this->deleteProducts($criterion); + $res += $this->updateProducts($criterion); + } + + return $res; + } + + private function updateLangs($criterion): int + { + $res = 0; + $criterionId = $criterion->getId(); + foreach ($criterion->getNames() as $key => $value) { + $qb = $this->connection->createQueryBuilder(); + $qb + ->insert(_DB_PREFIX_ . 'product_comment_criterion_lang') + ->values( + [ + 'id_product_comment_criterion' => '?', + 'id_lang' => '?', + 'name' => '?', + ] + ) + ->setParameter(0, $criterionId) + ->setParameter(1, $key) + ->setParameter(2, $value) + ; + $res += $this->connection->executeUpdate($qb->getSQL(), $qb->getParameters(), $qb->getParameterTypes()); + } + + return $res; + } + + private function updateCategories($criterion): int + { + $res = 0; + $criterionId = $criterion->getId(); + foreach ($criterion->getCategories() as $id_category) { + $res += $this->connection->executeUpdate( + 'INSERT INTO `' . + _DB_PREFIX_ . 'product_comment_criterion_category` (`id_product_comment_criterion`, `id_category`) + VALUES(' . $criterionId . ',' . $id_category . ')' + ); + } + + return $res; + } + + private function updateProducts($criterion): int + { + $res = 0; + $criterionId = $criterion->getId(); + foreach ($criterion->getProducts() as $id_product) { + $res += $this->connection->executeUpdate( + 'INSERT INTO `' . + _DB_PREFIX_ . 'product_comment_criterion_product` (`id_product_comment_criterion`, `id_product`) + VALUES(' . $criterionId . ',' . $id_product . ')' + ); + } + + return $res; + } + /** * @param int $idProduct * @param int $idLang @@ -88,4 +253,116 @@ public function getByProduct($idProduct, $idLang) return $qb->execute()->fetchAll(); } + + /** + * Get Criterions + * + * @return array Criterions + */ + public function getCriterions($id_lang, $type = false, $active = false) + { + $sql = ' + SELECT pcc.`id_product_comment_criterion`, pcc.id_product_comment_criterion_type, pccl.`name`, pcc.active + FROM `' . _DB_PREFIX_ . 'product_comment_criterion` pcc + JOIN `' . _DB_PREFIX_ . 'product_comment_criterion_lang` pccl ON (pcc.id_product_comment_criterion = pccl.id_product_comment_criterion) + WHERE pccl.`id_lang` = ' . $id_lang . ($active ? ' AND active = 1' : '') . ($type ? ' AND id_product_comment_criterion_type = ' . (int) $type : '') . ' + ORDER BY pccl.`name` ASC'; + $criterions = $this->connection->executeQuery($sql)->fetchAll(); + + $types = self::getTypes(); + foreach ($criterions as $key => $data) { + $criterions[$key]['type_name'] = $types[$data['id_product_comment_criterion_type']]; + } + + return $criterions; + } + + /** + * @param int $id_criterion + * + * @return array + */ + public function getProducts(int $id_criterion) + { + $sql = ' + SELECT pccp.id_product, pccp.id_product_comment_criterion + FROM `' . _DB_PREFIX_ . 'product_comment_criterion_product` pccp + WHERE pccp.id_product_comment_criterion = ' . $id_criterion; + + $res = $this->connection->executeQuery($sql)->fetchAll(); + + $products = []; + if ($res) { + foreach ($res as $row) { + $products[] = (int) $row['id_product']; + } + } + + return $products; + } + + /** + * @param int $id_criterion + * + * @return array + */ + public function getCategories(int $id_criterion) + { + $sql = ' + SELECT pccc.id_category, pccc.id_product_comment_criterion + FROM `' . _DB_PREFIX_ . 'product_comment_criterion_category` pccc + WHERE pccc.id_product_comment_criterion = ' . $id_criterion; + + $res = $this->connection->executeQuery($sql)->fetchAll(); + + $criterions = []; + if ($res) { + foreach ($res as $row) { + $criterions[] = (int) $row['id_category']; + } + } + + return $criterions; + } + + /** + * @return array + */ + public function getTypes() + { + $sfTranslator = SymfonyContainer::getInstance()->get('translator'); + + return [ + 1 => $sfTranslator->trans('Valid for the entire catalog', [], 'Modules.Productcomments.Admin'), + 2 => $sfTranslator->trans('Restricted to some categories', [], 'Modules.Productcomments.Admin'), + 3 => $sfTranslator->trans('Restricted to some products', [], 'Modules.Productcomments.Admin'), + ]; + } + + /** + * Get Criterion with names in active languages + * + * @return ProductCommentCriterion + */ + public function findRelation($id_criterion) + { + if ($id_criterion > 0) { + $criterion = $this->find($id_criterion); + $sql = ' + SELECT `id_lang`, `name` + FROM `' . _DB_PREFIX_ . 'product_comment_criterion_lang` pccl + WHERE pccl.id_product_comment_criterion = ' . $id_criterion . ' + ORDER BY pccl.`id_lang` ASC'; + $langNames = $this->connection->executeQuery($sql)->fetchAll(); + $langArray = []; + foreach ($langNames as $langName) { + $langArray[$langName['id_lang']] = $langName['name']; + } + $criterion->setNames($langArray); + } else { + $criterion = new ProductCommentCriterion(); + } + + return $criterion; + } } diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php index a1e0d1a3..88db9688 100644 --- a/src/Repository/ProductCommentRepository.php +++ b/src/Repository/ProductCommentRepository.php @@ -26,11 +26,28 @@ namespace PrestaShop\Module\ProductComment\Repository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; +use Hook; +use PrestaShop\Module\ProductComment\Entity\ProductComment; -class ProductCommentRepository +/** + * @extends ServiceEntityRepository + * + * @method ProductComment|null find($id, $lockMode = null, $lockVersion = null) + * @method ProductComment|null findOneBy(array $criteria, array $orderBy = null) + * @method ProductComment[] findAll() + * @method ProductComment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ProductCommentRepository extends ServiceEntityRepository { + /** + * @var ManagerRegistry the Doctrine Registry + */ + private $registry; + /** * @var Connection the Database connection */ @@ -54,23 +71,54 @@ class ProductCommentRepository const DEFAULT_COMMENTS_PER_PAGE = 5; /** + * @param ManagerRegistry $registry * @param Connection $connection * @param string $databasePrefix * @param bool $guestCommentsAllowed * @param int $commentsMinimalTime */ public function __construct( - Connection $connection, + $registry, + $connection, $databasePrefix, $guestCommentsAllowed, $commentsMinimalTime ) { + parent::__construct($registry, ProductComment::class); $this->connection = $connection; $this->databasePrefix = $databasePrefix; $this->guestCommentsAllowed = (bool) $guestCommentsAllowed; $this->commentsMinimalTime = (int) $commentsMinimalTime; } + public function add(ProductComment $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(ProductComment $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function delete(ProductComment $entity): void + { + $entityId = $entity->getId(); + + $this->remove($entity, true); + + $this->deleteGrades($entityId); + $this->deleteReports($entityId); + $this->deleteUsefulness($entityId); + } + /** * @param int $productId * @param int $page @@ -168,7 +216,84 @@ public function getAverageGrade($productId, $validatedOnly) ; } - return (float) $qb->execute()->fetchColumn(); + return (float) $qb->execute()->fetch(\PDO::FETCH_COLUMN); + } + + /** + * @param int $langId + * @param int $shopId + * @param int $validate + * @param bool $deleted + * @param int $page + * @param int $limit + * @param bool $skip_validate + * + * @return array + */ + public function getByValidate($langId, $shopId, $validate = 0, $deleted = false, $page = null, $limit = null, $skip_validate = false) + { + /** @var QueryBuilder $qb */ + $qb = $this->connection->createQueryBuilder(); + $qb + ->select('pc.`id_product_comment`, pc.`id_product`, c.id_customer AS customer_id, + IF(c.id_customer, CONCAT(c.`firstname`, \' \', c.`lastname`), pc.customer_name) customer_name, + pc.`title`, pc.`content`, pc.`grade`, pc.`date_add`, pl.`name`') + ->from($this->databasePrefix . 'product_comment', 'pc') + ->leftJoin('pc', $this->databasePrefix . 'customer', 'c', 'pc.id_customer = c.id_customer') + ->leftJoin('pc', $this->databasePrefix . 'product_lang', 'pl', 'pc.id_product = pl.id_product') + ->andWhere('pc.deleted = :deleted') + ->setParameter('deleted', $deleted) + ->andWhere('pl.id_lang = :id_lang') + ->setParameter('id_lang', $langId) + ->andWhere('pl.id_shop = :id_shop') + ->setParameter('id_shop', $shopId) + ->addOrderBy('pc.date_add', 'DESC') + ; + + if (!$skip_validate) { + $qb + ->andWhere('pc.validate = :validate') + ->setParameter('validate', $validate) + ; + } + if ($page && $limit) { + $limit = (int) $limit; + $offset = ($page - 1) * $limit; + $qb + ->setFirstResult($offset) + ->setMaxResults($limit); + } + + return $this->connection->executeQuery( + $qb->getSQL(), $qb->getParameters(), $qb->getParameterTypes() + )->fetchAll(); + } + + /** + * @param int $validate + * @param bool $skip_validate + * + * @return int + */ + public function getCountByValidate($validate = 0, $skip_validate = false) + { + /** @var QueryBuilder $qb */ + $qb = $this->connection->createQueryBuilder(); + $qb + ->select('COUNT(*)') + ->from($this->databasePrefix . 'product_comment', 'pc') + ; + + if (!$skip_validate) { + $qb + ->andWhere('pc.validate = :validate') + ->setParameter('validate', $validate) + ; + } + + return (int) $this->connection->executeQuery( + $qb->getSQL(), $qb->getParameters(), $qb->getParameterTypes() + )->fetch(\PDO::FETCH_COLUMN); } /** @@ -204,10 +329,7 @@ public function getAverageGrades(array $productIds, $validatedOnly) $sql .= ' FROM ' . $this->databasePrefix . 'product_comment'; - $query = $this->connection->prepare($sql); - $query->execute(); - - return (array) $query->fetch(); + return $this->connection->executeQuery($sql)->fetch(); } /** @@ -236,7 +358,7 @@ public function getCommentsNumber($productId, $validatedOnly) ; } - return (int) $qb->execute()->fetchColumn(); + return (int) $qb->execute()->fetch(\PDO::FETCH_COLUMN); } /** @@ -267,12 +389,7 @@ public function getCommentsNumberForProducts(array $productIds, $validatedOnly) $sql .= ' FROM ' . $this->databasePrefix . 'product_comment'; - // return $sql; - - $query = $this->connection->prepare($sql); - $query->execute(); - - return (array) $query->fetch(); + return (array) $this->connection->executeQuery($sql)->fetch(); } /** @@ -416,4 +533,88 @@ private function getLastComment(array $criteria) return empty($comments) ? [] : $comments[0]; } + + /** + * @param ProductComment $productComment + * @param int $validate + * + * @return bool + */ + public function validate($productComment, $validate = 1) + { + $success = $this->connection->executeUpdate(' + UPDATE `' . _DB_PREFIX_ . 'product_comment` SET + `validate` = ' . $validate . ' + WHERE `id_product_comment` = ' . $productComment->getId()); + + Hook::exec('actionObjectProductCommentValidateAfter', ['object' => $productComment]); + + return (bool) $success; + } + + /** + * @param int $id_product_comment + * + * @return bool + */ + public function deleteGrades($id_product_comment) + { + $success = $this->connection->executeUpdate(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_grade` + WHERE `id_product_comment` = ' . $id_product_comment); + + return (bool) $success; + } + + /** + * @param int $id_product_comment + * + * @return bool + */ + public function deleteReports($id_product_comment) + { + $success = $this->connection->executeUpdate(' + DELETE FROM `' . $this->databasePrefix . 'product_comment_report` + WHERE `id_product_comment` = ' . $id_product_comment); + + return (bool) $success; + } + + /** + * @param int $id_product_comment + * + * @return bool + */ + public function deleteUsefulness($id_product_comment) + { + $success = $this->connection->executeUpdate(' + DELETE FROM `' . _DB_PREFIX_ . 'product_comment_usefulness` + WHERE `id_product_comment` = ' . $id_product_comment); + + return (bool) $success; + } + + /** + * @param int $langId + * @param int $shopId + * + * @return array + */ + public function getReportedComments($langId, $shopId) + { + $sql = 'SELECT DISTINCT(pc.`id_product_comment`), pc.`id_product`, pc.`content`, pc.`grade`, pc.`date_add`, pc.`title` + , IF(c.id_customer, CONCAT(c.`firstname`, \' \', c.`lastname`), pc.customer_name) customer_name, pl.`name` + FROM `' . $this->databasePrefix . 'product_comment_report` pcr + LEFT JOIN `' . $this->databasePrefix . 'product_comment` pc + ON pcr.id_product_comment = pc.id_product_comment + LEFT JOIN `' . $this->databasePrefix . 'customer` c ON (c.`id_customer` = pc.`id_customer`) + LEFT JOIN `' . $this->databasePrefix . 'product_lang` pl ON ' . + '(pl.`id_product` = pc.`id_product` ' . + ' AND pl.`id_lang` = ' . $langId . + ' AND pl.`id_shop` = ' . $shopId . + ') + ORDER BY pc.`date_add` DESC'; + + return $this->connection->executeQuery($sql)->fetchAll(); + } } diff --git a/tests/phpstan/phpstan-1.7.6.neon b/tests/phpstan/phpstan-1.7.6.neon deleted file mode 100644 index 8c1ccec5..00000000 --- a/tests/phpstan/phpstan-1.7.6.neon +++ /dev/null @@ -1,12 +0,0 @@ -includes: - - %currentWorkingDirectory%/tests/phpstan/phpstan.neon - -parameters: - ignoreErrors: - - '#Access to an undefined property Cookie::\$id_customer.#' - - '#Access to an undefined property Cookie::\$id_guest.#' - - '#Access to an undefined property HelperList::\$list_id.#' - - '#Access to an undefined property HelperList::\$shopLinkType.#' - - '#Parameter \#1 \$idCategory of class Category constructor expects null, int given.#' - - '#Parameter \#1 \$value of method ControllerCore::ajaxRender\(\) expects null, string\|false given.#' - - '#Parameter \#2 \$value of static method CacheCore::store\(\) expects string, array\|mysqli_result\|PDOStatement\|resource\|false\|null given.#' diff --git a/tests/phpstan/phpstan-1.7.7.neon b/tests/phpstan/phpstan-1.7.7.neon index 341e5dc8..93399a5a 100644 --- a/tests/phpstan/phpstan-1.7.7.neon +++ b/tests/phpstan/phpstan-1.7.7.neon @@ -8,3 +8,6 @@ parameters: - '#Access to an undefined property HelperList::\$list_id.#' - '#Access to an undefined property HelperList::\$shopLinkType.#' - '#Parameter \#1 \$value of method ControllerCore::ajaxRender\(\) expects null, string\|false given.#' + - + message: '#PHPDoc tag @extends contains generic type [a-zA-Z0-9\\_]+<[a-zA-Z0-9\\_]+> but class [a-zA-Z0-9\\_]+ is not generic.#' + path: ../../src/Repository diff --git a/tests/phpstan/phpstan-1.7.8.neon b/tests/phpstan/phpstan-1.7.8.neon index d29f77ca..e6ad951a 100644 --- a/tests/phpstan/phpstan-1.7.8.neon +++ b/tests/phpstan/phpstan-1.7.8.neon @@ -7,3 +7,6 @@ parameters: - '#Access to an undefined property Cookie::\$id_guest.#' - '#Access to an undefined property HelperList::\$list_id.#' - '#Access to an undefined property HelperList::\$shopLinkType.#' + - + message: '#PHPDoc tag @extends contains generic type [a-zA-Z0-9\\_]+<[a-zA-Z0-9\\_]+> but class [a-zA-Z0-9\\_]+ is not generic.#' + path: ../../src/Repository diff --git a/tests/phpstan/phpstan-8.0.neon b/tests/phpstan/phpstan-8.0.neon new file mode 100644 index 00000000..23b71e8d --- /dev/null +++ b/tests/phpstan/phpstan-8.0.neon @@ -0,0 +1,5 @@ +includes: + - %currentWorkingDirectory%/tests/phpstan/phpstan.neon + +parameters: + ignoreErrors: diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon index 037652f7..0961334b 100644 --- a/tests/phpstan/phpstan.neon +++ b/tests/phpstan/phpstan.neon @@ -10,3 +10,7 @@ parameters: - ../../src/ - ../../upgrade/ level: 5 + ignoreErrors: + - + message: '#Cannot call method [a-zA-Z0-9\\_]+\(\) on object\|false.#' + path: ../../productcomments.php diff --git a/views/css/productcomments.css b/views/css/productcomments.css index ab40df51..106d2808 100644 --- a/views/css/productcomments.css +++ b/views/css/productcomments.css @@ -589,7 +589,7 @@ font-size: 13px; } -@media (min-width: 768px) { +@media (min-width: 960px) { #product-comments-list-footer { position: relative; min-height: 45px; @@ -607,7 +607,7 @@ } } -@media (max-width: 768px) { +@media (max-width: 960px) { #product-comments-list-footer { display: flex; flex-direction: row-reverse; @@ -616,7 +616,7 @@ } } -@media (max-width: 576px) { +@media (max-width: 768px) { #product-comments-list-footer { display: flex; flex-direction: column; @@ -665,3 +665,7 @@ #product-comments-list-pagination ul li.active span { cursor: not-allowed; } + +#product-comments-list-pagination ul li.hidden { + display: none; +} diff --git a/views/js/jquery.simplePagination.js b/views/js/jquery.simplePagination.js deleted file mode 100644 index 1108cdc6..00000000 --- a/views/js/jquery.simplePagination.js +++ /dev/null @@ -1,398 +0,0 @@ -/** -* simplePagination.js v1.6 -* A simple jQuery pagination plugin. -* http://flaviusmatis.github.com/simplePagination.js/ -* -* Copyright 2012, Flavius Matis -* Released under the MIT license. -* http://flaviusmatis.github.com/license.html -*/ - -(function($){ - - var methods = { - init: function(options) { - var o = $.extend({ - items: 1, - itemsOnPage: 1, - pages: 0, - displayedPages: 5, - edges: 2, - currentPage: 0, - useAnchors: true, - hrefTextPrefix: '#page-', - hrefTextSuffix: '', - prevText: 'Prev', - nextText: 'Next', - ellipseText: '…', - ellipsePageSet: true, - cssStyle: 'light-theme', - listStyle: '', - labelMap: [], - selectOnClick: true, - nextAtFront: false, - invertPageOrder: false, - useStartEdge : true, - useEndEdge : true, - onPageClick: function(pageNumber, event) { - // Callback triggered when a page is clicked - // Page number is given as an optional parameter - }, - onInit: function() { - // Callback triggered immediately after initialization - } - }, options || {}); - - var self = this; - - o.pages = o.pages ? o.pages : Math.ceil(o.items / o.itemsOnPage) ? Math.ceil(o.items / o.itemsOnPage) : 1; - if (o.currentPage) - o.currentPage = o.currentPage - 1; - else - o.currentPage = !o.invertPageOrder ? 0 : o.pages - 1; - o.halfDisplayed = o.displayedPages / 2; - - this.each(function() { - self.addClass(o.cssStyle + ' simple-pagination').data('pagination', o); - methods._draw.call(self); - }); - - o.onInit(); - - return this; - }, - - selectPage: function(page) { - methods._selectPage.call(this, page - 1); - return this; - }, - - prevPage: function() { - var o = this.data('pagination'); - if (!o.invertPageOrder) { - if (o.currentPage > 0) { - methods._selectPage.call(this, o.currentPage - 1); - } - } else { - if (o.currentPage < o.pages - 1) { - methods._selectPage.call(this, o.currentPage + 1); - } - } - return this; - }, - - nextPage: function() { - var o = this.data('pagination'); - if (!o.invertPageOrder) { - if (o.currentPage < o.pages - 1) { - methods._selectPage.call(this, o.currentPage + 1); - } - } else { - if (o.currentPage > 0) { - methods._selectPage.call(this, o.currentPage - 1); - } - } - return this; - }, - - getPagesCount: function() { - return this.data('pagination').pages; - }, - - setPagesCount: function(count) { - this.data('pagination').pages = count; - }, - - getCurrentPage: function () { - return this.data('pagination').currentPage + 1; - }, - - destroy: function(){ - this.empty(); - return this; - }, - - drawPage: function (page) { - var o = this.data('pagination'); - o.currentPage = page - 1; - this.data('pagination', o); - methods._draw.call(this); - return this; - }, - - redraw: function(){ - methods._draw.call(this); - return this; - }, - - disable: function(){ - var o = this.data('pagination'); - o.disabled = true; - this.data('pagination', o); - methods._draw.call(this); - return this; - }, - - enable: function(){ - var o = this.data('pagination'); - o.disabled = false; - this.data('pagination', o); - methods._draw.call(this); - return this; - }, - - updateItems: function (newItems) { - var o = this.data('pagination'); - o.items = newItems; - o.pages = methods._getPages(o); - this.data('pagination', o); - methods._draw.call(this); - }, - - updateItemsOnPage: function (itemsOnPage) { - var o = this.data('pagination'); - o.itemsOnPage = itemsOnPage; - o.pages = methods._getPages(o); - this.data('pagination', o); - methods._selectPage.call(this, 0); - return this; - }, - - getItemsOnPage: function() { - return this.data('pagination').itemsOnPage; - }, - - _draw: function() { - var o = this.data('pagination'), - interval = methods._getInterval(o), - i, - tagName; - - methods.destroy.call(this); - - tagName = (typeof this.prop === 'function') ? this.prop('tagName') : this.attr('tagName'); - - var $panel = tagName === 'UL' ? this : $('').appendTo(this); - - // Generate Prev link - if (o.prevText) { - methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage - 1 : o.currentPage + 1, {text: o.prevText, classes: 'prev'}); - } - - // Generate Next link (if option set for at front) - if (o.nextText && o.nextAtFront) { - methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: o.nextText, classes: 'next'}); - } - - // Generate start edges - if (!o.invertPageOrder) { - if (interval.start > 0 && o.edges > 0) { - if(o.useStartEdge) { - var end = Math.min(o.edges, interval.start); - for (i = 0; i < end; i++) { - methods._appendItem.call(this, i); - } - } - if (o.edges < interval.start && (interval.start - o.edges != 1)) { - $panel.append('
  • ' + o.ellipseText + '
  • '); - } else if (interval.start - o.edges == 1) { - methods._appendItem.call(this, o.edges); - } - } - } else { - if (interval.end < o.pages && o.edges > 0) { - if(o.useStartEdge) { - var begin = Math.max(o.pages - o.edges, interval.end); - for (i = o.pages - 1; i >= begin; i--) { - methods._appendItem.call(this, i); - } - } - - if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) { - $panel.append('
  • ' + o.ellipseText + '
  • '); - } else if (o.pages - o.edges - interval.end == 1) { - methods._appendItem.call(this, interval.end); - } - } - } - - // Generate interval links - if (!o.invertPageOrder) { - for (i = interval.start; i < interval.end; i++) { - methods._appendItem.call(this, i); - } - } else { - for (i = interval.end - 1; i >= interval.start; i--) { - methods._appendItem.call(this, i); - } - } - - // Generate end edges - if (!o.invertPageOrder) { - if (interval.end < o.pages && o.edges > 0) { - if (o.pages - o.edges > interval.end && (o.pages - o.edges - interval.end != 1)) { - $panel.append('
  • ' + o.ellipseText + '
  • '); - } else if (o.pages - o.edges - interval.end == 1) { - methods._appendItem.call(this, interval.end); - } - if(o.useEndEdge) { - var begin = Math.max(o.pages - o.edges, interval.end); - for (i = begin; i < o.pages; i++) { - methods._appendItem.call(this, i); - } - } - } - } else { - if (interval.start > 0 && o.edges > 0) { - if (o.edges < interval.start && (interval.start - o.edges != 1)) { - $panel.append('
  • ' + o.ellipseText + '
  • '); - } else if (interval.start - o.edges == 1) { - methods._appendItem.call(this, o.edges); - } - - if(o.useEndEdge) { - var end = Math.min(o.edges, interval.start); - for (i = end - 1; i >= 0; i--) { - methods._appendItem.call(this, i); - } - } - } - } - - // Generate Next link (unless option is set for at front) - if (o.nextText && !o.nextAtFront) { - methods._appendItem.call(this, !o.invertPageOrder ? o.currentPage + 1 : o.currentPage - 1, {text: o.nextText, classes: 'next'}); - } - - if (o.ellipsePageSet && !o.disabled) { - methods._ellipseClick.call(this, $panel); - } - - }, - - _getPages: function(o) { - var pages = Math.ceil(o.items / o.itemsOnPage); - return pages || 1; - }, - - _getInterval: function(o) { - return { - start: Math.ceil(o.currentPage > o.halfDisplayed ? Math.max(Math.min(o.currentPage - o.halfDisplayed, (o.pages - o.displayedPages)), 0) : 0), - end: Math.ceil(o.currentPage > o.halfDisplayed ? Math.min(o.currentPage + o.halfDisplayed, o.pages) : Math.min(o.displayedPages, o.pages)) - }; - }, - - _appendItem: function(pageIndex, opts) { - var self = this, options, $link, o = self.data('pagination'), $linkWrapper = $('
  • '), $ul = self.find('ul'); - - pageIndex = pageIndex < 0 ? 0 : (pageIndex < o.pages ? pageIndex : o.pages - 1); - - options = { - text: pageIndex + 1, - classes: '' - }; - - if (o.labelMap.length && o.labelMap[pageIndex]) { - options.text = o.labelMap[pageIndex]; - } - - options = $.extend(options, opts || {}); - - if (pageIndex == o.currentPage || o.disabled) { - if (o.disabled || options.classes === 'prev' || options.classes === 'next') { - $linkWrapper.addClass('disabled'); - } else { - $linkWrapper.addClass('active'); - } - $link = $('' + (options.text) + ''); - } else { - if (o.useAnchors) { - $link = $('' + (options.text) + ''); - } else { - $link = $('' + (options.text) + ''); - } - $link.click(function(event){ - return methods._selectPage.call(self, pageIndex, event); - }); - } - - if (options.classes) { - $link.addClass(options.classes); - } - - $linkWrapper.append($link); - - if ($ul.length) { - $ul.append($linkWrapper); - } else { - self.append($linkWrapper); - } - }, - - _selectPage: function(pageIndex, event) { - var o = this.data('pagination'); - o.currentPage = pageIndex; - if (o.selectOnClick) { - methods._draw.call(this); - } - return o.onPageClick(pageIndex + 1, event); - }, - - - _ellipseClick: function($panel) { - var self = this, - o = this.data('pagination'), - $ellip = $panel.find('.ellipse'); - $ellip.addClass('clickable').parent().removeClass('disabled'); - $ellip.click(function(event) { - if (!o.disable) { - var $this = $(this), - val = (parseInt($this.parent().prev().text(), 10) || 0) + 1; - $this - .html('') - .find('input') - .focus() - .click(function(event) { - // prevent input number arrows from bubbling a click event on $ellip - event.stopPropagation(); - }) - .keyup(function(event) { - var val = $(this).val(); - if (event.which === 13 && val !== '') { - // enter to accept - if ((val>0)&&(val<=o.pages)) - methods._selectPage.call(self, val - 1); - } else if (event.which === 27) { - // escape to cancel - $ellip.empty().html(o.ellipseText); - } - }) - .bind('blur', function(event) { - var val = $(this).val(); - if (val !== '') { - methods._selectPage.call(self, val - 1); - } - $ellip.empty().html(o.ellipseText); - return false; - }); - } - return false; - }); - } - - }; - - $.fn.pagination = function(method) { - - // Method calling logic - if (methods[method] && method.charAt(0) != '_') { - return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); - } else if (typeof method === 'object' || !method) { - return methods.init.apply(this, arguments); - } else { - $.error('Method ' + method + ' does not exist on jQuery.pagination'); - } - - }; - -})(jQuery); diff --git a/views/js/list-comments.js b/views/js/list-comments.js index 697c9ec6..89bc6c40 100644 --- a/views/js/list-comments.js +++ b/views/js/list-comments.js @@ -32,7 +32,13 @@ jQuery(document).ready(function () { const reportCommentUrl = commentsList.data('report-comment-url'); const commentPrototype = commentsList.data('comment-item-prototype'); - emptyProductComment.hide(); + const pagesListId = '#product-comments-list-pagination'; + const pageIdPrefix = '#pcl_page_'; + const totalPages = commentsList.data('total-pages'); + const prevCount = 0; + const nextCount = totalPages + 1; + const gapText = '…'; + $('.grade-stars').rating(); prestashop.on('updatedProduct', function() { @@ -59,31 +65,80 @@ jQuery(document).ready(function () { reportCommentPostErrorModal.modal('show'); } - function paginateComments(page) { - $.get(commentsListUrl, {page: page}, function(jsonResponse) { - if (jsonResponse.comments && jsonResponse.comments.length > 0) { - populateComments(jsonResponse.comments); - if (jsonResponse.comments_nb > jsonResponse.comments_per_page) { - $('#product-comments-list-pagination').pagination({ - currentPage: page, - items: jsonResponse.comments_nb, - itemsOnPage: jsonResponse.comments_per_page, - cssStyle: '', - prevText: '', - nextText: '', - useAnchors: false, - displayedPages: 2, - onPageClick: paginateComments - }); - } else { - $('#product-comments-list-pagination').hide(); - } - } else { - commentsList.html(''); - emptyProductComment.show(); - commentsList.append(emptyProductComment); + async function fetchComments(page) { + let response = await fetch(commentsListUrl + "&page=" + page); + + if (response.status === 200) { + let data = await response.text(); + populateComments((JSON.parse(data)).comments); + } + } + + $(pagesListId + ' li').on('click', + function() { + let oldCount = commentsList.data('current-page'); + let newCount = $(this).index(); + + if (newCount === prevCount) { // click prev + newCount = oldCount - 1; + if (newCount <= 0) return; } - }); + if (newCount === nextCount) { // click next + newCount = oldCount + 1; + if (newCount >= nextCount) return; + } + + $(`${pageIdPrefix}${oldCount} span`).removeClass('current'); + $(`${pageIdPrefix}${oldCount}`).removeClass('active'); + + fetchComments(newCount); // fetch new page's comments + + $(`${pageIdPrefix}${newCount}`).addClass('active'); + $(`${pageIdPrefix}${newCount} span`).addClass('current'); + + $(`${pageIdPrefix}${newCount} span`).html(newCount); + commentsList.data('current-page', newCount); + + if (newCount === 1) // disable prev + $(`${pageIdPrefix}${prevCount}`).addClass('disabled'); + else + $(`${pageIdPrefix}${prevCount}`).removeClass('disabled'); + + if (newCount === totalPages) // disable next + $(`${pageIdPrefix}${nextCount}`).addClass('disabled'); + else + $(`${pageIdPrefix}${nextCount}`).removeClass('disabled'); + + // long list with over 9 pages + if (9 <= totalPages) { + generateGap(newCount, prevCount); + generateGap(newCount, nextCount); + } + } + ) + + function generateGap(start, stop) { + if (start == stop) + return 0; + let step = (start < stop) ? +1 : -1; + let i = start + step; + if (4 < Math.abs(stop - start)) { + $(`${pageIdPrefix}${i}`).removeClass('hidden').removeClass('disabled'); + $(`${pageIdPrefix}${i} span`).html(i); + i = i + step; + $(`${pageIdPrefix}${i}`).removeClass('hidden').removeClass('disabled'); + $(`${pageIdPrefix}${i} span`).html(gapText); + i = i + step; + for (; i != stop - 2*step; i = i + step) { + $(`${pageIdPrefix}${i}`).addClass('hidden'); + } + } + else { + for (; i != stop; i = i + step) { + $(`${pageIdPrefix}${i}`).removeClass('hidden').removeClass('disabled'); + $(`${pageIdPrefix}${i} span`).html(i); + } + } } function populateComments(comments) { @@ -165,5 +220,11 @@ jQuery(document).ready(function () { }) } - paginateComments(1); + if (totalPages <= 1) + $(pagesListId).hide(); + + if (totalPages > 0) { + emptyProductComment.hide(); + $(`${pageIdPrefix}1`).trigger('click'); + } }); diff --git a/views/templates/hook/product-comments-list.tpl b/views/templates/hook/product-comments-list.tpl index 3d07c5ee..1f353544 100644 --- a/views/templates/hook/product-comments-list.tpl +++ b/views/templates/hook/product-comments-list.tpl @@ -42,11 +42,25 @@ data-list-comments-url="{$list_comments_url nofilter}" data-update-comment-usefulness-url="{$update_comment_usefulness_url nofilter}" data-report-comment-url="{$report_comment_url nofilter}" - data-comment-item-prototype="{$comment_prototype|escape:'html'}"> + data-comment-item-prototype="{$comment_prototype|escape:'html'}" + data-current-page="1" + data-total-pages="{$list_total_pages}">