From e5b851239a92e888d689bf964f67eb8b11a6bad7 Mon Sep 17 00:00:00 2001 From: bc-andreadao Date: Fri, 17 Jan 2025 11:15:07 -0600 Subject: [PATCH 01/13] add github workflow for autogenerating docs --- .github/workflows/doc.yml | 50 +++++++++++++++++++++++++++++++++++++++ generate-docs.sh | 21 ++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 .github/workflows/doc.yml create mode 100755 generate-docs.sh diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml new file mode 100644 index 00000000..abb60640 --- /dev/null +++ b/.github/workflows/doc.yml @@ -0,0 +1,50 @@ +name: Generate Documentation (main) + +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + + - name: Clear Composer Cache + run: composer clear-cache + + - name: Install or Update Composer Dependencies + run: | + composer update bc-andreadao/wp-documentor --no-dev + composer update bc-andreadao/phpdocumentor-markdown --no-dev --with-all-dependencies + + - name: Run shell script to generate documentation + run: ./generate-docs.sh + + - name: Generate and push documentation + run: | + git clone https://$GITHUB_ACTOR:${{ secrets.ACCESS_TOKEN }}@github.com/bc-andreadao/bc-wordpress-reference.git + cd bc-wordpress-reference + git fetch origin + BRANCH_NAME="docs-$(date +'%Y-%m-%d_%H-%M-%S')" + git checkout main + git checkout -b $BRANCH_NAME + rsync -av --ignore-times $GITHUB_WORKSPACE/docs/ pages/ + git config user.name "GitHub Actions" + git config user.email "actions@github.com"s + git add . + git commit -m "Update documentation from $(date +'%Y-%m-%d')" || echo "No changes to commit" + echo "Current branch: $(git branch --show-current)" + git push -v --set-upstream origin $BRANCH_NAME || { + echo "Push failed. Current git status:" + git status + echo "Remote branches:" + git branch -r + exit 1 + } diff --git a/generate-docs.sh b/generate-docs.sh new file mode 100755 index 00000000..210bab9d --- /dev/null +++ b/generate-docs.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# To run this file, run the command `./generate-docs.sh` in the terminal + +# Clean up existing docs directory completely +rm -rf docs +mkdir -p docs +echo "Created clean directory for markdown template inside docs." + +# Generate hook documentation in Markdown format using Pronamic WP Documentor +vendor/bin/wp-documentor parse src --format=markdown --output=docs/Hooks.md + +# Generate documentation for classes in Markdown format using PHPDocumentor +docker run --rm \ + -v "$PWD:/data" \ + -v "$PWD/vendor/bc-andreadao/phpdocumentor-markdown:/phpdoc" \ + phpdoc/phpdoc:3 \ + -d /data/src \ + -t /data/docs \ + --template=/phpdoc/themes/markdown \ + --visibility=public,protected \ No newline at end of file From 5622250587101b686489408b2306fe6d3f48fc1f Mon Sep 17 00:00:00 2001 From: bc-andreadao Date: Fri, 17 Jan 2025 11:21:32 -0600 Subject: [PATCH 02/13] update dependencies & packages --- composer.json | 56 + composer.lock | 10734 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 10790 insertions(+) create mode 100644 composer.json create mode 100644 composer.lock diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..32704a7d --- /dev/null +++ b/composer.json @@ -0,0 +1,56 @@ +{ + "name": "moderntribe/bigcommerce", + "description": "BigCommerce for WordPress", + "type": "wordpress-plugin", + "license": "GPLv2", + "config": { + "platform": { + "php": "8.2" + }, + "vendor-dir": "vendor", + "sort-packages": true, + "preferred-install": { + "*": "dist" + }, + "allow-plugins": { + "kylekatarnls/update-helper": true + } + }, + "require": { + "bigcommerce/api": "3.1.0", + "moderntribe/bigcommerce-api-php-v3": "2.3.4", + "monolog/monolog": "1.24.0", + "pimple/pimple": "3.2.3", + "vlucas/phpdotenv": "2.4.0", + "bc-andreadao/wp-documentor": "dev-main", + "bc-andreadao/phpdocumentor-markdown": "dev-master" + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/bordoni/phpass.git" + }, + { + "type": "vcs", + "url": "https://github.com/bc-andreadao/wp-documentor.git" + }, + { + "type": "vcs", + "url": "https://github.com/bc-andreadao/phpDocumentor-markdown.git" + } + ], + "autoload": { + "psr-4": { + "BigCommerce\\": "src/BigCommerce" + } + }, + "autoload-dev": { + "psr-4": { + "BigCommerce\\": "tests/integration/BigCommerce" + } + }, + "require-dev": { + "league/csv": "^8.2", + "lucatume/wp-browser": "^3.1" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..c95cad2f --- /dev/null +++ b/composer.lock @@ -0,0 +1,10734 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "8e5c06b2f1437751fd41e70f65ad35f7", + "packages": [ + { + "name": "bc-andreadao/phpdocumentor-markdown", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/bc-andreadao/phpDocumentor-markdown.git", + "reference": "061a474115a54c502cf7a686b12160152dbacaae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bc-andreadao/phpDocumentor-markdown/zipball/061a474115a54c502cf7a686b12160152dbacaae", + "reference": "061a474115a54c502cf7a686b12160152dbacaae", + "shasum": "" + }, + "require-dev": { + "php": ">=7.4", + "phpunit/phpunit": "^9.5", + "twig/twig": "2.*" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "PhpDocumentorMarkdown\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "PhpDocumentorMarkdown\\Test\\": "tests/" + } + }, + "scripts": { + "test": [ + "vendor/bin/phpunit" + ], + "create-docs": [ + "phpdoc && cp -r example/* docs/.wiki" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Saggre", + "email": "sakri.koskimies@hotmail.com" + } + ], + "description": "Markdown template for phpDocumentor3", + "keywords": [ + "documentation", + "github", + "gitlab", + "markdown", + "phpdoc", + "phpdocumentor" + ], + "support": { + "source": "https://github.com/bc-andreadao/phpDocumentor-markdown/tree/master" + }, + "time": "2024-12-13T23:37:56+00:00" + }, + { + "name": "bc-andreadao/wp-documentor", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/bc-andreadao/wp-documentor.git", + "reference": "f0dc0734e500bfa646b5f0b9123661621cca79f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bc-andreadao/wp-documentor/zipball/f0dc0734e500bfa646b5f0b9123661621cca79f4", + "reference": "f0dc0734e500bfa646b5f0b9123661621cca79f4", + "shasum": "" + }, + "require": { + "php": ">=8.0", + "phpdocumentor/reflection": "^4.0", + "phpdocumentor/reflection-docblock": "^5.2", + "symfony/console": "^5.0 || ^6.0 || ^6.1 || ^6.2", + "symfony/filesystem": "^5.0 || ^6.0 || ^6.1 || ^6.2", + "symfony/finder": "^5.0 || ^6.0 || ^6.1 || ^6.2", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", + "phpcompatibility/php-compatibility": "^9.3", + "phpcompatibility/phpcompatibility-wp": "^2.1", + "phpdocumentor/phpdocumentor": "^3.0", + "roots/wordpress": "^5.7", + "squizlabs/php_codesniffer": "^3.6", + "wp-coding-standards/wpcs": "^2.3" + }, + "default-branch": true, + "bin": [ + "bin/wp-documentor" + ], + "type": "library", + "autoload": { + "psr-4": { + "Pronamic\\WordPress\\Documentor\\": "src" + } + }, + "scripts": { + "phpdoc": [ + "vendor/bin/phpdoc --setting='guides.enabled=true'" + ], + "test": [ + "bin/wp-documentor parse tests/source --format=hookster --type=actions --relative=tests/docs --output=tests/docs/hookster-actions.json", + "bin/wp-documentor parse tests/source --format=hookster --type=filters --relative=tests/docs --output=tests/docs/hookster-filters.json", + "bin/wp-documentor parse tests/source --format=markdown --relative=tests/docs --output=tests/docs/hooks.md", + "bin/wp-documentor parse tests/source --format=phpdocumentor-rst --type=actions --relative=tests/docs --output=tests/docs/phpdocumentor-actions.rst", + "bin/wp-documentor parse tests/source --format=phpdocumentor-rst --type=filters --relative=tests/docs --output=tests/docs/phpdocumentor-filters.rst", + "bin/wp-documentor parse wordpress --format=markdown --relative=tests/docs --memory-limit=-1 --output=tests/docs/wordpress-hooks.md", + "bin/wp-documentor parse tests/issue-10 --format=markdown --output=tests/issue-10/hooks.md --prefix=prefix_1 --prefix=prefix_2", + "bin/wp-documentor parse tests/issue-11 --format=markdown --output=tests/issue-11/hooks.md", + "bin/wp-documentor parse tests/issue-12 --format=markdown --output=tests/issue-12/hooks.md", + "bin/wp-documentor parse tests/issue-13 --exclude=file-exclude.php --exclude=folder-exclude/ --format=markdown --output=tests/issue-13/hooks.md", + "bin/wp-documentor parse tests/issue-14 --format=markdown --output=tests/issue-14/hooks.md", + "bin/wp-documentor parse tests/issue-16 --format=markdown --output=tests/issue-16/hooks.md", + "bin/wp-documentor parse tests/issue-17 --format=markdown --output=tests/issue-17/hooks.md", + "bin/wp-documentor parse tests/issue-18 --format=markdown --output=tests/issue-18/hooks.md" + ] + }, + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Pronamic", + "email": "info@pronamic.eu", + "homepage": "https://www.pronamic.eu/", + "role": "Company" + }, + { + "name": "Remco Tolsma", + "email": "info@remcotolsma.nl", + "homepage": "https://www.remcotolsma.nl/", + "role": "Developer" + } + ], + "description": "Documentation Generator for WordPress.", + "keywords": [ + "api", + "application", + "dga", + "documentation", + "phpdoc", + "wordpress" + ], + "support": { + "source": "https://github.com/bc-andreadao/wp-documentor/tree/main" + }, + "time": "2024-12-10T20:20:33+00:00" + }, + { + "name": "bigcommerce/api", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/bigcommerce/bigcommerce-api-php.git", + "reference": "e57fc7ab2de3a5dabc047fd96fa61b2596d23089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bigcommerce/bigcommerce-api-php/zipball/e57fc7ab2de3a5dabc047fd96fa61b2596d23089", + "reference": "e57fc7ab2de3a5dabc047fd96fa61b2596d23089", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "~3.0|~5.0", + "paragonie/random_compat": "~1.4|~2.0", + "php": ">=5.3.0" + }, + "require-dev": { + "codeless/jugglecode": "1.0", + "phpunit/phpunit": "4.5.*", + "satooshi/php-coveralls": "1.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Bigcommerce": "src/" + }, + "psr-4": { + "Bigcommerce\\Test\\": "test/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bigcommerce", + "homepage": "http://www.bigcommerce.com" + } + ], + "description": "Enables PHP applications to communicate with the Bigcommerce API.", + "homepage": "http://developer.bigcommerce.com", + "keywords": [ + "api", + "business", + "ecommerce", + "http", + "rest" + ], + "support": { + "issues": "https://github.com/bigcommerce/bigcommerce-api-php/issues", + "source": "https://github.com/bigcommerce/bigcommerce-api-php/tree/master" + }, + "time": "2017-08-22T16:07:01+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12", + "phpstan/phpstan": "1.4.10 || 2.0.3", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "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/1.1.4" + }, + "time": "2024-12-07T21:18:45+00:00" + }, + { + "name": "firebase/php-jwt", + "version": "v5.5.1", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "83b609028194aa042ea33b5af2d41a7427de80e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6", + "reference": "83b609028194aa042ea33b5af2d41a7427de80e6", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8 <=9" + }, + "suggest": { + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v5.5.1" + }, + "time": "2021-11-08T20:18:51+00:00" + }, + { + "name": "moderntribe/bigcommerce-api-php-v3", + "version": "v2.3.4", + "source": { + "type": "git", + "url": "https://github.com/moderntribe/bigcommerce-api-php-v3.git", + "reference": "054f0c7bc188560bdcad24c7ace908def11a5c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/moderntribe/bigcommerce-api-php-v3/zipball/054f0c7bc188560bdcad24c7ace908def11a5c9e", + "reference": "054f0c7bc188560bdcad24c7ace908def11a5c9e", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.8", + "satooshi/php-coveralls": "~1.0", + "squizlabs/php_codesniffer": "~2.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "BigCommerce\\Api\\v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "autoload-dev": { + "psr-4": { + "BigCommerce\\Api\\v3\\": "test/" + } + }, + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Bigcommerce", + "homepage": "https://developer.bigcommerce.com/api/v3/" + } + ], + "homepage": "https://developer.bigcommerce.com/api/v3/", + "keywords": [ + "api", + "php", + "sdk", + "swagger" + ], + "support": { + "issues": "https://github.com/moderntribe/bigcommerce-api-php-v3/issues", + "source": "https://github.com/moderntribe/bigcommerce-api-php-v3/tree/v2.3.4" + }, + "time": "2023-03-15T21:18:15+00:00" + }, + { + "name": "monolog/monolog", + "version": "1.24.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", + "reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "jakub-onderka/php-parallel-lint": "0.9", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", + "swiftmailer/swiftmailer": "^5.3|^6.0" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/1.24.0" + }, + "time": "2018-11-05T09:00:11+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.19.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/715f4d25e225bc47b293a8b997fe6ce99bf987d2", + "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.1" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.4" + }, + "time": "2024-09-29T15:01:53+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.21", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/96c132c7f2f7bc3230723b66e89f8f150b29d5ae", + "reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "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" + }, + "time": "2022-02-16T17:07:03+00:00" + }, + { + "name": "phpdocumentor/reflection", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/Reflection.git", + "reference": "447928a45710d6313e68774cf12b5f730b909baa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/447928a45710d6313e68774cf12b5f730b909baa", + "reference": "447928a45710d6313e68774cf12b5f730b909baa", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.0", + "php": ">=7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/reflection-docblock": "^5", + "phpdocumentor/type-resolver": "^1.0", + "psr/log": "~1.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mikey179/vfsstream": "~1.2", + "mockery/mockery": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-4.x": "4.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\": "src/phpDocumentor" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Reflection library to do Static Analysis for PHP Projects", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/Reflection/issues", + "source": "https://github.com/phpDocumentor/Reflection/tree/4.x" + }, + "time": "2020-06-19T18:26:14+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", + "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.1" + }, + "time": "2024-12-07T09:39:29+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + }, + "time": "2024-11-09T15:12:26+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" + }, + "time": "2024-10-13T11:29:49+00:00" + }, + { + "name": "pimple/pimple", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/container": "^1.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ], + "support": { + "issues": "https://github.com/silexphp/Pimple/issues", + "source": "https://github.com/silexphp/Pimple/tree/master" + }, + "time": "2018-01-21T07:42:36+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+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": "symfony/console", + "version": "v5.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "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.47" + }, + "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": "2024-11-06T11:30:55+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.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/v3.5.1" + }, + "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": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v6.4.13", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, + "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/v6.4.13" + }, + "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": "2024-10-25T15:07:50+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "63741784cd7b9967975eec610b256eed3ede022b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", + "reference": "63741784cd7b9967975eec610b256eed3ede022b", + "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.45" + }, + "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": "2024-09-28T13:32:08+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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 backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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 writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + }, + "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": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/string", + "version": "v6.4.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "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/string/tree/v6.4.15" + }, + "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": "2024-11-13T13:31:12+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause-Attribution" + ], + "authors": [ + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "http://www.vancelucas.com" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/master" + }, + "time": "2016-09-01T10:05:43+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "antecedent/patchwork", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/antecedent/patchwork.git", + "reference": "1bf183a3e1bd094f231a2128b9ecc5363c269245" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/1bf183a3e1bd094f231a2128b9ecc5363c269245", + "reference": "1bf183a3e1bd094f231a2128b9ecc5363c269245", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignas Rudaitis", + "email": "ignas.rudaitis@gmail.com" + } + ], + "description": "Method redefinition (monkey-patching) functionality for PHP.", + "homepage": "https://antecedent.github.io/patchwork/", + "keywords": [ + "aop", + "aspect", + "interception", + "monkeypatching", + "redefinition", + "runkit", + "testing" + ], + "support": { + "issues": "https://github.com/antecedent/patchwork/issues", + "source": "https://github.com/antecedent/patchwork/tree/2.2.1" + }, + "time": "2024-12-11T10:19:54+00:00" + }, + { + "name": "behat/gherkin", + "version": "v4.11.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "32821a17b12620951e755b5d49328a6421a5b5b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/32821a17b12620951e755b5d49328a6421a5b5b5", + "reference": "32821a17b12620951e755b5d49328a6421a5b5b5", + "shasum": "" + }, + "require": { + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*" + }, + "require-dev": { + "cucumber/cucumber": "dev-gherkin-24.1.0", + "phpunit/phpunit": "^9.6", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Gherkin": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Gherkin DSL parser for PHP", + "homepage": "http://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "support": { + "issues": "https://github.com/Behat/Gherkin/issues", + "source": "https://github.com/Behat/Gherkin/tree/v4.11.0" + }, + "time": "2024-12-06T10:07:25+00:00" + }, + { + "name": "bordoni/phpass", + "version": "0.3.6", + "source": { + "type": "git", + "url": "https://github.com/bordoni/phpass.git", + "reference": "12f8f5cc03ebb7efd69554f104afe9aa1aa46e1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bordoni/phpass/zipball/12f8f5cc03ebb7efd69554f104afe9aa1aa46e1a", + "reference": "12f8f5cc03ebb7efd69554f104afe9aa1aa46e1a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "replace": { + "hautelook/phpass": "0.3.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Hautelook": "src/" + } + }, + "license": [ + "Public Domain" + ], + "authors": [ + { + "name": "Solar Designer", + "email": "solar@openwall.com", + "homepage": "http://openwall.com/phpass/" + }, + { + "name": "Gustavo Bordoni", + "email": "gustavo@bordoni.me", + "homepage": "https://bordoni.me" + } + ], + "description": "Portable PHP password hashing framework", + "homepage": "http://github.com/bordoni/phpass/", + "keywords": [ + "Blowfish", + "crypt", + "password", + "security" + ], + "support": { + "source": "https://github.com/bordoni/phpass/tree/0.3.6", + "issues": "https://github.com/bordoni/phpass/issues" + }, + "time": "2012-08-31T00:00:00+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/dbal": "<4.0.0 || >=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" + }, + { + "name": "codeception/codeception", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Codeception.git", + "reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/b88014f3348c93f3df99dc6d0967b0dbfa804474", + "reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.4.0", + "codeception/lib-asserts": "^1.0 | 2.0.*@dev", + "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.1.1 | ^9.0", + "codeception/stub": "^2.0 | ^3.0 | ^4.0", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "guzzlehttp/psr7": "^1.4 | ^2.0", + "php": ">=5.6.0 <9.0", + "symfony/console": ">=2.7 <6.0", + "symfony/css-selector": ">=2.7 <6.0", + "symfony/event-dispatcher": ">=2.7 <6.0", + "symfony/finder": ">=2.7 <6.0", + "symfony/yaml": ">=2.7 <6.0" + }, + "require-dev": { + "codeception/module-asserts": "^1.0 | 2.0.*@dev", + "codeception/module-cli": "^1.0 | 2.0.*@dev", + "codeception/module-db": "^1.0 | 2.0.*@dev", + "codeception/module-filesystem": "^1.0 | 2.0.*@dev", + "codeception/module-phpbrowser": "^1.0 | 2.0.*@dev", + "codeception/specify": "~0.3", + "codeception/util-universalframework": "*@dev", + "monolog/monolog": "~1.8", + "squizlabs/php_codesniffer": "~2.0", + "symfony/process": ">=2.7 <6.0", + "vlucas/phpdotenv": "^2.0 | ^3.0 | ^4.0 | ^5.0" + }, + "suggest": { + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "hoa/console": "For interactive console functionality", + "stecman/symfony-console-completion": "For BASH autocompletion", + "symfony/phpunit-bridge": "For phpunit-bridge support" + }, + "bin": [ + "codecept" + ], + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "files": [ + "functions.php" + ], + "psr-4": { + "Codeception\\": "src/Codeception", + "Codeception\\Extension\\": "ext" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "https://codegyre.com" + } + ], + "description": "BDD-style testing framework", + "homepage": "https://codeception.com/", + "keywords": [ + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "support": { + "issues": "https://github.com/Codeception/Codeception/issues", + "source": "https://github.com/Codeception/Codeception/tree/4.2.2" + }, + "funding": [ + { + "url": "https://opencollective.com/codeception", + "type": "open_collective" + } + ], + "time": "2022-08-13T13:28:25+00:00" + }, + { + "name": "codeception/lib-asserts", + "version": "1.13.2", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-asserts.git", + "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/184231d5eab66bc69afd6b9429344d80c67a33b6", + "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6", + "shasum": "" + }, + "require": { + "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3 | ^9.0", + "ext-dom": "*", + "php": ">=5.6.0 <9.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" + } + ], + "description": "Assertion methods used by Codeception core and Asserts module", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-asserts/issues", + "source": "https://github.com/Codeception/lib-asserts/tree/1.13.2" + }, + "time": "2020-10-21T16:26:20+00:00" + }, + { + "name": "codeception/lib-innerbrowser", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-innerbrowser.git", + "reference": "31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2", + "reference": "31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2", + "shasum": "" + }, + "require": { + "codeception/codeception": "4.*@dev", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": ">=5.6.0 <9.0", + "symfony/browser-kit": ">=2.7 <6.0", + "symfony/dom-crawler": ">=2.7 <6.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "require-dev": { + "codeception/util-universalframework": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Parent library for all Codeception framework modules and PhpBrowser", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-innerbrowser/issues", + "source": "https://github.com/Codeception/lib-innerbrowser/tree/1.5.1" + }, + "time": "2021-08-30T15:21:42+00:00" + }, + { + "name": "codeception/module-asserts", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-asserts.git", + "reference": "59374f2fef0cabb9e8ddb53277e85cdca74328de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-asserts/zipball/59374f2fef0cabb9e8ddb53277e85cdca74328de", + "reference": "59374f2fef0cabb9e8ddb53277e85cdca74328de", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "codeception/lib-asserts": "^1.13.1", + "php": ">=5.6.0 <9.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" + } + ], + "description": "Codeception module containing various assertions", + "homepage": "https://codeception.com/", + "keywords": [ + "assertions", + "asserts", + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/module-asserts/issues", + "source": "https://github.com/Codeception/module-asserts/tree/1.3.1" + }, + "time": "2020-10-21T16:48:15+00:00" + }, + { + "name": "codeception/module-cli", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-cli.git", + "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-cli/zipball/1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f", + "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "php": ">=5.6.0 <9.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + } + ], + "description": "Codeception module for testing basic shell commands and shell output", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/module-cli/issues", + "source": "https://github.com/Codeception/module-cli/tree/1.1.1" + }, + "time": "2020-12-26T16:56:19+00:00" + }, + { + "name": "codeception/module-db", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-db.git", + "reference": "04c3e66fbd3a3ced17fcccc49627f6393a97b04b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-db/zipball/04c3e66fbd3a3ced17fcccc49627f6393a97b04b", + "reference": "04c3e66fbd3a3ced17fcccc49627f6393a97b04b", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "php": ">=5.6.0 <9.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "DB module for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception", + "database-testing", + "db-testing" + ], + "support": { + "issues": "https://github.com/Codeception/module-db/issues", + "source": "https://github.com/Codeception/module-db/tree/1.2.0" + }, + "time": "2022-03-05T19:38:40+00:00" + }, + { + "name": "codeception/module-filesystem", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-filesystem.git", + "reference": "781be167fb1557bfc9b61e0a4eac60a32c534ec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-filesystem/zipball/781be167fb1557bfc9b61e0a4eac60a32c534ec1", + "reference": "781be167fb1557bfc9b61e0a4eac60a32c534ec1", + "shasum": "" + }, + "require": { + "codeception/codeception": "^4.0", + "php": ">=5.6.0 <9.0", + "symfony/finder": ">=2.7 <6.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Codeception module for testing local filesystem", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception", + "filesystem" + ], + "support": { + "issues": "https://github.com/Codeception/module-filesystem/issues", + "source": "https://github.com/Codeception/module-filesystem/tree/1.0.3" + }, + "time": "2020-10-24T14:46:40+00:00" + }, + { + "name": "codeception/module-phpbrowser", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-phpbrowser.git", + "reference": "8ba6bede11d0914e74d98691f427fd8f397f192e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-phpbrowser/zipball/8ba6bede11d0914e74d98691f427fd8f397f192e", + "reference": "8ba6bede11d0914e74d98691f427fd8f397f192e", + "shasum": "" + }, + "require": { + "codeception/codeception": "^4.1", + "codeception/lib-innerbrowser": "^1.3", + "guzzlehttp/guzzle": "^6.3|^7.0", + "php": ">=5.6.0 <9.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "require-dev": { + "codeception/module-rest": "^1.0" + }, + "suggest": { + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Codeception module for testing web application over HTTP", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception", + "functional-testing", + "http" + ], + "support": { + "issues": "https://github.com/Codeception/module-phpbrowser/issues", + "source": "https://github.com/Codeception/module-phpbrowser/tree/1.0.3" + }, + "time": "2022-05-21T13:50:41+00:00" + }, + { + "name": "codeception/module-webdriver", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-webdriver.git", + "reference": "e22ac7da756df659df6dd4fac2dff9c859e30131" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/e22ac7da756df659df6dd4fac2dff9c859e30131", + "reference": "e22ac7da756df659df6dd4fac2dff9c859e30131", + "shasum": "" + }, + "require": { + "codeception/codeception": "^4.0", + "php": ">=5.6.0 <9.0", + "php-webdriver/webdriver": "^1.8.0" + }, + "suggest": { + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Zaahid Bateson" + } + ], + "description": "WebDriver module for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "acceptance-testing", + "browser-testing", + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/module-webdriver/issues", + "source": "https://github.com/Codeception/module-webdriver/tree/1.4.1" + }, + "time": "2022-09-12T05:09:51+00:00" + }, + { + "name": "codeception/phpunit-wrapper", + "version": "9.0.9", + "source": { + "type": "git", + "url": "https://github.com/Codeception/phpunit-wrapper.git", + "reference": "7439a53ae367986e9c22b2ac00f9d7376bb2f8cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/7439a53ae367986e9c22b2ac00f9d7376bb2f8cf", + "reference": "7439a53ae367986e9c22b2ac00f9d7376bb2f8cf", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "phpunit/phpunit": "^9.0" + }, + "require-dev": { + "codeception/specify": "*", + "consolidation/robo": "^3.0.0-alpha3", + "vlucas/phpdotenv": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\PHPUnit\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Davert", + "email": "davert.php@resend.cc" + }, + { + "name": "Naktibalda" + } + ], + "description": "PHPUnit classes used by Codeception", + "support": { + "issues": "https://github.com/Codeception/phpunit-wrapper/issues", + "source": "https://github.com/Codeception/phpunit-wrapper/tree/9.0.9" + }, + "time": "2022-05-23T06:24:11+00:00" + }, + { + "name": "codeception/stub", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Stub.git", + "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/18a148dacd293fc7b044042f5aa63a82b08bff5d", + "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d", + "shasum": "" + }, + "require": { + "php": "^7.4 | ^8.0", + "phpunit/phpunit": "^8.4 | ^9.0 | ^10.0 | 10.0.x-dev" + }, + "require-dev": { + "consolidation/robo": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "support": { + "issues": "https://github.com/Codeception/Stub/issues", + "source": "https://github.com/Codeception/Stub/tree/4.0.2" + }, + "time": "2022-01-31T19:25:15+00:00" + }, + { + "name": "codeception/util-universalframework", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/util-universalframework.git", + "reference": "cc381f364c6d24f9b9c7b70a4c724949725f491a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/util-universalframework/zipball/cc381f364c6d24f9b9c7b70a4c724949725f491a", + "reference": "cc381f364c6d24f9b9c7b70a4c724949725f491a", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gintautas Miselis" + } + ], + "description": "Mock framework module used in internal Codeception tests", + "homepage": "http://codeception.com/", + "support": { + "issues": "https://github.com/Codeception/util-universalframework/issues", + "source": "https://github.com/Codeception/util-universalframework/tree/1.0.0" + }, + "time": "2019-09-22T06:06:49+00:00" + }, + { + "name": "composer/ca-bundle", + "version": "1.5.4", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/bc0593537a463e55cadf45fd938d23b75095b7e1", + "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8 || ^9", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.5.4" + }, + "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": "2024-11-27T15:35:25+00:00" + }, + { + "name": "composer/class-map-generator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/composer/class-map-generator.git", + "reference": "4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915", + "reference": "4b0a223cf5be7c9ee7e0ef1bc7db42b4a97c9915", + "shasum": "" + }, + "require": { + "composer/pcre": "^2.1 || ^3.1", + "php": "^7.2 || ^8.0", + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", + "phpunit/phpunit": "^8", + "symfony/filesystem": "^5.4 || ^6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\ClassMapGenerator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Utilities to scan PHP code and generate class maps.", + "keywords": [ + "classmap" + ], + "support": { + "issues": "https://github.com/composer/class-map-generator/issues", + "source": "https://github.com/composer/class-map-generator/tree/1.5.0" + }, + "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": "2024-11-25T16:11:06+00:00" + }, + { + "name": "composer/composer", + "version": "2.8.4", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "112e37d1dca22b3fdb81cf3524ab4994f47fdb8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/112e37d1dca22b3fdb81cf3524ab4994f47fdb8c", + "reference": "112e37d1dca22b3fdb81cf3524ab4994f47fdb8c", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.5", + "composer/class-map-generator": "^1.4.0", + "composer/metadata-minifier": "^1.0", + "composer/pcre": "^2.2 || ^3.2", + "composer/semver": "^3.3", + "composer/spdx-licenses": "^1.5.7", + "composer/xdebug-handler": "^2.0.2 || ^3.0.3", + "justinrainbow/json-schema": "^5.3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "react/promise": "^2.11 || ^3.2", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.2", + "seld/signal-handler": "^2.0", + "symfony/console": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/finder": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/polyfill-php73": "^1.24", + "symfony/polyfill-php80": "^1.24", + "symfony/polyfill-php81": "^1.24", + "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3" + }, + "require-dev": { + "phpstan/phpstan": "^1.11.8", + "phpstan/phpstan-deprecation-rules": "^1.2.0", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpstan/phpstan-symfony": "^1.4.0", + "symfony/phpunit-bridge": "^6.4.3 || ^7.0.1" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "bin": [ + "bin/composer" + ], + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "phpstan/rules.neon" + ] + }, + "branch-alias": { + "dev-main": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "https://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", + "homepage": "https://getcomposer.org/", + "keywords": [ + "autoload", + "dependency", + "package" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/composer/issues", + "security": "https://github.com/composer/composer/security/policy", + "source": "https://github.com/composer/composer/tree/2.8.4" + }, + "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": "2024-12-11T10:57:47+00:00" + }, + { + "name": "composer/metadata-minifier", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/metadata-minifier.git", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2", + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\MetadataMinifier\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Small utility library that handles metadata minification and expansion.", + "keywords": [ + "composer", + "compression" + ], + "support": { + "issues": "https://github.com/composer/metadata-minifier/issues", + "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" + }, + "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": "2021-04-07T13:37:33+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "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/3.3.2" + }, + "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": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "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": "2024-09-19T14:15:21+00:00" + }, + { + "name": "composer/spdx-licenses", + "version": "1.5.8", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a", + "reference": "560bdcf8deb88ae5d611c80a2de8ea9d0358cc0a", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/spdx-licenses/issues", + "source": "https://github.com/composer/spdx-licenses/tree/1.5.8" + }, + "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": "2023-11-20T07:44:33+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "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": "2024-05-06T16:37:16+00:00" + }, + { + "name": "dg/mysql-dump", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/dg/MySQL-dump.git", + "reference": "b83859026dc3651c6aa39376705fbfa57c0486c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dg/MySQL-dump/zipball/b83859026dc3651c6aa39376705fbfa57c0486c5", + "reference": "b83859026dc3651c6aa39376705fbfa57c0486c5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "http://davidgrudl.com" + } + ], + "description": "MySQL database dump.", + "homepage": "https://github.com/dg/MySQL-dump", + "keywords": [ + "mysql" + ], + "support": { + "source": "https://github.com/dg/MySQL-dump/tree/v1.6.0" + }, + "time": "2024-09-16T04:30:48+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "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%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + }, + "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%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:23:10+00:00" + }, + { + "name": "eftec/bladeone", + "version": "3.52", + "source": { + "type": "git", + "url": "https://github.com/EFTEC/BladeOne.git", + "reference": "a19bf66917de0b29836983db87a455a4f6e32148" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/EFTEC/BladeOne/zipball/a19bf66917de0b29836983db87a455a4f6e32148", + "reference": "a19bf66917de0b29836983db87a455a4f6e32148", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.6" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16.1", + "phpunit/phpunit": "^5.7", + "squizlabs/php_codesniffer": "^3.5.4" + }, + "suggest": { + "eftec/bladeonehtml": "Extension to create forms", + "ext-mbstring": "This extension is used if it's active" + }, + "type": "library", + "autoload": { + "psr-4": { + "eftec\\bladeone\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jorge Patricio Castro Castillo", + "email": "jcastro@eftec.cl" + } + ], + "description": "The standalone version Blade Template Engine from Laravel in a single php file", + "homepage": "https://github.com/EFTEC/BladeOne", + "keywords": [ + "blade", + "php", + "template", + "templating", + "view" + ], + "support": { + "issues": "https://github.com/EFTEC/BladeOne/issues", + "source": "https://github.com/EFTEC/BladeOne/tree/3.52" + }, + "time": "2021-04-17T13:49:01+00:00" + }, + { + "name": "gettext/gettext", + "version": "v4.8.12", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/Gettext.git", + "reference": "11af89ee6c087db3cf09ce2111a150bca5c46e12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/11af89ee6c087db3cf09ce2111a150bca5c46e12", + "reference": "11af89ee6c087db3cf09ce2111a150bca5c46e12", + "shasum": "" + }, + "require": { + "gettext/languages": "^2.3", + "php": ">=5.4.0" + }, + "require-dev": { + "illuminate/view": "^5.0.x-dev", + "phpunit/phpunit": "^4.8|^5.7|^6.5", + "squizlabs/php_codesniffer": "^3.0", + "symfony/yaml": "~2", + "twig/extensions": "*", + "twig/twig": "^1.31|^2.0" + }, + "suggest": { + "illuminate/view": "Is necessary if you want to use the Blade extractor", + "symfony/yaml": "Is necessary if you want to use the Yaml extractor/generator", + "twig/extensions": "Is necessary if you want to use the Twig extractor", + "twig/twig": "Is necessary if you want to use the Twig extractor" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP gettext manager", + "homepage": "https://github.com/oscarotero/Gettext", + "keywords": [ + "JS", + "gettext", + "i18n", + "mo", + "po", + "translation" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/oscarotero/Gettext/issues", + "source": "https://github.com/php-gettext/Gettext/tree/v4.8.12" + }, + "funding": [ + { + "url": "https://paypal.me/oscarotero", + "type": "custom" + }, + { + "url": "https://github.com/oscarotero", + "type": "github" + }, + { + "url": "https://www.patreon.com/misteroom", + "type": "patreon" + } + ], + "time": "2024-05-18T10:25:07+00:00" + }, + { + "name": "gettext/languages", + "version": "2.10.0", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/Languages.git", + "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/Languages/zipball/4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab", + "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4" + }, + "bin": [ + "bin/export-plural-rules" + ], + "type": "library", + "autoload": { + "psr-4": { + "Gettext\\Languages\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michele Locati", + "email": "mlocati@gmail.com", + "role": "Developer" + } + ], + "description": "gettext languages with plural rules", + "homepage": "https://github.com/php-gettext/Languages", + "keywords": [ + "cldr", + "i18n", + "internationalization", + "l10n", + "language", + "languages", + "localization", + "php", + "plural", + "plural rules", + "plurals", + "translate", + "translations", + "unicode" + ], + "support": { + "issues": "https://github.com/php-gettext/Languages/issues", + "source": "https://github.com/php-gettext/Languages/tree/2.10.0" + }, + "funding": [ + { + "url": "https://paypal.me/mlocati", + "type": "custom" + }, + { + "url": "https://github.com/mlocati", + "type": "github" + } + ], + "time": "2022-10-18T15:00:10+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2024-07-24T11:22:20+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2024-10-17T10:06:22+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2024-07-18T11:15:46+00:00" + }, + { + "name": "illuminate/collections", + "version": "v11.35.1", + "source": { + "type": "git", + "url": "https://github.com/illuminate/collections.git", + "reference": "b8be9c0fedfc5be1524b290fed640d4b7d42c813" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/collections/zipball/b8be9c0fedfc5be1524b290fed640d4b7d42c813", + "reference": "b8be9c0fedfc5be1524b290fed640d4b7d42c813", + "shasum": "" + }, + "require": { + "illuminate/conditionable": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "php": "^8.2" + }, + "suggest": { + "symfony/var-dumper": "Required to use the dump method (^7.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "files": [ + "functions.php", + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Collections package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-12-10T14:54:28+00:00" + }, + { + "name": "illuminate/conditionable", + "version": "v11.35.1", + "source": { + "type": "git", + "url": "https://github.com/illuminate/conditionable.git", + "reference": "911df1bda950a3b799cf80671764e34eede131c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/conditionable/zipball/911df1bda950a3b799cf80671764e34eede131c6", + "reference": "911df1bda950a3b799cf80671764e34eede131c6", + "shasum": "" + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Conditionable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-11-21T16:28:56+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v11.35.1", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "184317f701ba20ca265e36808ed54b75b115972d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/184317f701ba20ca265e36808ed54b75b115972d", + "reference": "184317f701ba20ca265e36808ed54b75b115972d", + "shasum": "" + }, + "require": { + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/simple-cache": "^1.0|^2.0|^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-11-25T15:33:38+00:00" + }, + { + "name": "illuminate/macroable", + "version": "v11.35.1", + "source": { + "type": "git", + "url": "https://github.com/illuminate/macroable.git", + "reference": "e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed", + "reference": "e1cb9e51b9ed5d3c9bc1ab431d0a52fe42a990ed", + "shasum": "" + }, + "require": { + "php": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Macroable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-06-28T20:10:30+00:00" + }, + { + "name": "illuminate/support", + "version": "v11.35.1", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "bc363403d9ed3214754a0501e33c05d2afcfd474" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/bc363403d9ed3214754a0501e33c05d2afcfd474", + "reference": "bc363403d9ed3214754a0501e33c05d2afcfd474", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^2.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-mbstring": "*", + "illuminate/collections": "^11.0", + "illuminate/conditionable": "^11.0", + "illuminate/contracts": "^11.0", + "illuminate/macroable": "^11.0", + "nesbot/carbon": "^2.72.2|^3.4", + "php": "^8.2", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "replace": { + "spatie/once": "*" + }, + "suggest": { + "illuminate/filesystem": "Required to use the Composer class (^11.0).", + "laravel/serializable-closure": "Required to use the once function (^1.3).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).", + "league/uri": "Required to use the Uri class (^7.5.1).", + "ramsey/uuid": "Required to use Str::uuid() (^4.7).", + "symfony/process": "Required to use the Composer class (^7.0).", + "symfony/uid": "Required to use Str::ulid() (^7.0).", + "symfony/var-dumper": "Required to use the dd function (^7.0).", + "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "files": [ + "functions.php", + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-12-11T23:23:18+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "reference": "feb2ca6dd1cebdaf1ed60a4c8de2e53ce11c4fd8", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.0" + }, + "time": "2024-07-06T21:00:26+00:00" + }, + { + "name": "league/csv", + "version": "8.2.3", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/csv.git", + "reference": "d2aab1e7bde802582c3879acf03d92716577c76d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/d2aab1e7bde802582c3879acf03d92716577c76d", + "reference": "d2aab1e7bde802582c3879acf03d92716577c76d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.5.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^1.9", + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Csv\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://github.com/nyamsprod/", + "role": "Developer" + } + ], + "description": "Csv data manipulation made easy in PHP", + "homepage": "http://csv.thephpleague.com", + "keywords": [ + "csv", + "export", + "filter", + "import", + "read", + "write" + ], + "support": { + "forum": "https://groups.google.com/forum/#!forum/thephpleague", + "issues": "https://github.com/thephpleague/csv/issues", + "source": "https://github.com/thephpleague/csv/tree/8.x" + }, + "time": "2018-02-06T08:27:03+00:00" + }, + { + "name": "lucatume/wp-browser", + "version": "3.2.3", + "source": { + "type": "git", + "url": "https://github.com/lucatume/wp-browser.git", + "reference": "0bec9fabe8be43f80dac4af7f90131ec9e299ff4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lucatume/wp-browser/zipball/0bec9fabe8be43f80dac4af7f90131ec9e299ff4", + "reference": "0bec9fabe8be43f80dac4af7f90131ec9e299ff4", + "shasum": "" + }, + "require": { + "antecedent/patchwork": "^2.0", + "bordoni/phpass": "^0.3", + "codeception/codeception": "^4", + "codeception/module-asserts": "^1.0", + "codeception/module-cli": "^1.0", + "codeception/module-db": "^1.0", + "codeception/module-filesystem": "^1.0", + "codeception/module-phpbrowser": "^1.0", + "codeception/module-webdriver": "^1.0", + "codeception/util-universalframework": "^1.0", + "dg/mysql-dump": "^1.3", + "ext-fileinfo": "*", + "ext-json": "*", + "ext-pdo": "*", + "mikehaertl/php-shellcommand": "^1.6", + "mikemclin/laravel-wp-password": "~2.0.0", + "php": ">=5.6.0", + "vria/nodiacritic": "^0.1.2", + "wp-cli/wp-cli": ">=2.0 <3.0.0", + "wp-cli/wp-cli-bundle": "*", + "zordius/lightncandy": "^1.2" + }, + "conflict": { + "codeception/module-asserts": ">=2.0", + "codeception/module-cli": ">=2.0", + "codeception/module-db": ">=2.0", + "codeception/module-filesystem": ">=2.0", + "codeception/module-phpbrowser": ">=2.0", + "codeception/module-webdriver": ">=2.0", + "codeception/util-universalframework": ">=2.0" + }, + "require-dev": { + "erusev/parsedown": "^1.7", + "gumlet/php-image-resize": "^1.6", + "lucatume/codeception-snapshot-assertions": "^0.2", + "mikey179/vfsstream": "^1.6", + "symfony/translation": "^3.4", + "victorjonsson/markdowndocs": "dev-master", + "vlucas/phpdotenv": "^3.0" + }, + "suggest": { + "codeception/module-asserts:^1.0": "Codeception 4.0 compatibility.", + "codeception/module-cli:^1.0": "Codeception 4.0 compatibility; required by the WPCLI module.", + "codeception/module-db:^1.0": "Codeception 4.0 compatibility; required by the WPDb module, PHP 5.6 compatible version.", + "codeception/module-filesystem:^1.0": "Codeception 4.0 compatibility; required by the WPFilesystem module.", + "codeception/module-phpbrowser:^1.0": "Codeception 4.0 compatibility; required by the WPBrowser module.", + "codeception/module-webdriver:^1.0": "Codeception 4.0 compatibility; required by the WPWebDriver module.", + "codeception/util-universalframework:^1.0": "Codeception 4.0 compatibility; required by the WordPress framework module.", + "gumlet/php-image-resize": "To handle runtime image modification in the WPDb::haveAttachmentInDatabase method.", + "vlucas/phpdotenv:^4.0": "To manage more complex environment file based configuration of the suites." + }, + "type": "library", + "extra": { + "_hash": "484f861f69198089cab0e642f27e5653" + }, + "autoload": { + "files": [ + "src/tad/WPBrowser/utils.php", + "src/tad/WPBrowser/wp-polyfills.php" + ], + "psr-4": { + "tad\\": "src/tad", + "Codeception\\": "src/Codeception", + "lucatume\\WPBrowser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "theAverageDev (Luca Tumedei)", + "email": "luca@theaveragedev.com", + "homepage": "http://theaveragedev.com", + "role": "Developer" + } + ], + "description": "WordPress extension of the PhpBrowser class.", + "homepage": "http://github.com/lucatume/wp-browser", + "keywords": [ + "codeception", + "wordpress" + ], + "support": { + "issues": "https://github.com/lucatume/wp-browser/issues", + "source": "https://github.com/lucatume/wp-browser/tree/3.2.3" + }, + "funding": [ + { + "url": "https://github.com/lucatume", + "type": "github" + } + ], + "time": "2024-01-08T08:27:20+00:00" + }, + { + "name": "mck89/peast", + "version": "v1.16.3", + "source": { + "type": "git", + "url": "https://github.com/mck89/peast.git", + "reference": "645ec21b650bc2aced18285c85f220d22afc1430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mck89/peast/zipball/645ec21b650bc2aced18285c85f220d22afc1430", + "reference": "645ec21b650bc2aced18285c85f220d22afc1430", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.16.3-dev" + } + }, + "autoload": { + "psr-4": { + "Peast\\": "lib/Peast/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marco Marchiò", + "email": "marco.mm89@gmail.com" + } + ], + "description": "Peast is PHP library that generates AST for JavaScript code", + "support": { + "issues": "https://github.com/mck89/peast/issues", + "source": "https://github.com/mck89/peast/tree/v1.16.3" + }, + "time": "2024-07-23T14:00:32+00:00" + }, + { + "name": "mikehaertl/php-shellcommand", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/mikehaertl/php-shellcommand.git", + "reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/e79ea528be155ffdec6f3bf1a4a46307bb49e545", + "reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545", + "shasum": "" + }, + "require": { + "php": ">= 5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">4.0 <=9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "mikehaertl\\shellcommand\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Härtl", + "email": "haertl.mike@gmail.com" + } + ], + "description": "An object oriented interface to shell commands", + "keywords": [ + "shell" + ], + "support": { + "issues": "https://github.com/mikehaertl/php-shellcommand/issues", + "source": "https://github.com/mikehaertl/php-shellcommand/tree/1.7.0" + }, + "time": "2023-04-19T08:25:22+00:00" + }, + { + "name": "mikemclin/laravel-wp-password", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/mikemclin/laravel-wp-password.git", + "reference": "5225c95f75aa0a5ad4040ec2074d1c8d7f10b5f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikemclin/laravel-wp-password/zipball/5225c95f75aa0a5ad4040ec2074d1c8d7f10b5f4", + "reference": "5225c95f75aa0a5ad4040ec2074d1c8d7f10b5f4", + "shasum": "" + }, + "require": { + "bordoni/phpass": "0.3.*", + "illuminate/support": ">=4.0.0", + "php": ">=5.3.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "^2.2" + }, + "type": "laravel-package", + "extra": { + "laravel": { + "aliases": { + "WpPassword": "MikeMcLin\\WpPassword\\Facades\\WpPassword" + }, + "providers": [ + "MikeMcLin\\WpPassword\\WpPasswordProvider" + ] + } + }, + "autoload": { + "psr-4": { + "MikeMcLin\\WpPassword\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike McLin", + "email": "mike@mikemclin.com", + "homepage": "http://mikemclin.net" + } + ], + "description": "Laravel package that checks and creates WordPress password hashes", + "homepage": "https://github.com/mikemclin/laravel-wp-password", + "keywords": [ + "hashing", + "laravel", + "password", + "wordpress" + ], + "support": { + "issues": "https://github.com/mikemclin/laravel-wp-password/issues", + "source": "https://github.com/mikemclin/laravel-wp-password/tree/2.0.3" + }, + "time": "2021-09-30T13:48:57+00:00" + }, + { + "name": "mustache/mustache", + "version": "v2.14.2", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/mustache.php.git", + "reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/e62b7c3849d22ec55f3ec425507bf7968193a6cb", + "reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~1.11", + "phpunit/phpunit": "~3.7|~4.0|~5.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Mustache": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "A Mustache implementation in PHP.", + "homepage": "https://github.com/bobthecow/mustache.php", + "keywords": [ + "mustache", + "templating" + ], + "support": { + "issues": "https://github.com/bobthecow/mustache.php/issues", + "source": "https://github.com/bobthecow/mustache.php/tree/v2.14.2" + }, + "time": "2022-08-23T13:07:01+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-11-08T17:47:46+00:00" + }, + { + "name": "nb/oxymel", + "version": "v0.1.0", + "source": { + "type": "git", + "url": "https://github.com/nb/oxymel.git", + "reference": "cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nb/oxymel/zipball/cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c", + "reference": "cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "type": "library", + "autoload": { + "psr-0": { + "Oxymel": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nikolay Bachiyski", + "email": "nb@nikolay.bg", + "homepage": "http://extrapolate.me/" + } + ], + "description": "A sweet XML builder", + "homepage": "https://github.com/nb/oxymel", + "keywords": [ + "xml" + ], + "support": { + "issues": "https://github.com/nb/oxymel/issues", + "source": "https://github.com/nb/oxymel/tree/master" + }, + "time": "2013-02-24T15:01:54+00:00" + }, + { + "name": "nesbot/carbon", + "version": "3.8.2", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e1268cdbc486d97ce23fef2c666dc3c6b6de9947", + "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.57.2", + "kylekatarnls/multi-tester": "^2.5.3", + "ondrejmirtes/better-reflection": "^6.25.0.4", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.11.2", + "phpunit/phpunit": "^10.5.20", + "squizlabs/php_codesniffer": "^3.9.0" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev", + "dev-2.x": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2024-11-07T17:46:48+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "php-webdriver/webdriver", + "version": "1.15.2", + "source": { + "type": "git", + "url": "https://github.com/php-webdriver/php-webdriver.git", + "reference": "998e499b786805568deaf8cbf06f4044f05d91bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/998e499b786805568deaf8cbf06f4044f05d91bf", + "reference": "998e499b786805568deaf8cbf06f4044f05d91bf", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-zip": "*", + "php": "^7.3 || ^8.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/process": "^5.0 || ^6.0 || ^7.0" + }, + "replace": { + "facebook/webdriver": "*" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.20.0", + "ondram/ci-detector": "^4.0", + "php-coveralls/php-coveralls": "^2.4", + "php-mock/php-mock-phpunit": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "autoload": { + "files": [ + "lib/Exception/TimeoutException.php" + ], + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.", + "homepage": "https://github.com/php-webdriver/php-webdriver", + "keywords": [ + "Chromedriver", + "geckodriver", + "php", + "selenium", + "webdriver" + ], + "support": { + "issues": "https://github.com/php-webdriver/php-webdriver/issues", + "source": "https://github.com/php-webdriver/php-webdriver/tree/1.15.2" + }, + "time": "2024-11-21T15:12:59+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.32", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-22T04:23:01+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.22", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.5.0 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-12-05T13:48:26+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:30:58+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:33:00+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:35:11+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-14T16:00:52+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "seld/jsonlint", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "reference": "1748aaf847fc731cfad7725aec413ee46f0cc3a2", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "support": { + "issues": "https://github.com/Seldaek/jsonlint/issues", + "source": "https://github.com/Seldaek/jsonlint/tree/1.11.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" + } + ], + "time": "2024-07-11T14:55:45+00:00" + }, + { + "name": "seld/phar-utils", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/phar-utils.git", + "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c", + "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\PharUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "PHAR file format utilities, for when PHP phars you up", + "keywords": [ + "phar" + ], + "support": { + "issues": "https://github.com/Seldaek/phar-utils/issues", + "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1" + }, + "time": "2022-08-31T10:31:18+00:00" + }, + { + "name": "seld/signal-handler", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/signal-handler.git", + "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", + "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "require-dev": { + "phpstan/phpstan": "^1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^7.5.20 || ^8.5.23", + "psr/log": "^1 || ^2 || ^3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\Signal\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development", + "keywords": [ + "posix", + "sigint", + "signal", + "sigterm", + "unix" + ], + "support": { + "issues": "https://github.com/Seldaek/signal-handler/issues", + "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2" + }, + "time": "2023-09-03T09:24:00+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "03cce39764429e07fbab9b989a1182a24578341d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/03cce39764429e07fbab9b989a1182a24578341d", + "reference": "03cce39764429e07fbab9b989a1182a24578341d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/dom-crawler": "^4.4|^5.0|^6.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/css-selector": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "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": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/browser-kit/tree/v5.4.45" + }, + "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": "2024-10-22T13:05:35+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.2.0" + }, + "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": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/4f7f3c35fba88146b56d0025d20ace3f3901f097", + "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v5.4.45" + }, + "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": "2024-09-25T14:11:13+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v5.4.48", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "b57df76f4757a9a8dfbb57ba48d7780cc20776c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b57df76f4757a9a8dfbb57ba48d7780cc20776c6", + "reference": "b57df76f4757a9a8dfbb57ba48d7780cc20776c6", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "masterminds/html5": "<2.6" + }, + "require-dev": { + "masterminds/html5": "^2.6", + "symfony/css-selector": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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 DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v5.4.48" + }, + "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": "2024-11-13T14:36:38+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9", + "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "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\\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.45" + }, + "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": "2024-09-25T14:11:13+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.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/v3.5.1" + }, + "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": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + }, + "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": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.2.0" + }, + "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": "2024-11-06T14:24:19+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.4.13", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/bee9bfabfa8b4045a66bf82520e492cddbaffa66", + "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.18|^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.4.13" + }, + "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": "2024-09-27T18:14:25+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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 translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + }, + "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": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/yaml", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "a454d47278cc16a5db371fe73ae66a78a633371e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a454d47278cc16a5db371fe73ae66a78a633371e", + "reference": "a454d47278cc16a5db371fe73ae66a78a633371e", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.3" + }, + "require-dev": { + "symfony/console": "^5.3|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.4.45" + }, + "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": "2024-09-25T14:11:13+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "vria/nodiacritic", + "version": "0.1.2", + "source": { + "type": "git", + "url": "https://github.com/vria/nodiacritic.git", + "reference": "3efeb60fb2586fe3ce8ff0f3c122d380717b8b07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vria/nodiacritic/zipball/3efeb60fb2586fe3ce8ff0f3c122d380717b8b07", + "reference": "3efeb60fb2586fe3ce8ff0f3c122d380717b8b07", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "4.8.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "VRia\\Utils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0" + ], + "authors": [ + { + "name": "Riabchenko Vlad", + "email": "contact@vria.eu", + "homepage": "http://vria.eu" + } + ], + "description": "Tiny helper function that removes all diacritical signs from characters", + "homepage": "https://github.com/vria/nodiacritic", + "keywords": [ + "accent", + "diacritic", + "filter", + "string", + "text" + ], + "support": { + "email": "contact@vria.eu", + "issues": "https://github.com/vria/nodiacritic/issues", + "source": "https://github.com/vria/nodiacritic/tree/0.1.2" + }, + "time": "2016-09-17T22:03:11+00:00" + }, + { + "name": "wp-cli/cache-command", + "version": "v2.1.3", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/cache-command.git", + "reference": "1dbb59e5ed126b9a2fa9d521d29910f3f4eb0f97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/cache-command/zipball/1dbb59e5ed126b9a2fa9d521d29910f3f4eb0f97", + "reference": "1dbb59e5ed126b9a2fa9d521d29910f3f4eb0f97", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "cache", + "cache add", + "cache decr", + "cache delete", + "cache flush", + "cache flush-group", + "cache get", + "cache incr", + "cache replace", + "cache set", + "cache supports", + "cache type", + "transient", + "transient delete", + "transient get", + "transient set", + "transient type", + "transient list" + ] + }, + "autoload": { + "files": [ + "cache-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Manages object and transient caches.", + "homepage": "https://github.com/wp-cli/cache-command", + "support": { + "issues": "https://github.com/wp-cli/cache-command/issues", + "source": "https://github.com/wp-cli/cache-command/tree/v2.1.3" + }, + "time": "2024-04-26T14:54:22+00:00" + }, + { + "name": "wp-cli/checksum-command", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/checksum-command.git", + "reference": "bc82cfb0b1e24eec99cd1bfa515a62c63bd46936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/bc82cfb0b1e24eec99cd1bfa515a62c63bd46936", + "reference": "bc82cfb0b1e24eec99cd1bfa515a62c63bd46936", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "core verify-checksums", + "plugin verify-checksums" + ] + }, + "autoload": { + "files": [ + "checksum-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Verifies file integrity by comparing to published checksums.", + "homepage": "https://github.com/wp-cli/checksum-command", + "support": { + "issues": "https://github.com/wp-cli/checksum-command/issues", + "source": "https://github.com/wp-cli/checksum-command/tree/v2.3.0" + }, + "time": "2024-10-01T21:53:46+00:00" + }, + { + "name": "wp-cli/config-command", + "version": "v2.3.7", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/config-command.git", + "reference": "effb7898bc6ffdaf8a0666432f3c8e35b715858e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/config-command/zipball/effb7898bc6ffdaf8a0666432f3c8e35b715858e", + "reference": "effb7898bc6ffdaf8a0666432f3c8e35b715858e", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5", + "wp-cli/wp-config-transformer": "^1.4.0" + }, + "require-dev": { + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4.2.8" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "config", + "config edit", + "config delete", + "config create", + "config get", + "config has", + "config is-true", + "config list", + "config path", + "config set", + "config shuffle-salts" + ] + }, + "autoload": { + "files": [ + "config-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + }, + { + "name": "Alain Schlesser", + "email": "alain.schlesser@gmail.com", + "homepage": "https://www.alainschlesser.com" + } + ], + "description": "Generates and reads the wp-config.php file.", + "homepage": "https://github.com/wp-cli/config-command", + "support": { + "issues": "https://github.com/wp-cli/config-command/issues", + "source": "https://github.com/wp-cli/config-command/tree/v2.3.7" + }, + "time": "2024-10-01T10:19:18+00:00" + }, + { + "name": "wp-cli/core-command", + "version": "v2.1.18", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/core-command.git", + "reference": "f7580f93fe66a5584fa7b7c42bd2c0c1435c9d2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/core-command/zipball/f7580f93fe66a5584fa7b7c42bd2c0c1435c9d2e", + "reference": "f7580f93fe66a5584fa7b7c42bd2c0c1435c9d2e", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4 || ^2 || ^3", + "wp-cli/wp-cli": "^2.5.1" + }, + "require-dev": { + "wp-cli/checksum-command": "^1 || ^2", + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "core", + "core check-update", + "core download", + "core install", + "core is-installed", + "core multisite-convert", + "core multisite-install", + "core update", + "core update-db", + "core version" + ] + }, + "autoload": { + "files": [ + "core-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Downloads, installs, updates, and manages a WordPress installation.", + "homepage": "https://github.com/wp-cli/core-command", + "support": { + "issues": "https://github.com/wp-cli/core-command/issues", + "source": "https://github.com/wp-cli/core-command/tree/v2.1.18" + }, + "time": "2024-04-12T09:36:36+00:00" + }, + { + "name": "wp-cli/cron-command", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/cron-command.git", + "reference": "46f849f2f0ba859c6acd356eefc76769c8381ae5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/cron-command/zipball/46f849f2f0ba859c6acd356eefc76769c8381ae5", + "reference": "46f849f2f0ba859c6acd356eefc76769c8381ae5", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/eval-command": "^2.0", + "wp-cli/server-command": "^2.0", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "cron", + "cron test", + "cron event", + "cron event delete", + "cron event list", + "cron event run", + "cron event schedule", + "cron schedule", + "cron schedule list", + "cron event unschedule" + ] + }, + "autoload": { + "files": [ + "cron-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Tests, runs, and deletes WP-Cron events; manages WP-Cron schedules.", + "homepage": "https://github.com/wp-cli/cron-command", + "support": { + "issues": "https://github.com/wp-cli/cron-command/issues", + "source": "https://github.com/wp-cli/cron-command/tree/v2.3.1" + }, + "time": "2024-10-01T10:30:28+00:00" + }, + { + "name": "wp-cli/db-command", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/db-command.git", + "reference": "d4c0dd25ec8b3d0118a2400cf6b87e8d08b77c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/db-command/zipball/d4c0dd25ec8b3d0118a2400cf6b87e8d08b77c43", + "reference": "d4c0dd25ec8b3d0118a2400cf6b87e8d08b77c43", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "db", + "db clean", + "db create", + "db drop", + "db reset", + "db check", + "db optimize", + "db prefix", + "db repair", + "db cli", + "db query", + "db export", + "db import", + "db search", + "db tables", + "db size", + "db columns" + ] + }, + "autoload": { + "files": [ + "db-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Performs basic database operations using credentials stored in wp-config.php.", + "homepage": "https://github.com/wp-cli/db-command", + "support": { + "issues": "https://github.com/wp-cli/db-command/issues", + "source": "https://github.com/wp-cli/db-command/tree/v2.1.2" + }, + "time": "2024-10-01T10:48:48+00:00" + }, + { + "name": "wp-cli/embed-command", + "version": "v2.0.17", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/embed-command.git", + "reference": "ece56cafcb8ef0a05dac9e41b5ab852ecd57b02c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/embed-command/zipball/ece56cafcb8ef0a05dac9e41b5ab852ecd57b02c", + "reference": "ece56cafcb8ef0a05dac9e41b5ab852ecd57b02c", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "embed", + "embed fetch", + "embed provider", + "embed provider list", + "embed provider match", + "embed handler", + "embed handler list", + "embed cache", + "embed cache clear", + "embed cache find", + "embed cache trigger" + ] + }, + "autoload": { + "files": [ + "embed-command.php" + ], + "psr-4": { + "WP_CLI\\Embeds\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pascal Birchler", + "homepage": "https://pascalbirchler.com/" + } + ], + "description": "Inspects oEmbed providers, clears embed cache, and more.", + "homepage": "https://github.com/wp-cli/embed-command", + "support": { + "issues": "https://github.com/wp-cli/embed-command/issues", + "source": "https://github.com/wp-cli/embed-command/tree/v2.0.17" + }, + "time": "2024-10-01T10:30:42+00:00" + }, + { + "name": "wp-cli/entity-command", + "version": "v2.8.2", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/entity-command.git", + "reference": "9dad0753ecba347d5fbdb6b80d01e38768bca4ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/9dad0753ecba347d5fbdb6b80d01e38768bca4ea", + "reference": "9dad0753ecba347d5fbdb6b80d01e38768bca4ea", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.11" + }, + "require-dev": { + "wp-cli/cache-command": "^1 || ^2", + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/media-command": "^1.1 || ^2", + "wp-cli/super-admin-command": "^1 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "comment", + "comment approve", + "comment count", + "comment create", + "comment delete", + "comment exists", + "comment generate", + "comment get", + "comment list", + "comment meta", + "comment meta add", + "comment meta delete", + "comment meta get", + "comment meta list", + "comment meta patch", + "comment meta pluck", + "comment meta update", + "comment recount", + "comment spam", + "comment status", + "comment trash", + "comment unapprove", + "comment unspam", + "comment untrash", + "comment update", + "menu", + "menu create", + "menu delete", + "menu item", + "menu item add-custom", + "menu item add-post", + "menu item add-term", + "menu item delete", + "menu item list", + "menu item update", + "menu list", + "menu location", + "menu location assign", + "menu location list", + "menu location remove", + "network meta", + "network meta add", + "network meta delete", + "network meta get", + "network meta list", + "network meta patch", + "network meta pluck", + "network meta update", + "option", + "option add", + "option delete", + "option get", + "option list", + "option patch", + "option pluck", + "option update", + "option set-autoload", + "option get-autoload", + "post", + "post create", + "post delete", + "post edit", + "post exists", + "post generate", + "post get", + "post list", + "post meta", + "post meta add", + "post meta clean-duplicates", + "post meta delete", + "post meta get", + "post meta list", + "post meta patch", + "post meta pluck", + "post meta update", + "post term", + "post term add", + "post term list", + "post term remove", + "post term set", + "post update", + "post url-to-id", + "post-type", + "post-type get", + "post-type list", + "site", + "site activate", + "site archive", + "site create", + "site generate", + "site deactivate", + "site delete", + "site empty", + "site list", + "site mature", + "site meta", + "site meta add", + "site meta delete", + "site meta get", + "site meta list", + "site meta patch", + "site meta pluck", + "site meta update", + "site option", + "site private", + "site public", + "site spam", + "site unarchive", + "site unmature", + "site unspam", + "taxonomy", + "taxonomy get", + "taxonomy list", + "term", + "term create", + "term delete", + "term generate", + "term get", + "term list", + "term meta", + "term meta add", + "term meta delete", + "term meta get", + "term meta list", + "term meta patch", + "term meta pluck", + "term meta update", + "term recount", + "term update", + "user", + "user add-cap", + "user add-role", + "user application-password", + "user application-password create", + "user application-password delete", + "user application-password exists", + "user application-password get", + "user application-password list", + "user application-password record-usage", + "user application-password update", + "user create", + "user delete", + "user exists", + "user generate", + "user get", + "user import-csv", + "user list", + "user list-caps", + "user meta", + "user meta add", + "user meta delete", + "user meta get", + "user meta list", + "user meta patch", + "user meta pluck", + "user meta update", + "user remove-cap", + "user remove-role", + "user reset-password", + "user session", + "user session destroy", + "user session list", + "user set-role", + "user signup", + "user signup activate", + "user signup delete", + "user signup get", + "user signup list", + "user spam", + "user term", + "user term add", + "user term list", + "user term remove", + "user term set", + "user unspam", + "user update" + ] + }, + "autoload": { + "files": [ + "entity-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Manage WordPress comments, menus, options, posts, sites, terms, and users.", + "homepage": "https://github.com/wp-cli/entity-command", + "support": { + "issues": "https://github.com/wp-cli/entity-command/issues", + "source": "https://github.com/wp-cli/entity-command/tree/v2.8.2" + }, + "time": "2024-10-01T10:44:33+00:00" + }, + { + "name": "wp-cli/eval-command", + "version": "v2.2.5", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/eval-command.git", + "reference": "1fd2dc9ae74f5fcde7a9b861a1073d6f19952b74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/eval-command/zipball/1fd2dc9ae74f5fcde7a9b861a1073d6f19952b74", + "reference": "1fd2dc9ae74f5fcde7a9b861a1073d6f19952b74", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "eval", + "eval-file" + ] + }, + "autoload": { + "files": [ + "eval-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Executes arbitrary PHP code or files.", + "homepage": "https://github.com/wp-cli/eval-command", + "support": { + "issues": "https://github.com/wp-cli/eval-command/issues", + "source": "https://github.com/wp-cli/eval-command/tree/v2.2.5" + }, + "time": "2024-10-01T10:30:51+00:00" + }, + { + "name": "wp-cli/export-command", + "version": "v2.1.13", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/export-command.git", + "reference": "eeafa03095b80d2648d1a67b00c688be9d418aff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/export-command/zipball/eeafa03095b80d2648d1a67b00c688be9d418aff", + "reference": "eeafa03095b80d2648d1a67b00c688be9d418aff", + "shasum": "" + }, + "require": { + "nb/oxymel": "~0.1.0", + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/import-command": "^1 || ^2", + "wp-cli/media-command": "^1 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "export" + ] + }, + "autoload": { + "files": [ + "export-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Exports WordPress content to a WXR file.", + "homepage": "https://github.com/wp-cli/export-command", + "support": { + "issues": "https://github.com/wp-cli/export-command/issues", + "source": "https://github.com/wp-cli/export-command/tree/v2.1.13" + }, + "time": "2024-10-01T10:31:03+00:00" + }, + { + "name": "wp-cli/extension-command", + "version": "v2.1.23", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/extension-command.git", + "reference": "c307a11e7ea078cfd52177eefeef9906aa69edcd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/c307a11e7ea078cfd52177eefeef9906aa69edcd", + "reference": "c307a11e7ea078cfd52177eefeef9906aa69edcd", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4 || ^2 || ^3", + "wp-cli/wp-cli": "^2.10" + }, + "require-dev": { + "wp-cli/cache-command": "^2.0", + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/language-command": "^2.0", + "wp-cli/scaffold-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "plugin", + "plugin activate", + "plugin deactivate", + "plugin delete", + "plugin get", + "plugin install", + "plugin is-installed", + "plugin list", + "plugin path", + "plugin search", + "plugin status", + "plugin toggle", + "plugin uninstall", + "plugin update", + "theme", + "theme activate", + "theme delete", + "theme disable", + "theme enable", + "theme get", + "theme install", + "theme is-installed", + "theme list", + "theme mod", + "theme mod get", + "theme mod set", + "theme mod remove", + "theme path", + "theme search", + "theme status", + "theme update", + "theme mod list" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "files": [ + "extension-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + }, + { + "name": "Alain Schlesser", + "email": "alain.schlesser@gmail.com", + "homepage": "https://www.alainschlesser.com" + } + ], + "description": "Manages plugins and themes, including installs, activations, and updates.", + "homepage": "https://github.com/wp-cli/extension-command", + "support": { + "issues": "https://github.com/wp-cli/extension-command/issues", + "source": "https://github.com/wp-cli/extension-command/tree/v2.1.23" + }, + "time": "2024-10-01T10:44:18+00:00" + }, + { + "name": "wp-cli/i18n-command", + "version": "v2.6.3", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/i18n-command.git", + "reference": "065bb3758fcbff922f1b7a01ab702aab0da79803" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/065bb3758fcbff922f1b7a01ab702aab0da79803", + "reference": "065bb3758fcbff922f1b7a01ab702aab0da79803", + "shasum": "" + }, + "require": { + "eftec/bladeone": "3.52", + "gettext/gettext": "^4.8", + "mck89/peast": "^1.13.11", + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/scaffold-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "suggest": { + "ext-json": "Used for reading and generating JSON translation files", + "ext-mbstring": "Used for calculating include/exclude matches in code extraction" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "i18n", + "i18n make-pot", + "i18n make-json", + "i18n make-mo", + "i18n make-php", + "i18n update-po" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "autoload": { + "files": [ + "i18n-command.php" + ], + "psr-4": { + "WP_CLI\\I18n\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pascal Birchler", + "homepage": "https://pascalbirchler.com/" + } + ], + "description": "Provides internationalization tools for WordPress projects.", + "homepage": "https://github.com/wp-cli/i18n-command", + "support": { + "issues": "https://github.com/wp-cli/i18n-command/issues", + "source": "https://github.com/wp-cli/i18n-command/tree/v2.6.3" + }, + "time": "2024-10-01T11:16:25+00:00" + }, + { + "name": "wp-cli/import-command", + "version": "v2.0.13", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/import-command.git", + "reference": "22f32451046c1d8e7963ff96d95942af14fbb4e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/import-command/zipball/22f32451046c1d8e7963ff96d95942af14fbb4e9", + "reference": "22f32451046c1d8e7963ff96d95942af14fbb4e9", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/export-command": "^1 || ^2", + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "import" + ] + }, + "autoload": { + "files": [ + "import-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Imports content from a given WXR file.", + "homepage": "https://github.com/wp-cli/import-command", + "support": { + "issues": "https://github.com/wp-cli/import-command/issues", + "source": "https://github.com/wp-cli/import-command/tree/v2.0.13" + }, + "time": "2024-10-01T10:44:58+00:00" + }, + { + "name": "wp-cli/language-command", + "version": "v2.0.22", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/language-command.git", + "reference": "27db28eca5f7627c7fbd8da82c6c51eb05e7858e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/language-command/zipball/27db28eca5f7627c7fbd8da82c6c51eb05e7858e", + "reference": "27db28eca5f7627c7fbd8da82c6c51eb05e7858e", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "language", + "language core", + "language core activate", + "language core is-installed", + "language core install", + "language core list", + "language core uninstall", + "language core update", + "language plugin", + "language plugin is-installed", + "language plugin install", + "language plugin list", + "language plugin uninstall", + "language plugin update", + "language theme", + "language theme is-installed", + "language theme install", + "language theme list", + "language theme uninstall", + "language theme update", + "site switch-language" + ] + }, + "autoload": { + "files": [ + "language-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Installs, activates, and manages language packs.", + "homepage": "https://github.com/wp-cli/language-command", + "support": { + "issues": "https://github.com/wp-cli/language-command/issues", + "source": "https://github.com/wp-cli/language-command/tree/v2.0.22" + }, + "time": "2024-10-01T10:45:06+00:00" + }, + { + "name": "wp-cli/maintenance-mode-command", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/maintenance-mode-command.git", + "reference": "d560d7f42fb21e1fc182d69e0cdf06c69891791d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/maintenance-mode-command/zipball/d560d7f42fb21e1fc182d69e0cdf06c69891791d", + "reference": "d560d7f42fb21e1fc182d69e0cdf06c69891791d", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "maintenance-mode", + "maintenance-mode activate", + "maintenance-mode deactivate", + "maintenance-mode status", + "maintenance-mode is-active" + ] + }, + "autoload": { + "files": [ + "maintenance-mode-command.php" + ], + "psr-4": { + "WP_CLI\\MaintenanceMode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thrijith Thankachan", + "email": "thrijith13@gmail.com", + "homepage": "https://thrijith.com" + } + ], + "description": "Activates, deactivates or checks the status of the maintenance mode of a site.", + "homepage": "https://github.com/wp-cli/maintenance-mode-command", + "support": { + "issues": "https://github.com/wp-cli/maintenance-mode-command/issues", + "source": "https://github.com/wp-cli/maintenance-mode-command/tree/v2.1.2" + }, + "time": "2024-10-01T10:45:18+00:00" + }, + { + "name": "wp-cli/media-command", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/media-command.git", + "reference": "5e2d34d7d01c87d1f50b4838512b3501f5ca6f9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/5e2d34d7d01c87d1f50b4838512b3501f5ca6f9a", + "reference": "5e2d34d7d01c87d1f50b4838512b3501f5ca6f9a", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/extension-command": "^2.0", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "media", + "media import", + "media regenerate", + "media image-size" + ] + }, + "autoload": { + "files": [ + "media-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Imports files as attachments, regenerates thumbnails, or lists registered image sizes.", + "homepage": "https://github.com/wp-cli/media-command", + "support": { + "issues": "https://github.com/wp-cli/media-command/issues", + "source": "https://github.com/wp-cli/media-command/tree/v2.2.1" + }, + "time": "2024-10-01T10:45:30+00:00" + }, + { + "name": "wp-cli/mustangostang-spyc", + "version": "0.6.3", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/spyc.git", + "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/spyc/zipball/6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", + "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "4.3.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.5.x-dev" + } + }, + "autoload": { + "files": [ + "includes/functions.php" + ], + "psr-4": { + "Mustangostang\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "mustangostang", + "email": "vlad.andersen@gmail.com" + } + ], + "description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)", + "homepage": "https://github.com/mustangostang/spyc/", + "support": { + "source": "https://github.com/wp-cli/spyc/tree/autoload" + }, + "time": "2017-04-25T11:26:20+00:00" + }, + { + "name": "wp-cli/package-command", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/package-command.git", + "reference": "9dc4084c66547049ab863e293f427f8c0d099b18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/package-command/zipball/9dc4084c66547049ab863e293f427f8c0d099b18", + "reference": "9dc4084c66547049ab863e293f427f8c0d099b18", + "shasum": "" + }, + "require": { + "composer/composer": "^1.10.23 || ^2.2.17", + "ext-json": "*", + "wp-cli/wp-cli": "^2.8" + }, + "require-dev": { + "wp-cli/scaffold-command": "^1 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "package", + "package browse", + "package install", + "package list", + "package update", + "package uninstall" + ] + }, + "autoload": { + "files": [ + "package-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Lists, installs, and removes WP-CLI packages.", + "homepage": "https://github.com/wp-cli/package-command", + "support": { + "issues": "https://github.com/wp-cli/package-command/issues", + "source": "https://github.com/wp-cli/package-command/tree/v2.5.3" + }, + "time": "2024-10-01T11:13:44+00:00" + }, + { + "name": "wp-cli/php-cli-tools", + "version": "v0.11.22", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/php-cli-tools.git", + "reference": "a6bb94664ca36d0962f9c2ff25591c315a550c51" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/a6bb94664ca36d0962f9c2ff25591c315a550c51", + "reference": "a6bb94664ca36d0962f9c2ff25591c315a550c51", + "shasum": "" + }, + "require": { + "php": ">= 5.3.0" + }, + "require-dev": { + "roave/security-advisories": "dev-latest", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.11.x-dev" + } + }, + "autoload": { + "files": [ + "lib/cli/cli.php" + ], + "psr-0": { + "cli": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@handbuilt.co", + "role": "Maintainer" + }, + { + "name": "James Logsdon", + "email": "jlogsdon@php.net", + "role": "Developer" + } + ], + "description": "Console utilities for PHP", + "homepage": "http://github.com/wp-cli/php-cli-tools", + "keywords": [ + "cli", + "console" + ], + "support": { + "issues": "https://github.com/wp-cli/php-cli-tools/issues", + "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.11.22" + }, + "time": "2023-12-03T19:25:05+00:00" + }, + { + "name": "wp-cli/rewrite-command", + "version": "v2.0.14", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/rewrite-command.git", + "reference": "0dd0d11918eaaf2fcad5bc13646ecf266ffa83e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/rewrite-command/zipball/0dd0d11918eaaf2fcad5bc13646ecf266ffa83e9", + "reference": "0dd0d11918eaaf2fcad5bc13646ecf266ffa83e9", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "rewrite", + "rewrite flush", + "rewrite list", + "rewrite structure" + ] + }, + "autoload": { + "files": [ + "rewrite-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Lists or flushes the site's rewrite rules, updates the permalink structure.", + "homepage": "https://github.com/wp-cli/rewrite-command", + "support": { + "issues": "https://github.com/wp-cli/rewrite-command/issues", + "source": "https://github.com/wp-cli/rewrite-command/tree/v2.0.14" + }, + "time": "2024-10-01T10:45:45+00:00" + }, + { + "name": "wp-cli/role-command", + "version": "v2.0.15", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/role-command.git", + "reference": "f92efbf92a0bb4b34e1de9523d9cbd393d406ba2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/role-command/zipball/f92efbf92a0bb4b34e1de9523d9cbd393d406ba2", + "reference": "f92efbf92a0bb4b34e1de9523d9cbd393d406ba2", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "role", + "role create", + "role delete", + "role exists", + "role list", + "role reset", + "cap", + "cap add", + "cap list", + "cap remove" + ] + }, + "autoload": { + "files": [ + "role-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Adds, removes, lists, and resets roles and capabilities.", + "homepage": "https://github.com/wp-cli/role-command", + "support": { + "issues": "https://github.com/wp-cli/role-command/issues", + "source": "https://github.com/wp-cli/role-command/tree/v2.0.15" + }, + "time": "2024-10-01T10:46:02+00:00" + }, + { + "name": "wp-cli/scaffold-command", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/scaffold-command.git", + "reference": "d67d8348f653d00438535ec4389ab9259ef6fb8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/scaffold-command/zipball/d67d8348f653d00438535ec4389ab9259ef6fb8f", + "reference": "d67d8348f653d00438535ec4389ab9259ef6fb8f", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "scaffold", + "scaffold underscores", + "scaffold block", + "scaffold child-theme", + "scaffold plugin", + "scaffold plugin-tests", + "scaffold post-type", + "scaffold taxonomy", + "scaffold theme-tests" + ] + }, + "autoload": { + "files": [ + "scaffold-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Generates code for post types, taxonomies, blocks, plugins, child themes, etc.", + "homepage": "https://github.com/wp-cli/scaffold-command", + "support": { + "issues": "https://github.com/wp-cli/scaffold-command/issues", + "source": "https://github.com/wp-cli/scaffold-command/tree/v2.4.0" + }, + "time": "2024-10-01T11:13:37+00:00" + }, + { + "name": "wp-cli/search-replace-command", + "version": "v2.1.7", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/search-replace-command.git", + "reference": "89e1653c9b888179a121a8354c75fc5e8ca7931d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/89e1653c9b888179a121a8354c75fc5e8ca7931d", + "reference": "89e1653c9b888179a121a8354c75fc5e8ca7931d", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "search-replace" + ] + }, + "autoload": { + "files": [ + "search-replace-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Searches/replaces strings in the database.", + "homepage": "https://github.com/wp-cli/search-replace-command", + "support": { + "issues": "https://github.com/wp-cli/search-replace-command/issues", + "source": "https://github.com/wp-cli/search-replace-command/tree/v2.1.7" + }, + "time": "2024-06-28T09:30:38+00:00" + }, + { + "name": "wp-cli/server-command", + "version": "v2.0.14", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/server-command.git", + "reference": "012e10d3281866235cbf626f38a27169d6c6e13b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/server-command/zipball/012e10d3281866235cbf626f38a27169d6c6e13b", + "reference": "012e10d3281866235cbf626f38a27169d6c6e13b", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "server" + ] + }, + "autoload": { + "files": [ + "server-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Launches PHP's built-in web server for a specific WordPress installation.", + "homepage": "https://github.com/wp-cli/server-command", + "support": { + "issues": "https://github.com/wp-cli/server-command/issues", + "source": "https://github.com/wp-cli/server-command/tree/v2.0.14" + }, + "time": "2024-10-01T10:46:38+00:00" + }, + { + "name": "wp-cli/shell-command", + "version": "v2.0.15", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/shell-command.git", + "reference": "2c38ef12a912b23224c7f2abd5bc716a889340fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/shell-command/zipball/2c38ef12a912b23224c7f2abd5bc716a889340fb", + "reference": "2c38ef12a912b23224c7f2abd5bc716a889340fb", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "shell" + ] + }, + "autoload": { + "files": [ + "shell-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Opens an interactive PHP console for running and testing PHP code.", + "homepage": "https://github.com/wp-cli/shell-command", + "support": { + "issues": "https://github.com/wp-cli/shell-command/issues", + "source": "https://github.com/wp-cli/shell-command/tree/v2.0.15" + }, + "time": "2024-10-01T10:46:50+00:00" + }, + { + "name": "wp-cli/super-admin-command", + "version": "v2.0.15", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/super-admin-command.git", + "reference": "ecd9cee09918eb34f60c05944cc188f4916cb026" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/super-admin-command/zipball/ecd9cee09918eb34f60c05944cc188f4916cb026", + "reference": "ecd9cee09918eb34f60c05944cc188f4916cb026", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "super-admin", + "super-admin add", + "super-admin list", + "super-admin remove" + ] + }, + "autoload": { + "files": [ + "super-admin-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Lists, adds, or removes super admin users on a multisite installation.", + "homepage": "https://github.com/wp-cli/super-admin-command", + "support": { + "issues": "https://github.com/wp-cli/super-admin-command/issues", + "source": "https://github.com/wp-cli/super-admin-command/tree/v2.0.15" + }, + "time": "2024-10-01T10:48:29+00:00" + }, + { + "name": "wp-cli/widget-command", + "version": "v2.1.11", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/widget-command.git", + "reference": "c50cd32e4e3d16bf29821ae0208b7154ef6f9031" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/widget-command/zipball/c50cd32e4e3d16bf29821ae0208b7154ef6f9031", + "reference": "c50cd32e4e3d16bf29821ae0208b7154ef6f9031", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.5" + }, + "require-dev": { + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + }, + "bundled": true, + "commands": [ + "widget", + "widget add", + "widget deactivate", + "widget delete", + "widget list", + "widget move", + "widget reset", + "widget update", + "sidebar", + "sidebar list" + ] + }, + "autoload": { + "files": [ + "widget-command.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Bachhuber", + "email": "daniel@runcommand.io", + "homepage": "https://runcommand.io" + } + ], + "description": "Adds, moves, and removes widgets; lists sidebars.", + "homepage": "https://github.com/wp-cli/widget-command", + "support": { + "issues": "https://github.com/wp-cli/widget-command/issues", + "source": "https://github.com/wp-cli/widget-command/tree/v2.1.11" + }, + "time": "2024-10-01T10:48:21+00:00" + }, + { + "name": "wp-cli/wp-cli", + "version": "v2.11.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/wp-cli.git", + "reference": "53f0df112901fcf95099d0f501912a209429b6a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/53f0df112901fcf95099d0f501912a209429b6a9", + "reference": "53f0df112901fcf95099d0f501912a209429b6a9", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "mustache/mustache": "^2.14.1", + "php": "^5.6 || ^7.0 || ^8.0", + "symfony/finder": ">2.7", + "wp-cli/mustangostang-spyc": "^0.6.3", + "wp-cli/php-cli-tools": "~0.11.2" + }, + "require-dev": { + "roave/security-advisories": "dev-latest", + "wp-cli/db-command": "^1.3 || ^2", + "wp-cli/entity-command": "^1.2 || ^2", + "wp-cli/extension-command": "^1.1 || ^2", + "wp-cli/package-command": "^1 || ^2", + "wp-cli/wp-cli-tests": "^4.0.1" + }, + "suggest": { + "ext-readline": "Include for a better --prompt implementation", + "ext-zip": "Needed to support extraction of ZIP archives when doing downloads or updates" + }, + "bin": [ + "bin/wp", + "bin/wp.bat" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.11.x-dev" + } + }, + "autoload": { + "psr-0": { + "WP_CLI\\": "php/" + }, + "classmap": [ + "php/class-wp-cli.php", + "php/class-wp-cli-command.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WP-CLI framework", + "homepage": "https://wp-cli.org", + "keywords": [ + "cli", + "wordpress" + ], + "support": { + "docs": "https://make.wordpress.org/cli/handbook/", + "issues": "https://github.com/wp-cli/wp-cli/issues", + "source": "https://github.com/wp-cli/wp-cli" + }, + "time": "2024-08-08T03:04:55+00:00" + }, + { + "name": "wp-cli/wp-cli-bundle", + "version": "v2.11.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/wp-cli-bundle.git", + "reference": "f77a284ccf92023981046edf63111ab427106d05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-cli-bundle/zipball/f77a284ccf92023981046edf63111ab427106d05", + "reference": "f77a284ccf92023981046edf63111ab427106d05", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "wp-cli/cache-command": "^2", + "wp-cli/checksum-command": "^2.1", + "wp-cli/config-command": "^2.1", + "wp-cli/core-command": "^2.1", + "wp-cli/cron-command": "^2", + "wp-cli/db-command": "^2", + "wp-cli/embed-command": "^2", + "wp-cli/entity-command": "^2", + "wp-cli/eval-command": "^2", + "wp-cli/export-command": "^2", + "wp-cli/extension-command": "^2.1", + "wp-cli/i18n-command": "^2", + "wp-cli/import-command": "^2", + "wp-cli/language-command": "^2", + "wp-cli/maintenance-mode-command": "^2", + "wp-cli/media-command": "^2", + "wp-cli/package-command": "^2.1", + "wp-cli/rewrite-command": "^2", + "wp-cli/role-command": "^2", + "wp-cli/scaffold-command": "^2", + "wp-cli/search-replace-command": "^2", + "wp-cli/server-command": "^2", + "wp-cli/shell-command": "^2", + "wp-cli/super-admin-command": "^2", + "wp-cli/widget-command": "^2", + "wp-cli/wp-cli": "^2.11.0" + }, + "require-dev": { + "roave/security-advisories": "dev-latest", + "wp-cli/wp-cli-tests": "^4" + }, + "suggest": { + "psy/psysh": "Enhanced `wp shell` functionality" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.11.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WP-CLI bundle package with default commands.", + "homepage": "https://wp-cli.org", + "keywords": [ + "cli", + "wordpress" + ], + "support": { + "docs": "https://make.wordpress.org/cli/handbook/", + "issues": "https://github.com/wp-cli/wp-cli-bundle/issues", + "source": "https://github.com/wp-cli/wp-cli-bundle" + }, + "time": "2024-08-08T03:29:34+00:00" + }, + { + "name": "wp-cli/wp-config-transformer", + "version": "v1.4.1", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/wp-config-transformer.git", + "reference": "9da378b5a4e28bba3bce4ff4ff04a54d8c9f1a01" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-config-transformer/zipball/9da378b5a4e28bba3bce4ff4ff04a54d8c9f1a01", + "reference": "9da378b5a4e28bba3bce4ff4ff04a54d8c9f1a01", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/WPConfigTransformer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frankie Jarrett", + "email": "fjarrett@gmail.com" + } + ], + "description": "Programmatically edit a wp-config.php file.", + "homepage": "https://github.com/wp-cli/wp-config-transformer", + "support": { + "issues": "https://github.com/wp-cli/wp-config-transformer/issues", + "source": "https://github.com/wp-cli/wp-config-transformer/tree/v1.4.1" + }, + "time": "2024-10-16T12:50:47+00:00" + }, + { + "name": "zordius/lightncandy", + "version": "v1.2.6", + "source": { + "type": "git", + "url": "https://github.com/zordius/lightncandy.git", + "reference": "b451f73e8b5c73e62e365997ba3c993a0376b72a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zordius/lightncandy/zipball/b451f73e8b5c73e62e365997ba3c993a0376b72a", + "reference": "b451f73e8b5c73e62e365997ba3c993a0376b72a", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": ">=7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.5-dev" + } + }, + "autoload": { + "psr-4": { + "LightnCandy\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Zordius Chen", + "email": "zordius@gmail.com" + } + ], + "description": "An extremely fast PHP implementation of handlebars ( http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).", + "homepage": "https://github.com/zordius/lightncandy", + "keywords": [ + "handlebars", + "logicless", + "mustache", + "php", + "template" + ], + "support": { + "issues": "https://github.com/zordius/lightncandy/issues", + "source": "https://github.com/zordius/lightncandy/tree/v1.2.6" + }, + "time": "2021-07-11T04:52:41+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "bc-andreadao/phpdocumentor-markdown": 20, + "bc-andreadao/wp-documentor": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "platform-overrides": { + "php": "8.2" + }, + "plugin-api-version": "2.6.0" +} From a5a4f13f01a2cfa881657f70a6f929b480ea1928 Mon Sep 17 00:00:00 2001 From: bc-andreadao Date: Fri, 17 Jan 2025 11:24:20 -0600 Subject: [PATCH 03/13] add test php files for generating docs --- test/Add_To_Cart-test.php | 218 +++++++++++++++++++++++ test/Checkout-test.php | 75 ++++++++ test/Flusher-test.php | 39 +++++ test/Forms-test.php | 185 ++++++++++++++++++++ test/hooks.php | 90 ++++++++++ test/woocommerce-functions-test.php | 256 ++++++++++++++++++++++++++++ 6 files changed, 863 insertions(+) create mode 100644 test/Add_To_Cart-test.php create mode 100644 test/Checkout-test.php create mode 100644 test/Flusher-test.php create mode 100644 test/Forms-test.php create mode 100644 test/hooks.php create mode 100644 test/woocommerce-functions-test.php diff --git a/test/Add_To_Cart-test.php b/test/Add_To_Cart-test.php new file mode 100644 index 00000000..6981c478 --- /dev/null +++ b/test/Add_To_Cart-test.php @@ -0,0 +1,218 @@ +validate_request( $post_id, $_POST ) ) { + $error = new \WP_Error( 'unknown_product', __( 'We were unable to process your request. Please go back and try again.', 'bigcommerce' ) ); + /** + * Triggered when an error occurs during a form submission. Allows developers to handle or log form submission errors. + * + * @param \WP_Error $error The error object representing the validation or processing error. Contains error codes and messages. + * @param array $submission The sanitized form submission data (usually $_POST). + * @param string $redirect The URL to redirect the user after processing the error. Defaults to the home URL. + */ + do_action( 'bigcommerce/form/error', $error, $_POST, home_url( '/' ) ); + + return; + } + + $product = new Product( $post_id ); + $product_id = $product->bc_id(); + $variant_id = $this->get_variant_id( $product, $_POST ); + + $options = []; + + // Options are sanitized below + $submitted_options = empty( $_POST[ 'option' ] ) ? [] : (array) $_POST[ 'option' ]; // phpcs:ignore + $option_config = $product->options(); + $modifier_config = $product->modifiers(); + foreach ( $option_config as $config ) { + if ( array_key_exists( $config[ 'id' ], $submitted_options ) ) { + $options[ $config[ 'id' ] ] = absint( $submitted_options[ $config[ 'id' ] ] ); + } + } + foreach ( $modifier_config as $config ) { + if ( array_key_exists( $config[ 'id' ], $submitted_options ) ) { + $options[ $config[ 'id' ] ] = $this->sanitize_option( $submitted_options[ $config[ 'id' ] ], $config ); + } + } + + $quantity = array_key_exists( 'quantity', $_POST ) ? absint( $_POST[ 'quantity' ] ) : 1; + + $cart = new Cart( $cart_api ); + try { + $response = $cart->add_line_item( $product_id, $options, $quantity ); + $this->handle_response( $response, $cart, $post_id, $product_id, $variant_id ); + } catch ( ApiException $e ) { + $this->handle_exception( $e, $cart ); + } + } + + /** + * Sanitizes a product option based on its configuration type. + * + * @param mixed $value The value of the option submitted by the user. + * @param array $config The configuration of the option (type, id, etc.). + * + * @return mixed The sanitized option value. + */ + private function sanitize_option( $value, $config ) { + switch ( $config[ 'type' ] ) { + case 'date': + return strtotime( $value ); + case 'multi_line_text': + return sanitize_textarea_field( $value ); + case 'numbers_only_text': + return filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION|FILTER_FLAG_ALLOW_THOUSAND ); + case 'text': + return sanitize_text_field( $value ); + default: // checkboxes, selects, and radios + return (int) $value; + } + } + + /** + * Handles the response from the API after attempting to add a product to the cart. + * + * @param \BigCommerce\Api\v3\Model\Cart|null $response The response from the API. + * @param Cart $cart The cart instance. + * @param int $post_id The ID of the product post. + * @param int $product_id The ID of the product in BigCommerce. + * @param int $variant_id The variant ID for the product. + * + * @return void + */ + protected function handle_response( $response, Cart $cart, $post_id, $product_id, $variant_id ) { + $cart_url = $cart->get_cart_url(); + /** + * Triggered when a form is successfully processed. + * + * @param string $message The message that will display to the user. + * @param array $submission The data submitted to the form. + * @param string $url The URL to redirect the user to. + * @param array $data Additional data to store with the message. + */ + do_action( 'bigcommerce/form/success', __( '1 item added to Cart', 'bigcommerce' ), $_POST, $cart_url, [ + 'key' => 'add_to_cart', + 'cart_id' => $cart->get_cart_id(), + 'post_id' => $post_id, + 'product_id' => $product_id, + 'variant_id' => $variant_id, + ] ); + wp_safe_redirect( esc_url_raw( $cart_url ), 303 ); + exit(); + } + + /** + * Handles exceptions thrown during the cart API process. + * + * @param ApiException $e The exception thrown during the API request. + * @param Cart $cart The cart instance. + * + * @return void + */ + protected function handle_exception( ApiException $e, $cart ) { + if ( strpos( (string) $e->getCode(), '4' ) === 0 ) { + $body = $e->getResponseBody(); + if ( $body && ! empty( $body->title ) ) { + $message = sprintf( '[%d] %s', $e->getCode(), $body->title ); + } else { + $message = $e->getMessage(); + } + $error = new \WP_Error( 'api_error', sprintf( + __( 'There was an error adding this product to your cart. Error message: "%s"', 'bigcommerce' ), + $message + ), [ 'exception' => [ 'message' => $e->getMessage(), 'code' => $e->getCode() ] ] ); + } else { + $error = new \WP_Error( 'api_error', __( 'There was an error adding this product to your cart. It might be out of stock or unavailable.', 'bigcommerce' ), [ + 'exception' => [ + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ], + ] ); + } + do_action( 'bigcommerce/form/error', $error, $_POST, $cart->get_cart_url() ); + } + + /** + * Validates the request to ensure the product exists and is published. + * + * @param int $post_id The ID of the product post. + * @param array $submission The form submission data. + * + * @return bool True if the request is valid, false otherwise. + */ + protected function validate_request( $post_id, $submission ) { + $post = get_post( $post_id ); + if ( empty( $post ) ) { + return false; + } + if ( Product::NAME !== $post->post_type ) { + return false; + } + if ( $post->post_status !== 'publish' ) { + return false; + } + + return true; + } + + /** + * Gets the product variant ID from the form submission. + * + * @param Product $product The product object. + * @param array $submission The form submission data. + * + * @return int The variant ID. + */ + protected function get_variant_id( Product $product, $submission ) { + if ( ! empty( $submission[ 'variant_id' ] ) ) { + return (int) $submission[ 'variant_id' ]; + } + + $data = $product->get_source_data(); + + foreach ( $data->variants as $variant ) { + foreach ( $variant->option_values as $option ) { + $key = 'option-' . $option->option_id; + if ( ! isset( $submission[ $key ] ) ) { + continue 2; + } + if ( $submission[ $key ] != $option->id ) { + continue 2; + } + } + + // all options matched, we have a winner + return $variant->id; + } + + // fall back to the first variant + if ( ! empty( $data->variants ) ) { + return reset( $data->variants )->id; + } + + return 0; + } +} diff --git a/test/Checkout-test.php b/test/Checkout-test.php new file mode 100644 index 00000000..bd8bf4e4 --- /dev/null +++ b/test/Checkout-test.php @@ -0,0 +1,75 @@ +requirements( $container ); + $this->customer_login( $container ); + } + + private function requirements( Container $container ) { + $container[ self::REQUIREMENTS_NOTICE ] = function ( Container $container ) { + return new Requirements_Notice( $container[ Merchant::SETUP_STATUS ] ); + }; + + add_action( 'admin_notices', $this->create_callback( 'verify_checkout_requirements', function () use ( $container ) { + if ( $container[ Settings::CONFIG_STATUS ] >= Settings::STATUS_COMPLETE ) { + $container[ self::REQUIREMENTS_NOTICE ]->check_requirements(); + } + } ), 10, 0 ); + + add_action( 'admin_post_' . Requirements_Notice::REFRESH, $this->create_callback( 'refresh_checkout_requirements', function () use ( $container ) { + $container[ self::REQUIREMENTS_NOTICE ]->refresh_status(); + } ), 10, 0 ); + + add_filter( 'pre_option_' . \BigCommerce\Settings\Sections\Cart::OPTION_EMBEDDED_CHECKOUT, $this->create_callback( 'embedded_checkout_requirement_check', function ( $value ) use ( $container ) { + return $container[ self::REQUIREMENTS_NOTICE ]->filter_embedded_checkout( $value ); + } ), 10, 1 ); + + add_filter( 'bigcommerce/checkout/can_embed', $this->create_callback( 'embedded_checkout_supported', function ( $supported ) use ( $container ) { + return $container[ self::REQUIREMENTS_NOTICE ]->can_enable_embedded_checkout(); + } ), 1, 1 ); + } + + private function customer_login( Container $container ) { + $container[ self::LOGIN ] = function ( Container $container ) { + return new Customer_Login( $container[ Merchant::ONBOARDING_API ], $container[ Api::FACTORY ]->store() ); + }; + + add_filter( 'bigcommerce/checkout/url', $this->create_callback( 'checkout_url', function ( $url ) use ( $container ) { + return $container[ self::LOGIN ]->set_login_token_for_checkout( $url ); + } ), 10, 1 ); + } +} diff --git a/test/Flusher-test.php b/test/Flusher-test.php new file mode 100644 index 00000000..7bbf2cc3 --- /dev/null +++ b/test/Flusher-test.php @@ -0,0 +1,39 @@ +actions($container); + $this->errors($container); + $this->success($container); + $this->redirects($container); + $this->messaging($container); + } + + /** + * Registers form actions related to deleting, updating addresses, and handling user registrations. + * + * @param Container $container The container instance used to inject dependencies. + * + * @return void + */ + private function actions(Container $container) { + add_action('parse_request', $this->create_callback('handle_form_action', function () use ($container) { + $action = filter_var_array($_REQUEST, ['bc-action' => FILTER_SANITIZE_STRING]); + if ($action['bc-action']) { + do_action('bigcommerce/form/action=' . $action['bc-action'], stripslashes_deep($_REQUEST)); + } + }), 10, 0); + + $container[self::DELETE_ADDRESS] = function (Container $container) { + return new Delete_Address_Handler(); + }; + + add_action('bigcommerce/form/action=' . Delete_Address_Handler::ACTION, $this->create_callback('delete_address', function ($submission) use ($container) { + $container[self::DELETE_ADDRESS]->handle_request($submission); + }), 10, 1); + + $container[self::UPDATE_ADDRESS] = function (Container $container) { + return new Update_Address_Handler(); + }; + + add_action('bigcommerce/form/action=' . Update_Address_Handler::ACTION, $this->create_callback('update_address', function ($submission) use ($container) { + $container[self::UPDATE_ADDRESS]->handle_request($submission); + }), 10, 1); + + $container[self::UPDATE_PROFILE] = function (Container $container) { + return new Update_Profile_Handler(); + }; + + add_action('bigcommerce/form/action=' . Update_Profile_Handler::ACTION, $this->create_callback('update_profile', function ($submission) use ($container) { + $container[self::UPDATE_PROFILE]->handle_request($submission); + }), 10, 1); + + $container[self::REGISTER] = function (Container $container) { + return new Registration_Handler($container[Compatibility::SPAM_CHECKER], $container[Accounts::LOGIN]); + }; + + add_action('bigcommerce/form/action=' . Registration_Handler::ACTION, $this->create_callback('register', function ($submission) use ($container) { + return $container[self::REGISTER]->handle_request($submission); + }), 10, 1); + + $container[self::GIFT_CERTIFICATE] = function (Container $container) { + return new Purchase_Gift_Certificate_Handler($container[Api::FACTORY]->cart()); + }; + + add_action('bigcommerce/form/action=' . Purchase_Gift_Certificate_Handler::ACTION, $this->create_callback('purchase_gift_certificate', function ($submission) use ($container) { + return $container[self::GIFT_CERTIFICATE]->handle_request($submission); + }), 10, 1); + + $container[self::REVIEW] = function (Container $container) { + return new Product_Review_Handler($container[Api::FACTORY]->catalog()); + }; + + add_action('bigcommerce/form/action=' . Product_Review_Handler::ACTION, $this->create_callback('product_review', function ($submission) use ($container) { + $container[self::REVIEW]->handle_request($submission); + }), 10, 1); + } + + /** + * Registers the error handling actions for form submissions. + * + * @param Container $container The container instance used to inject dependencies. + * + * @return void + */ + private function errors(Container $container) { + $container[self::ERRORS] = function (Container $container) { + return new Error_Handler(); + }; + + add_action('bigcommerce/form/error', $this->create_callback('error', function (\WP_Error $error, $submission, $redirect = '') use ($container) { + $container[self::ERRORS]->form_error($error, $submission, $redirect); + }), 10, 3); + } +} diff --git a/test/hooks.php b/test/hooks.php new file mode 100644 index 00000000..8a7ca46b --- /dev/null +++ b/test/hooks.php @@ -0,0 +1,90 @@ + + * @copyright 2005-2022 Pronamic + * @license GPL-3.0-or-later + * @package Pronamic\WordPress\Documentor + */ + +/** + * Test function for prefix 1. + * + * @param string $first_param This is the first argument. + * @param string $second_param This is the second argument. + * @return string + */ +function test_issue_10_prefix_1( $first_param, $second_param ) { + /** + * Prefix 1 description. + * + * @param string $first_param_prefix_1 This is the first argument. Change up description! + * @param object $second_param_prefix_1 This is the second argument for prefix 1 + */ + return apply_filters( 'prefix_1_filter_name', $first_param_test, $second_param_test ); +} + +/** + * Test function for prefix 2. + * + * @param string $first_param This is the first argument. + * @param string $second_param This is the second argument. + * @return string + */ +function test_issue_10_prefix_2( $first_param, $second_param ) { + /** + * Prefix 2 description. + * + * @param array $first_param_prefix_2 This is the first argument for prefix 2 + * @param Exampletype $second_param_prefix_2 This is the second argument for prefix 2 + */ + return apply_filters( 'prefix_2_filter_name', $first_param, $second_param ); +} + +/** + * Test function for prefix 3. + * + * @param string $first_param This is the first argument. + * @param string $second_param This is the second argument. + * @return string + */ +function test_issue_10_prefix_3( $first_param, $second_param ) { + /** + * Prefix 3 description. + * + * @param integer $first_param_prefix_3 This is the first argument for prefix 3 + * @param boolean $second_param_prefix_3 This is the second argument for prefix 3. + */ + return apply_filters( 'prefix_3_filter_name', $first_param, $second_param ); +} + +/** + * Test function for prefix 4 + */ + +function test_issue_10_prefix_4( $first_param, $second_param ) { + + return do_action( 'prefix_4_filter_nameee', $first_param, $second_param, $third_param ); +} + +/** + * additional Prefix 4 description. + * + * @param int $tenth_param_prefix_4 This is the 7th argument for prefix 4 + * @param int $ele_param_prefix_4 This is the 8th argument for prefix 4 + * @param int $twelvth_param_prefix_4 This is the 9th argument for prefix 4!!! + */ +function test_issue_10_prefix_5( $first_param, $second_param ) { + /** + * Prefix 4 description... + * + * @param string $first_param_prefix_4 This is the 1st argument for prefix 4 + * @param object $second_param_prefix_4 This is the 2nd argument for prefix 4 + * @param string $third_param_prefix_4 This is the 3rd argument for prefix 4... + * @param string $fourth_param_prefix_4 This is the 4th argument for prefix 4 + * @param boolean $fifth_param_prefix_4 This is the 5th argument for prefix 4... + * @param string $six_param_prefix_44 This is the 6th argument for prefix 4........ + */ + return do_action( 'prefix_4_filter_nameee', $first_parammm, $second_parammm, $third_parammm ); +} diff --git a/test/woocommerce-functions-test.php b/test/woocommerce-functions-test.php new file mode 100644 index 00000000..d6f91fd8 --- /dev/null +++ b/test/woocommerce-functions-test.php @@ -0,0 +1,256 @@ +container(); + return $container[ Compatibility::WC_FACADE ]; + } +} + +if ( ! function_exists( 'wc_get_template_part' ) ) { + /** + * Retrieves a template part for WooCommerce. + * + * @param string $slug The template slug. + * @param string $name The template part name (optional). + * @return string The rendered template part. + */ + function wc_get_template_part( $slug, $name = '' ) { + $template = "{$slug}.php"; + if ( $name ) { + $template = "{$slug}-{$name}.php"; + } + return wc_get_template( $template ); + } +} + +if ( ! function_exists( 'wc_get_template' ) ) { + /** + * Retrieves and renders a WooCommerce template. + * + * @param string $template_name The template file name. + * @param array $args Arguments to pass to the template. + * @param string $template_path The path to the template (optional). + * @param string $default_path The default path (optional). + * @return void + */ + function wc_get_template( $template_name, $args = [], $template_path = '', $default_path = '' ) { + $container = bigcommerce()->container(); + $container[ Compatibility::THEME ]->render_template( $template_name, $args ); + } +} + +if ( ! function_exists( 'wc_get_template_html' ) ) { + /** + * Retrieves the HTML content for a WooCommerce template. + * + * @param string $template_name The template file name. + * @param array $args Arguments to pass to the template. + * @param string $template_path The path to the template (optional). + * @param string $default_path The default path (optional). + * @return string An empty string. + */ + function wc_get_template_html( $template_name, $args = [], $template_path = '', $default_path = '' ) { + return ''; + } +} + +if ( ! function_exists( 'wc_locate_template' ) ) { + /** + * Locates a WooCommerce template. + * + * @param string $template_name The template file name. + * @param string $template_path The path to the template (optional). + * @param string $default_path The default path (optional). + * @return string An empty string. + */ + function wc_locate_template( $template_name, $template_path = '', $default_path = '' ) { + return ''; + } +} + +if ( ! function_exists( 'woocommerce_mini_cart' ) ) { + /** + * Displays the mini cart for WooCommerce. + * + * @return void + */ + function woocommerce_mini_cart() { + printf( '
%s
', esc_html( __( 'Loading', 'bigcommerce' ) ) ); + } +} + +if ( ! function_exists( 'wc_get_cart_url' ) ) { + /** + * Retrieves the URL of the cart page. + * + * @return string The cart page URL. + */ + function wc_get_cart_url() { + return get_permalink( get_option( Cart_Page::NAME, 0 ) ); + } +} + +if ( ! function_exists( 'wc_get_checkout_url' ) ) { + /** + * Retrieves the URL of the checkout page. + * + * @return string The checkout page URL. + */ + function wc_get_checkout_url() { + return get_permalink( get_option( Checkout_Page::NAME, 0 ) ); + } +} + +if ( ! function_exists( 'is_cart' ) ) { + /** + * Checks if the current page is the cart page. + * + * @return bool True if the current page is the cart page, false otherwise. + */ + function is_cart() { + return is_page( get_option( Cart_Page::NAME, 0 ) ); + } +} + +if ( ! function_exists( 'is_checkout' ) ) { + /** + * Checks if the current page is the checkout page. + * + * @return bool True if the current page is the checkout page, false otherwise. + */ + function is_checkout() { + if ( ! (bool) get_option( Cart_Settings::OPTION_EMBEDDED_CHECKOUT, false ) ) { + return false; + } + return is_page( get_option( Checkout_Page::NAME, 0 ) ); + } +} + +if ( ! function_exists( 'is_account_page' ) ) { + /** + * Checks if the current page is the account page. + * + * @return bool True if the current page is the account page, false otherwise. + */ + function is_account_page() { + return is_page( get_option( Account_Page::NAME, 0 ) ); + } +} + +if ( ! function_exists( 'is_product' ) ) { + /** + * Checks if the current page is a product page. + * + * @return bool True if the current page is a product page, false otherwise. + */ + function is_product() { + return is_singular( Product::NAME ); + } +} + +if ( ! function_exists( 'is_shop' ) ) { + /** + * Checks if the current page is the shop page. + * + * @return bool True if the current page is the shop page, false otherwise. + */ + function is_shop() { + return is_archive( Product::NAME ); + } +} + +if ( ! function_exists( 'is_product_category' ) ) { + /** + * Checks if the current page is a product category page. + * + * @return bool True if the current page is a product category page, false otherwise. + */ + function is_product_category() { + return is_tax( Product_Category::NAME ); + } +} + +if ( ! function_exists( 'is_product_tag' ) ) { + /** + * Checks if the current page is a product tag page. + * + * @return bool False, as the function always returns false. + */ + function is_product_tag() { + return false; + } +} + +if ( ! function_exists( 'is_product_taxonomy' ) ) { + /** + * Checks if the current page is a product taxonomy page. + * + * @return bool True if the current page is a product taxonomy page, false otherwise. + */ + function is_product_taxonomy() { + return is_tax( Product_Category::NAME ); + } +} + +if ( ! function_exists( 'wc_get_image_size' ) ) { + /** + * Retrieves the WooCommerce image size. + * + * @return string An empty string. + */ + function wc_get_image_size() { + return ''; + } +} + +if ( ! function_exists( 'wc_print_notices' ) ) { + /** + * Prints WooCommerce notices. + * + * @return string An empty string. + */ + function wc_print_notices() { + return ''; + } +} + +if ( ! function_exists( 'woocommerce_reset_loop' ) ) { + /** + * Resets the WooCommerce loop. + * + * @return string An empty string. + */ + function woocommerce_reset_loop() { + return ''; + } +} + +if ( ! function_exists( 'wc_get_page_id' ) ) { + /** + * Retrieves the ID of a WooCommerce page. + * + * @return int The ID of the WooCommerce page, or -1 if not found. + */ + function wc_get_page_id() { + return -1; + } +} From bf801de581c34ebac62bd269affd85b010005f1a Mon Sep 17 00:00:00 2001 From: bc-andreadao Date: Fri, 17 Jan 2025 11:33:53 -0600 Subject: [PATCH 04/13] update .gitignore file --- .gitignore | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..43baf436 --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +# generated files # +################### + +.DS_Store* +ehthumbs.db +._* +*~ +.svn +.cvs +*.bak +*.swp +Thumbs.db +.DS_Store +.idea +pimple.json +.phpstorm.meta.php +*.un~ +.sass-cache +.scssc +/node_modules/ +phpdoc.json +vendor/* +.phpdoc/* +docs/* +composer.phar + +# Packages # +############ + +*.7z +*.dmg +*.gz +*.bz2 +*.iso +*.jar +*.rar +*.tar +*.zip +*.tgz + +# Logs and databases # +###################### + +*.log +*.sql + +# Local configuration # +####################### + +local-config.json From ff72188a584b441392a51506f1a8035ce9a45661 Mon Sep 17 00:00:00 2001 From: bc-andreadao Date: Fri, 17 Jan 2025 11:34:55 -0600 Subject: [PATCH 05/13] add docblocks for classes, hooks, functions --- bigcommerce.php | 170 ++-- src/BigCommerce/Accounts/Channel_Settings.php | 64 +- src/BigCommerce/Accounts/Countries.php | 41 +- src/BigCommerce/Accounts/Customer.php | 173 ++-- src/BigCommerce/Accounts/Customer_Group.php | 31 +- .../Accounts/Customer_Group_Proxy.php | 24 +- src/BigCommerce/Accounts/Login.php | 44 +- src/BigCommerce/Accounts/Nav_Menu.php | 151 ++-- src/BigCommerce/Accounts/Password_Reset.php | 166 ++-- src/BigCommerce/Accounts/Register.php | 316 ++++--- src/BigCommerce/Accounts/Roles/Customer.php | 33 +- src/BigCommerce/Accounts/Roles/Role.php | 27 + src/BigCommerce/Accounts/Sub_Nav.php | 141 +-- .../Accounts/User_Profile_Settings.php | 114 +-- .../Accounts/Wishlists/Actions/Add_Item.php | 63 +- .../Wishlists/Actions/Create_Wishlist.php | 57 +- .../Wishlists/Actions/Delete_Wishlist.php | 55 +- .../Wishlists/Actions/Edit_Wishlist.php | 56 +- .../Wishlists/Actions/Remove_Item.php | 56 +- .../Wishlists/Actions/Request_Router.php | 37 +- .../Wishlists/Actions/Wishlist_Action.php | 76 +- .../Accounts/Wishlists/Add_Item_View.php | 53 +- .../Accounts/Wishlists/Public_Wishlist.php | 93 +- .../Accounts/Wishlists/Wishlist.php | 130 ++- .../Wishlists/Wishlist_Public_View.php | 39 +- .../Wishlists/Wishlist_Request_Parser.php | 31 +- src/BigCommerce/Amp/Amp_Admin_Notices.php | 306 +++---- src/BigCommerce/Amp/Amp_Assets.php | 203 +++-- src/BigCommerce/Amp/Amp_Cart.php | 243 +++--- src/BigCommerce/Amp/Amp_Cart_Menu_Item.php | 105 ++- .../Amp/Amp_Controller_Factory.php | 58 +- src/BigCommerce/Amp/Amp_Template_Override.php | 264 +++--- src/BigCommerce/Amp/Classic.php | 19 +- src/BigCommerce/Amp/Overrides.php | 89 +- .../Analytics/Events/Add_To_Cart.php | 138 +-- .../Analytics/Events/View_Product.php | 219 ++--- src/BigCommerce/Analytics/Facebook_Pixel.php | 77 +- .../Analytics/Google_Analytics.php | 63 +- src/BigCommerce/Analytics/Segment.php | 96 ++- src/BigCommerce/Api/Api_Config_Renewal.php | 101 ++- src/BigCommerce/Api/Api_Data_Sanitizer.php | 126 ++- src/BigCommerce/Api/Api_Scopes_Validator.php | 207 +++-- src/BigCommerce/Api/Banners_Api.php | 29 +- src/BigCommerce/Api/Base_Client.php | 56 +- src/BigCommerce/Api/Caching_Client.php | 60 +- src/BigCommerce/Api/Configuration.php | 15 +- .../Api/ConfigurationRequiredException.php | 10 + src/BigCommerce/Api/Currencies_Api.php | 21 +- src/BigCommerce/Api/Customer_Api.php | 32 +- src/BigCommerce/Api/Marketing_Api.php | 21 +- src/BigCommerce/Api/Null_Client.php | 33 +- src/BigCommerce/Api/Payments_Api.php | 26 +- src/BigCommerce/Api/Request_Headers.php | 16 +- src/BigCommerce/Api/Shipping_Api.php | 47 +- src/BigCommerce/Api/Store_Api.php | 91 +- src/BigCommerce/Api/Tax_Class_Api.php | 11 +- src/BigCommerce/Api/Webhooks_Api.php | 47 +- src/BigCommerce/Api/v2ApiAdapter.php | 51 +- src/BigCommerce/Assets/Admin/JS_Config.php | 34 + .../Assets/Admin/JS_Localization.php | 19 +- src/BigCommerce/Assets/Admin/Scripts.php | 190 ++-- src/BigCommerce/Assets/Admin/Styles.php | 81 +- src/BigCommerce/Assets/Theme/Image_Sizes.php | 191 ++-- src/BigCommerce/Assets/Theme/JS_Config.php | 34 +- .../Assets/Theme/JS_Localization.php | 14 +- src/BigCommerce/Assets/Theme/Scripts.php | 22 +- src/BigCommerce/Assets/Theme/Styles.php | 23 +- src/BigCommerce/Banners/Banners.php | 101 ++- src/BigCommerce/CLI/Command.php | 74 +- .../CLI/Documentation/Build_Docs.php | 71 +- .../CLI/Documentation/Data_Importer.php | 27 +- .../CLI/Documentation/Import_Docs.php | 159 ++-- src/BigCommerce/CLI/Documentation/README.md | 2 +- src/BigCommerce/CLI/Import_Products.php | 22 +- src/BigCommerce/CLI/Reset_Plugin.php | 106 ++- .../CLI/Resources/Build_Resources.php | 166 ++-- src/BigCommerce/CLI/Resources/Resource.php | 357 ++++---- .../CLI/Resources/Resource_Group.php | 82 +- src/BigCommerce/CLI/Update_Country_Cache.php | 187 ++-- src/BigCommerce/Cache/Cache_Handler.php | 47 +- src/BigCommerce/Cart/Add_To_Cart.php | 379 ++++---- src/BigCommerce/Cart/Buy_Now.php | 37 +- src/BigCommerce/Cart/Cache_Control.php | 18 +- src/BigCommerce/Cart/Cart.php | 101 ++- src/BigCommerce/Cart/Cart_Mapper.php | 47 +- src/BigCommerce/Cart/Cart_Menu_Item.php | 20 +- src/BigCommerce/Cart/Cart_Recovery.php | 47 +- src/BigCommerce/Cart/Checkout.php | 45 +- src/BigCommerce/Cart/Item_Counter.php | 16 +- src/BigCommerce/Cart/Mini_Cart.php | 13 +- src/BigCommerce/Checkout/Customer_Login.php | 27 +- .../Checkout/Requirements_Notice.php | 107 +-- .../Compatibility/Akismet/Akismet.php | 27 +- .../Compatibility/Matomo/Matomo.php | 25 +- .../Compatibility/Spam_Checker.php | 14 +- .../Compatibility/Template_Compatibility.php | 23 +- .../Themes/Flatsome/Flatsome.php | 44 +- .../Flatsome/Templates/Account_Links.php | 105 ++- .../Compatibility/Themes/Null_Theme.php | 8 +- .../Compatibility/Themes/Theme.php | 29 +- .../Compatibility/Themes/Theme_Factory.php | 15 +- .../Compatibility/WooCommerce/Cart.php | 28 +- .../Compatibility/WooCommerce/Facade.php | 17 +- .../Compatibility/woocommerce-functions.php | 117 ++- src/BigCommerce/Container/Accounts.php | 513 +++++++---- src/BigCommerce/Container/Amp.php | 74 +- src/BigCommerce/Container/Analytics.php | 59 +- src/BigCommerce/Container/Api.php | 99 ++- src/BigCommerce/Container/Assets.php | 305 +++++-- src/BigCommerce/Container/Banners.php | 44 +- src/BigCommerce/Container/Cart.php | 135 ++- src/BigCommerce/Container/Checkout.php | 38 +- src/BigCommerce/Container/Cli.php | 136 ++- src/BigCommerce/Container/Compatibility.php | 55 +- src/BigCommerce/Container/Currency.php | 48 +- src/BigCommerce/Container/Editor.php | 60 +- src/BigCommerce/Container/Forms.php | 100 ++- .../Container/Gift_Certificates.php | 38 +- src/BigCommerce/Container/GraphQL.php | 109 ++- src/BigCommerce/Container/Image.php | 17 +- src/BigCommerce/Container/Import.php | 255 +++++- src/BigCommerce/Container/Log.php | 47 +- src/BigCommerce/Container/Merchant.php | 87 ++ src/BigCommerce/Container/Nav_Menu.php | 45 + src/BigCommerce/Container/Pages.php | 363 +++++--- src/BigCommerce/Container/Post_Meta.php | 12 + src/BigCommerce/Container/Post_Types.php | 568 +++++++----- src/BigCommerce/Container/Provider.php | 66 +- src/BigCommerce/Container/Proxy.php | 306 ++++--- src/BigCommerce/Container/Rest.php | 175 +++- src/BigCommerce/Container/Reviews.php | 115 ++- src/BigCommerce/Container/Rewrites.php | 115 ++- src/BigCommerce/Container/Schema.php | 170 +++- src/BigCommerce/Container/Settings.php | 350 +++++++- src/BigCommerce/Container/Shortcodes.php | 252 ++++-- src/BigCommerce/Container/Taxonomies.php | 293 +++++-- src/BigCommerce/Container/Templates.php | 55 +- .../Container/Theme_Customizer.php | 253 ++++-- src/BigCommerce/Container/Util.php | 50 +- src/BigCommerce/Container/Webhooks.php | 152 +++- src/BigCommerce/Container/Widgets.php | 56 +- .../Currency/Configurable_Formatter.php | 84 +- src/BigCommerce/Currency/Currency.php | 236 ++--- .../Currency/Currency_Formatter.php | 22 +- .../Currency/Formatter_Factory.php | 128 +-- src/BigCommerce/Currency/Intl_Formatter.php | 61 +- src/BigCommerce/Currency/USD_Formatter.php | 17 +- src/BigCommerce/Currency/With_Currency.php | 42 +- .../Controls/Multiple_Checkboxes.php | 17 +- src/BigCommerce/Customizer/Panels/Primary.php | 40 +- .../Customizer/Sections/Banners.php | 85 +- .../Customizer/Sections/Buttons.php | 69 +- src/BigCommerce/Customizer/Sections/Cart.php | 59 +- .../Customizer/Sections/Checkout.php | 64 +- .../Customizer/Sections/Colors.php | 192 ++++- .../Customizer/Sections/Product_Archive.php | 184 +++- .../Customizer/Sections/Product_Category.php | 147 ++-- .../Customizer/Sections/Product_Single.php | 133 ++- src/BigCommerce/Customizer/Styles.php | 31 +- .../Editor/Add_Products_Button.php | 35 +- .../Editor/Editor_Dialog_Template.php | 33 +- .../Gutenberg/Blocks/Account_Profile.php | 37 +- .../Editor/Gutenberg/Blocks/Address_List.php | 37 +- .../Editor/Gutenberg/Blocks/Cart.php | 37 +- .../Editor/Gutenberg/Blocks/Checkout.php | 37 +- .../Blocks/Gift_Certificate_Balance.php | 37 +- .../Blocks/Gift_Certificate_Form.php | 38 +- .../Gutenberg/Blocks/Gutenberg_Block.php | 46 +- .../Editor/Gutenberg/Blocks/Login_Form.php | 40 +- .../Editor/Gutenberg/Blocks/Order_History.php | 40 +- .../Gutenberg/Blocks/Product_Components.php | 100 ++- .../Gutenberg/Blocks/Product_Reviews.php | 49 +- .../Editor/Gutenberg/Blocks/Products.php | 65 +- .../Gutenberg/Blocks/Registration_Form.php | 41 +- .../Gutenberg/Blocks/Shortcode_Block.php | 87 +- .../Editor/Gutenberg/Blocks/Wishlist.php | 40 +- .../Editor/Gutenberg/Migrate_Blocks.php | 80 +- .../Channel_Not_Found_Exception.php | 4 +- .../Component_Not_Found_Exception.php | 3 + .../Exceptions/No_Task_Found_Exception.php | 4 +- .../Product_Not_Found_Exception.php | 4 +- .../Forms/Delete_Address_Handler.php | 31 +- src/BigCommerce/Forms/Error_Handler.php | 27 +- src/BigCommerce/Forms/Form_Handler.php | 9 +- src/BigCommerce/Forms/Form_Redirect.php | 22 +- src/BigCommerce/Forms/Messages.php | 37 +- .../Forms/Product_Review_Handler.php | 386 +++++---- .../Purchase_Gift_Certificate_Handler.php | 35 + .../Forms/Registration_Handler.php | 38 +- src/BigCommerce/Forms/Success_Handler.php | 34 +- .../Forms/Switch_Currency_Handler.php | 388 +++++---- .../Forms/Update_Address_Handler.php | 297 ++++--- .../Forms/Update_Profile_Handler.php | 19 +- src/BigCommerce/Gift_Certificates/Sub_Nav.php | 25 +- src/BigCommerce/GraphQL/BaseGQL.php | 490 ++++++----- src/BigCommerce/GraphQL/Customer_Query.php | 815 +++++++++--------- src/BigCommerce/GraphQL/GraphQL_Processor.php | 107 ++- src/BigCommerce/GraphQL/Product_Query.php | 80 +- src/BigCommerce/GraphQL/Reviews_Query.php | 81 +- src/BigCommerce/GraphQL/Terms_Query.php | 92 +- src/BigCommerce/Import/Image_Importer.php | 11 + .../Importers/Products/Product_Builder.php | 117 ++- .../Importers/Products/Product_Creator.php | 85 +- .../Importers/Products/Product_Ignorer.php | 109 +-- .../Importers/Products/Product_Importer.php | 99 ++- .../Importers/Products/Product_Remover.php | 37 +- .../Importers/Products/Product_Saver.php | 322 +++---- .../Products/Product_Strategy_Factory.php | 32 +- .../Importers/Products/Product_Updater.php | 12 + .../Import/Importers/Terms/Term_Creator.php | 37 + .../Import/Importers/Terms/Term_Ignorer.php | 44 +- .../Import/Importers/Terms/Term_Saver.php | 119 ++- .../Importers/Terms/Term_Strategy_Factory.php | 23 +- .../Import/Importers/Terms/Term_Updater.php | 23 + .../Import/Mappers/Brand_Mapper.php | 10 +- .../Mappers/Product_Category_Mapper.php | 8 + .../Import/Mappers/Term_Mapper.php | 32 +- .../Import/Processors/Brand_Import.php | 71 +- .../Import/Processors/Brand_Purge.php | 36 + .../Import/Processors/CategoriesTrees.php | 29 +- .../Import/Processors/Category_Import.php | 123 ++- .../Import/Processors/Category_Purge.php | 35 + .../Import/Processors/Channel_Initializer.php | 41 +- src/BigCommerce/Import/Processors/Cleanup.php | 361 ++++---- .../Import/Processors/Currencies.php | 193 +++-- .../Processors/Default_Customer_Group.php | 201 +++-- .../Import/Processors/Headless.php | 5 + .../Import/Processors/Store_Settings.php | 15 +- .../Import/Processors/Term_Import.php | 119 ++- .../Import/Processors/Term_Purge.php | 33 +- src/BigCommerce/Import/Runner/Cron_Runner.php | 18 + src/BigCommerce/Import/Runner/Status.php | 5 + src/BigCommerce/Logging/Error_Log.php | 2 +- src/BigCommerce/Plugin.php | 4 +- .../Post_Types/Product/Channel_Sync.php | 2 +- .../Post_Types/Product/Product.php | 4 +- src/BigCommerce/Post_Types/Product/Query.php | 52 +- .../Post_Types/Product/Reset_Listing.php | 38 +- .../Product/Single_Product_Sync.php | 228 ++--- .../Post_Types/Sync_Log/Sync_Log.php | 2 +- src/BigCommerce/Rest/Cart_Controller.php | 14 +- src/BigCommerce/Rest/Products_Controller.php | 124 ++- src/BigCommerce/Rewrites/Action_Endpoint.php | 11 + src/BigCommerce/Rewrites/Flusher.php | 48 +- src/BigCommerce/Settings/Import_Now.php | 3 + .../Settings/Screens/Abstract_Screen.php | 220 ++++- .../Screens/Create_Account_Screen.php | 21 + .../Settings/Screens/Onboarding_Screen.php | 7 + .../Settings/Sections/Account_Settings.php | 2 +- .../Settings/Sections/Api_Credentials.php | 5 + .../Settings/Sections/Channel_Select.php | 33 +- src/BigCommerce/Settings/Start_Over.php | 7 +- src/BigCommerce/Shortcodes/Order_History.php | 32 +- .../Shortcodes/Registration_Form.php | 2 +- .../Templates/Lost_Password_Form.php | 10 +- .../Templates/Product_Form_Preview.php | 36 +- .../Customer/Customer_Channel_Updater.php | 13 +- .../Webhooks/Customer/Customer_Saver.php | 12 + .../Webhooks/Product/Product_Creator.php | 23 +- .../Product_Inventory_Update_Webhook.php | 5 + .../Product/Product_Update_Webhook.php | 5 + .../Webhooks/Product/Product_Updater.php | 30 +- .../Widgets/Currency_Switcher_Widget.php | 8 + 263 files changed, 15757 insertions(+), 7223 deletions(-) diff --git a/bigcommerce.php b/bigcommerce.php index 07040a43..c0e2f0ad 100644 --- a/bigcommerce.php +++ b/bigcommerce.php @@ -3,7 +3,7 @@ Plugin Name: BigCommerce for WordPress Description: Scale your ecommerce business with WordPress on the front-end and BigCommerce on the back end. Free up server resources from things like catalog management, processing payments, and managing fulfillment logistics. Author: BigCommerce -Version: 5.0.2 +Version: 5.1.2 Author URI: https://www.bigcommerce.com/wordpress Requires PHP: 7.4.0 Text Domain: bigcommerce @@ -19,47 +19,50 @@ define( 'BIGCOMMERCE_WP_OPTIMAL_VERSION', '5.8' ); if ( version_compare( PHP_VERSION, BIGCOMMERCE_PHP_MINIMUM_VERSION, '<' ) || version_compare( get_bloginfo( 'version' ), BIGCOMMERCE_WP_MINIMUM_VERSION, '<' ) ) { - add_action( 'admin_notices', function() { - $message = sprintf( esc_html__( 'BigCommerce requires PHP version %s+ and WP version %s+, plugin is currently NOT RUNNING.', 'bigcommerce' ), BIGCOMMERCE_PHP_OPTIMAL_VERSION, BIGCOMMERCE_WP_OPTIMAL_VERSION ); - echo wp_kses_post( sprintf( '
%s
', wpautop( $message ) ) ); - } ); + add_action( 'admin_notices', function() { + $message = sprintf( esc_html__( 'BigCommerce requires PHP version %s+ and WP version %s+, plugin is currently NOT RUNNING.', 'bigcommerce' ), BIGCOMMERCE_PHP_OPTIMAL_VERSION, BIGCOMMERCE_WP_OPTIMAL_VERSION ); + echo wp_kses_post( sprintf( '
%s
', wpautop( $message ) ) ); + }); - return; + return; } elseif ( version_compare( PHP_VERSION, BIGCOMMERCE_PHP_OPTIMAL_VERSION, '<' ) || version_compare( get_bloginfo( 'version' ), BIGCOMMERCE_WP_OPTIMAL_VERSION, '<' ) ) { - add_action( 'admin_notices', function() { - $message = sprintf( esc_html__( 'BigCommerce requires PHP version %s+ and WP version %s+', 'bigcommerce' ), BIGCOMMERCE_PHP_OPTIMAL_VERSION, BIGCOMMERCE_WP_OPTIMAL_VERSION ); - echo wp_kses_post( sprintf( '
%s
', wpautop( $message ) ) ); - } ); + add_action( 'admin_notices', function() { + $message = sprintf( esc_html__( 'BigCommerce requires PHP version %s+ and WP version %s+', 'bigcommerce' ), BIGCOMMERCE_PHP_OPTIMAL_VERSION, BIGCOMMERCE_WP_OPTIMAL_VERSION ); + echo wp_kses_post( sprintf( '
%s
', wpautop( $message ) ) ); + }); } if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) { - require_once __DIR__ . '/vendor/autoload.php'; + require_once __DIR__ . '/vendor/autoload.php'; } register_activation_hook( __FILE__, [ \BigCommerce\Plugin::class, 'activate' ] ); -// Start the plugin add_action( 'plugins_loaded', 'bigcommerce_init', 2, 0 ); /** + * Fires after the plugin has initialized. + * + * @param \BigCommerce\Plugin $plugin The global instance of the plugin controller. + * @param \Pimple\Container $container The plugin's dependency injection container. * @return \BigCommerce\Plugin */ function bigcommerce_init() { // Don't load on frontend for non-active channel status - $channel_status = bigcommerce_get_primary_channel_status(); - $is_front_page = ! defined( 'WP_CLI' ) && ! is_admin() && $channel_status !== null; + $channel_status = bigcommerce_get_primary_channel_status(); + $is_front_page = ! defined( 'WP_CLI' ) && ! is_admin() && $channel_status !== null; // Don't load on frontend for non-active channel status - if ( $is_front_page && ! in_array( $channel_status, [ BC_Status::STATUS_ACTIVE, BC_Status::STATUS_PRE_LAUNCH ] ) ) { - return; - } - - if ( ! defined( 'DOING_CRON' ) && $is_front_page && $channel_status === BC_Status::STATUS_PRE_LAUNCH && ! current_user_can( 'publish_posts' ) ) { - handle_404_redirect_in_prelaunch(); - return; - } - $container = new \Pimple\Container( [ 'plugin_file' => __FILE__ ] ); - $plugin = \BigCommerce\Plugin::instance( $container ); - $plugin->init(); + if ( $is_front_page && ! in_array( $channel_status, [ BC_Status::STATUS_ACTIVE, BC_Status::STATUS_PRE_LAUNCH ] ) ) { + return; + } + + if ( ! defined( 'DOING_CRON' ) && $is_front_page && $channel_status === BC_Status::STATUS_PRE_LAUNCH && ! current_user_can( 'publish_posts' ) ) { + handle_404_redirect_in_prelaunch(); + return; + } + $container = new \Pimple\Container( [ 'plugin_file' => __FILE__ ] ); + $plugin = \BigCommerce\Plugin::instance( $container ); + $plugin->init(); /** * Fires after the plugin has initialized @@ -67,44 +70,45 @@ function bigcommerce_init() { * @param \BigCommerce\Plugin $plugin The global instance of the plugin controller * @param \Pimple\Container $container The plugin's dependency injection container */ - do_action( 'bigcommerce/init', $plugin, $container ); + do_action( 'bigcommerce/init', $plugin, $container ); - return $plugin; + return $plugin; } function handle_404_redirect_in_prelaunch() { // We have to do that here because we don't initialize the plugin in case of prelaunch status - add_filter( 'pre_handle_404', function ( $preempt ) { - if ( is_admin() || ! ( is_page() && is_main_query() ) ) { - return $preempt; - } - - $plugin_pages = [ - \BigCommerce\Pages\Account_Page::SLUG, - \BigCommerce\Pages\Address_Page::SLUG, - \BigCommerce\Pages\Cart_Page::SLUG, - \BigCommerce\Pages\Check_Balance_Page::SLUG, - \BigCommerce\Pages\Checkout_Complete_Page::SLUG, - \BigCommerce\Pages\Checkout_Page::SLUG, - \BigCommerce\Pages\Login_Page::SLUG, - \BigCommerce\Pages\Gift_Certificate_Page::SLUG, - \BigCommerce\Pages\Orders_Page::SLUG, - \BigCommerce\Pages\Registration_Page::SLUG, - \BigCommerce\Pages\Shipping_Returns_Page::SLUG, - \BigCommerce\Pages\Wishlist_Page::SLUG - ]; - - if ( ! in_array( get_queried_object()->post_name, $plugin_pages ) ) { - return $preempt; - } - - global $wp_query; - $wp_query->set_404(); - status_header( 404 ); - nocache_headers(); - - return ''; - }, 10, 1 ); + + add_filter( 'pre_handle_404', function ( $preempt ) { + if ( is_admin() || ! ( is_page() && is_main_query() ) ) { + return $preempt; + } + + $plugin_pages = [ + \BigCommerce\Pages\Account_Page::SLUG, + \BigCommerce\Pages\Address_Page::SLUG, + \BigCommerce\Pages\Cart_Page::SLUG, + \BigCommerce\Pages\Check_Balance_Page::SLUG, + \BigCommerce\Pages\Checkout_Complete_Page::SLUG, + \BigCommerce\Pages\Checkout_Page::SLUG, + \BigCommerce\Pages\Login_Page::SLUG, + \BigCommerce\Pages\Gift_Certificate_Page::SLUG, + \BigCommerce\Pages\Orders_Page::SLUG, + \BigCommerce\Pages\Registration_Page::SLUG, + \BigCommerce\Pages\Shipping_Returns_Page::SLUG, + \BigCommerce\Pages\Wishlist_Page::SLUG + ]; + + if ( ! in_array( get_queried_object()->post_name, $plugin_pages ) ) { + return $preempt; + } + + global $wp_query; + $wp_query->set_404(); + status_header( 404 ); + nocache_headers(); + + return ''; + }, 10, 1 ); } function bigcommerce() { @@ -125,39 +129,39 @@ function bigcommerce() { * @return mixed The found value. false if not found. */ function bigcommerce_get_env( $key ) { - $value = getenv( $key, true ) ?: getenv( $key ); - if ( $value === false && defined( $key ) ) { - $value = constant( $key ); - } + $value = getenv( $key, true ) ?: getenv( $key ); + if ( $value === false && defined( $key ) ) { + $value = constant( $key ); + } - return $value; + return $value; } /** - * Get the status of the primary channel + * Get the status of the primary channel. * * @return mixed The found value. null if not found. */ function bigcommerce_get_primary_channel_status() { - $cache_key = 'bigcommerce_primary_channel_status'; - $status = wp_cache_get( $cache_key ); - if ( empty( $status ) ) { - global $wpdb; - - $sql = "SELECT tm.meta_value - FROM {$wpdb->termmeta} tm - INNER JOIN {$wpdb->termmeta} tm2 ON tm2.term_id=tm.term_id - WHERE tm.meta_key=%s AND tm2.meta_key=%s AND tm2.meta_value=%s"; - - $status = $wpdb->get_var( $wpdb->prepare( - $sql, - BC_Status::STATUS, - \BigCommerce\Taxonomies\Channel\Channel::STATUS, - \BigCommerce\Taxonomies\Channel\Channel::STATUS_PRIMARY - ) ); - - wp_cache_set( $cache_key, $status ); - } + $cache_key = 'bigcommerce_primary_channel_status'; + $status = wp_cache_get( $cache_key ); + if ( empty( $status ) ) { + global $wpdb; + + $sql = "SELECT tm.meta_value + FROM {$wpdb->termmeta} tm + INNER JOIN {$wpdb->termmeta} tm2 ON tm2.term_id=tm.term_id + WHERE tm.meta_key=%s AND tm2.meta_key=%s AND tm2.meta_value=%s"; + + $status = $wpdb->get_var( $wpdb->prepare( + $sql, + BC_Status::STATUS, + \BigCommerce\Taxonomies\Channel\Channel::STATUS, + \BigCommerce\Taxonomies\Channel\Channel::STATUS_PRIMARY + ) ); + + wp_cache_set( $cache_key, $status ); + } return $status; } diff --git a/src/BigCommerce/Accounts/Channel_Settings.php b/src/BigCommerce/Accounts/Channel_Settings.php index 43e77204..cf088e2e 100644 --- a/src/BigCommerce/Accounts/Channel_Settings.php +++ b/src/BigCommerce/Accounts/Channel_Settings.php @@ -9,33 +9,42 @@ use BigCommerce\Taxonomies\Channel\Connections; use BigCommerce\Settings\Sections\Account_Settings; - +/** + * Manages channel settings related to global logins, syncing customer settings, + * and scheduling resyncs for updated global login configurations. + */ class Channel_Settings { + /** @const int RESYNC_TIME The time interval in seconds to resync global logins. */ const RESYNC_TIME = 600; + /** @var int The channel ID. */ protected $channel_id; - /** - * @var Connections - */ + /** @var Connections The Connections instance for managing channels. */ protected $connections; - /** - * @var CustomersApi - */ + /** @var CustomersApi The Customers API instance for updating customer settings. */ protected $customers; + /** + * Channel_Settings constructor. + * + * @param Connections $connections The Connections instance for managing channels. + * @param CustomersApi $customers The Customers API instance for updating customer settings. + */ public function __construct( Connections $connections, CustomersApi $customers ) { $this->connections = $connections; $this->customers = $customers; } - /** - * Get current channel id - * - * @return int - */ + /** + * Get the current channel ID. + * + * Retrieves the channel ID associated with the current active channel from the Connections instance. + * + * @return int The channel ID, or 0 if no channel is found. + */ protected function get_channel_id() { if ( ! $this->channel_id ) { try { @@ -43,8 +52,7 @@ protected function get_channel_id() { if ( $current_channel ) { $this->channel_id = (int) get_term_meta( $current_channel->term_id, Channel::CHANNEL_ID, true ); } - } catch (\Exception $e) { - + } catch ( \Exception $e ) { } } @@ -52,18 +60,22 @@ protected function get_channel_id() { } /** + * Sync global logins for the current channel. + * + * Updates the global login setting for the current channel. If the channel ID is unavailable, + * it will schedule a resync for later. + * * @return void - * @action bigcommerce/sync_global_logins + * @action bigcommerce/sync_global_logins Triggered when syncing global logins. */ public function sync_global_logins() { $channel_id = $this->get_channel_id(); if ( ! $channel_id ) { - // Do this another time when channel is connected + // Do this another time when the channel is connected $this->schedule_resync(); return; } - try { $allow_global_logins = (bool) get_option( Account_Settings::ALLOW_GLOBAL_LOGINS, true ); @@ -71,7 +83,7 @@ public function sync_global_logins() { 'allow_global_logins' => $allow_global_logins ] ); - // If action was successful + // If the action was successful if ( $response->getData()->getAllowGlobalLogins() === $allow_global_logins ) { $this->clear_all_scheduled_events(); } else { @@ -84,6 +96,11 @@ public function sync_global_logins() { } /** + * Schedule a resync for global logins. + * + * Schedules a resync of global logins by setting a single event to trigger + * after a predefined interval (RESYNC_TIME). + * * @return void */ protected function schedule_resync() { @@ -92,8 +109,13 @@ protected function schedule_resync() { } /** + * Schedule a sync for the channel. + * + * Triggers a sync for global logins by turning on the option for new channels, + * avoiding triggering the update_option listener, and scheduling the sync. + * * @return void - * @action bigcommerce/channel/promote + * @action bigcommerce/channel/promote Triggered when promoting a channel. */ public function schedule_sync() { // Turn on the option for new channels @@ -106,6 +128,10 @@ public function schedule_sync() { } /** + * Clear all scheduled events for syncing global logins. + * + * Clears the scheduled events for the "bigcommerce/sync_global_logins" hook. + * * @return void */ protected function clear_all_scheduled_events() { diff --git a/src/BigCommerce/Accounts/Countries.php b/src/BigCommerce/Accounts/Countries.php index 463007be..bedc7cbe 100644 --- a/src/BigCommerce/Accounts/Countries.php +++ b/src/BigCommerce/Accounts/Countries.php @@ -5,18 +5,31 @@ /** * Class Countries + * + * Handles loading and retrieving country data from a JSON file, and injecting + * country data into JavaScript configuration arrays. */ class Countries { private $data_file; private $data; + /** + * Countries constructor. + * + * @param string $data_file The path to the JSON file containing country data. + */ public function __construct( $data_file ) { $this->data_file = $data_file; } /** - * @return array - * @filter bigcommerce/countries/data + * Get a list of countries. + * + * Loads the country data from the JSON file if it hasn't been loaded yet, + * and returns the data as an array. + * + * @return array The list of countries loaded from the JSON file. + * @filter bigcommerce/countries/data Filter applied to the countries data before returning. */ public function get_countries() { $this->load_data(); @@ -24,19 +37,31 @@ public function get_countries() { return $this->data; } + /** + * Load country data from the JSON file. + * + * If the country data hasn't already been loaded, this method loads it from the specified + * JSON file and decodes it into an array. + * + * @return void + */ private function load_data() { - if ( isset( $data ) ) { - return; // already loaded + if ( isset( $this->data ) ) { + return; // Data is already loaded } $this->data = (array) json_decode( file_get_contents( $this->data_file ) ); } /** - * @param array $config + * Inject country data into JavaScript configuration. * - * @return array - * @filter bigcommerce/js_config - * @filter bigcommerce/admin/js_config + * Adds the list of countries to the provided JavaScript configuration array under the "countries" key. + * + * @param array $config The JavaScript configuration array to modify. + * + * @return array The modified JavaScript configuration array. + * @filter bigcommerce/js_config Filter applied to the JavaScript configuration before returning. + * @filter bigcommerce/admin/js_config Filter applied to the admin JavaScript configuration before returning. */ public function js_config( $config ) { $config[ 'countries' ] = $this->get_countries(); diff --git a/src/BigCommerce/Accounts/Customer.php b/src/BigCommerce/Accounts/Customer.php index c4a1d0d3..98133349 100644 --- a/src/BigCommerce/Accounts/Customer.php +++ b/src/BigCommerce/Accounts/Customer.php @@ -16,22 +16,40 @@ use BigCommerce\Taxonomies\Channel\Connections; /** - * Class Customer + * Handles customer-specific data and resources such as customer addresses, profiles, orders, and related functionalities. * - * Handle customer specific data and resources e.g. address, profile, orders amount and other + * This class interacts with the BigCommerce API to fetch and manage data for customers associated with WordPress users. */ class Customer { + /** + * Constant for customer ID meta key. + * + * @var string + */ const CUSTOMER_ID_META = 'bigcommerce_customer_id'; + /** + * The WordPress user ID associated with the customer. + * + * @var int + */ private $wp_user_id = 0; + /** + * Customer constructor. + * + * @param int $wp_user_id The WordPress user ID associated with the customer. + */ public function __construct( $wp_user_id ) { $this->wp_user_id = $wp_user_id; } /** - * Get customer addresses - * @return array + * Get customer addresses. + * + * Fetches all the addresses associated with the customer. + * + * @return array An array of addresses associated with the customer. */ public function get_addresses() { $customer_id = $this->get_customer_id(); @@ -51,13 +69,15 @@ public function get_addresses() { } } - /** - * Delete customer address by address id - * - * @param $address_id - * - * @return bool - */ + /** + * Delete a customer's address by address ID. + * + * Deletes the address associated with the provided address ID for the customer. + * + * @param int $address_id The ID of the address to be deleted. + * + * @return bool Returns true if the address was successfully deleted, false otherwise. + */ public function delete_address( $address_id ) { $customer_id = $this->get_customer_id(); if ( ! $customer_id ) { @@ -72,13 +92,15 @@ public function delete_address( $address_id ) { } } - /** - * Create customer address - * - * @param $address - * - * @return bool - */ + /** + * Add a new address for the customer. + * + * Adds a new address to the customer's account. + * + * @param array $address The address data to be added. + * + * @return bool Returns true if the address was successfully added, false otherwise. + */ public function add_address( $address ) { $customer_id = $this->get_customer_id(); if ( ! $customer_id ) { @@ -93,14 +115,16 @@ public function add_address( $address ) { } } - /** - * Update customer address by id - * - * @param $address_id - * @param $address - * - * @return bool - */ + /** + * Update a customer's address by address ID. + * + * Updates an existing address based on the provided address ID. + * + * @param int $address_id The ID of the address to be updated. + * @param array $address The updated address data. + * + * @return bool Returns true if the address was successfully updated, false otherwise. + */ public function update_address( $address_id, $address ) { $customer_id = $this->get_customer_id(); if ( ! $customer_id ) { @@ -115,11 +139,13 @@ public function update_address( $address_id, $address ) { } } - /** - * Get amount of orders for the customer - * - * @return int - */ + /** + * Get the number of orders for the customer. + * + * Returns the total count of orders placed by the customer. + * + * @return int The number of orders associated with the customer. + */ public function get_order_count() { $customer_id = $this->get_customer_id(); if ( ! $customer_id ) { @@ -137,19 +163,16 @@ public function get_order_count() { } /** - * Get the most recent orders on the account. Each will include - * at least one product (useful for finding featured images), - * but is not guaranteed to include all. + * Get the most recent orders of the customer. * - * WARNING: This function is heavy on API calls. One call for the - * order list, plus another for each order in the list. + * Returns a list of the most recent orders for the customer, each including at least one product. + * Note that this function makes multiple API calls and should be optimized for scalability in the future. * - * @param int $page - * @param int $limit - * - * @return array - * @todo Optimize for scalability + * @param int $page The page number of results. + * @param int $limit The number of results per page. * + * @return array A list of the most recent orders of the customer. + * @todo Optimize for scalability. */ public function get_orders( $page = 1, $limit = 12 ) { $customer_id = $this->get_customer_id(); @@ -180,12 +203,15 @@ public function get_orders( $page = 1, $limit = 12 ) { } } - /** - * Get customer order details by order id - * - * @param $order_id - * @return array|false - */ + /** + * Get detailed information for a specific customer order. + * + * Fetches detailed information about the specified order, including products and shipping addresses. + * + * @param int $order_id The ID of the order to retrieve. + * + * @return array|false An array of order details or false if the order is not found. + */ public function get_order_details( $order_id ) { $order = Client::getOrder( $order_id ); if ( empty( $order ) || $order->customer_id != $this->get_customer_id() ) { @@ -254,11 +280,14 @@ private function flatten_resource( Resource $resource ) { return $item; } - /** - * Get customer profile data - * - * @return array|mixed|void - */ + + /** + * Get the profile data of the customer. + * + * Returns the customer's profile information, including fields like name, email, and customer group. + * + * @return array An array of customer profile data. + */ public function get_profile() { $customer_id = $this->get_customer_id(); if ( ! $customer_id ) { @@ -291,12 +320,13 @@ public function get_profile() { } } - /** - * Update customer profile data - * @param $profile - * - * @return bool - */ + /** + * Update the profile data of the customer. + * + * @param array $profile The profile data to update. + * + * @return bool Returns true if the profile was successfully updated, false otherwise. + */ public function update_profile( $profile ) { $customer_id = $this->get_customer_id(); if ( ! $customer_id ) { @@ -312,7 +342,9 @@ public function update_profile( $profile ) { } /** - * @return int The ID of the customer account linked to this user + * Get the customer ID linked to the current WordPress user. + * + * @return int The customer ID associated with the WordPress user. */ public function get_customer_id() { $customer_id = get_user_option( self::CUSTOMER_ID_META, $this->wp_user_id ); @@ -321,9 +353,9 @@ public function get_customer_id() { } /** - * @param int $customer_id The customer ID to link to this user + * Set the customer ID linked to the current WordPress user. * - * @return void + * @param int $customer_id The customer ID to link to the WordPress user. */ public function set_customer_id( $customer_id ) { update_user_option( $this->wp_user_id, self::CUSTOMER_ID_META, $customer_id ); @@ -331,10 +363,8 @@ public function set_customer_id( $customer_id ) { /** * Get the customer group ID assigned to the user. - * Value will be fetched from cache if available, - * otherwise from the API. * - * @return int|null + * @return int|null The group ID of the customer, or null if the user is a guest. */ public function get_group_id() { $customer_id = is_user_logged_in() || defined( 'DOING_CRON' ) ? get_user_option( self::CUSTOMER_ID_META, $this->wp_user_id ) : 0; @@ -380,7 +410,9 @@ public function get_group_id() { } /** - * @return array|null + * Get the default group for guest users. + * + * @return array|null An array of default customer group IDs for guests, or null if none are found. */ public function get_guests_default_group() { $args = [ @@ -391,6 +423,13 @@ public function get_guests_default_group() { $customer_groups = Client::getCustomerGroups( $query ); if ( empty( $customer_groups ) ) { + /** + * Log information about empty customer groups. + * + * @param string $level The log level (INFO) + * @param string $message The log message + * @param array $context Additional context data + */ do_action( 'bigcommerce/log', Error_Log::INFO, __( 'Customer groups are empty', 'bigcommerce' ), [] ); return null; } @@ -408,9 +447,9 @@ public function get_guests_default_group() { } /** - * Get the customer group associated with this customer + * Get the customer group for the current customer. * - * @return Customer_Group + * @return Customer_Group The customer group object associated with the customer. */ public function get_group() { return new Customer_Group( $this->get_group_id() ); diff --git a/src/BigCommerce/Accounts/Customer_Group.php b/src/BigCommerce/Accounts/Customer_Group.php index 3c3eb254..d189c8e9 100644 --- a/src/BigCommerce/Accounts/Customer_Group.php +++ b/src/BigCommerce/Accounts/Customer_Group.php @@ -5,33 +5,44 @@ /** * Class Customer_Group + * + * Represents a customer group in BigCommerce and provides methods to retrieve group information. */ class Customer_Group { - /** @var int */ + /** @var int The ID of the customer group. */ private $group_id; /** - * @param int $group_id + * Customer_Group constructor. + * + * Initializes the customer group with the specified group ID. + * + * @param int $group_id The ID of the customer group. */ public function __construct( $group_id ) { $this->group_id = $group_id; } /** - * Get info about a customer group. Properties include: - * - id int The group ID - * - name string The group name - * - is_default bool Whether the group is the default for new customers - * - discount_rules array Discount rules applied to the group + * Get information about the customer group. + * + * Retrieves information about the customer group, including: + * - id (int) The group ID + * - name (string) The group name + * - is_default (bool) Whether the group is the default for new customers + * - discount_rules (array) Discount rules applied to the group + * + * The returned data can be filtered using the `bigcommerce/customer/group_info` filter. * - * @return array + * @return array The customer group information. + * @filter bigcommerce/customer/group_info A filter applied to the customer group info before returning. */ public function get_info() { /** * Filters customer group info. * - * @param array $default_group The default group - * @param int $group_id The group id. + * @param array $default_group The default group data. + * @param int $group_id The group ID. */ return apply_filters( 'bigcommerce/customer/group_info', $this->get_default_group(), $this->group_id ); } diff --git a/src/BigCommerce/Accounts/Customer_Group_Proxy.php b/src/BigCommerce/Accounts/Customer_Group_Proxy.php index 6a590be2..07d486a7 100644 --- a/src/BigCommerce/Accounts/Customer_Group_Proxy.php +++ b/src/BigCommerce/Accounts/Customer_Group_Proxy.php @@ -8,22 +8,28 @@ /** * Class Customer_Group_Proxy * - * Adds a caching proxy in front of requests for customer group info + * Adds a caching proxy in front of requests for customer group information. */ class Customer_Group_Proxy { /** - * @param array $info - * @param int $id + * Filter and merge additional customer group info. * - * @return array - * @filter bigcommerce/customer/group_info + * This method checks if the customer group information is available in the cache; + * if not, it fetches it from the API and caches it. The result is merged with the existing + * group information before being returned. + * + * @param array $info The existing customer group information. + * @param int $id The ID of the customer group. + * + * @return array The merged customer group information. + * @filter bigcommerce/customer/group_info Filter applied to the customer group info before returning. */ public function filter_group_info( $info, $id ) { $data = $this->fetch_from_cache( $id ) ?: $this->fetch_from_api( $id ); if ( empty( $data ) ) { - return $info; // nothing to add + return $info; // No additional data to merge } return array_merge( $info, $data ); @@ -58,7 +64,7 @@ private function fetch_from_api( $group_id ) { $info = wp_json_encode( $info ); $this->set_cache( $info, $group_id ); - return json_decode( $info, true ); // doing the encode/decode for consistency with the output from cache + return json_decode( $info, true ); // Ensuring consistency with cached data format } private function set_cache( $info, $group_id ) { @@ -66,8 +72,8 @@ private function set_cache( $info, $group_id ) { /** * Filter the duration of the group info cache. * - * @param int $expiration Time until expiration, in seconds - * @param int $group_id The ID of the group being cached + * @param int $expiration Time until expiration, in seconds. + * @param int $group_id The ID of the group being cached. */ $expiration = apply_filters( 'bigcommerce/customer/group_info_cache_expiration', HOUR_IN_SECONDS, $group_id ); diff --git a/src/BigCommerce/Accounts/Login.php b/src/BigCommerce/Accounts/Login.php index 72736c55..ef41def0 100644 --- a/src/BigCommerce/Accounts/Login.php +++ b/src/BigCommerce/Accounts/Login.php @@ -5,7 +5,6 @@ use BigCommerce\Accounts\Roles\Customer as Customer_Role; -use Bigcommerce\Api; use BigCommerce\Api_Factory; use BigCommerce\Import\Processors\Store_Settings; use BigCommerce\Pages\Account_Page; @@ -21,16 +20,25 @@ use WP_User; /** - * Class Login - * - * Handle login/lost password logic for the account + * Handles the login and lost password logic for the BigCommerce account integration with WordPress. + * This class connects WordPress users to BigCommerce customers, processes customer login, and provides the necessary functionality for user management. */ class Login { + /** + * The constant for storing the BigCommerce customer ID meta key. + */ const CUSTOMER_ID_META = 'bigcommerce_customer_id'; - /** @var Api_Factory */ + /** + * @var Api_Factory The factory class for creating API instances. + */ private $api_factory; + /** + * Login constructor. + * + * @param Api_Factory $api_factory The API factory to be used for creating API instances. + */ public function __construct( Api_Factory $api_factory ) { $this->api_factory = $api_factory; } @@ -77,7 +85,7 @@ private function find_customer_id_by_email( $email ) { } /** - * Create BC customer from wp user + * Create BC customer from wp user * @param \WP_User $user * * @return int The new customer's ID, 0 on failure @@ -175,7 +183,7 @@ public function login_error_handler( $errors, $redirect ) { } /** - * Get lost password url + * Get lost password url * @param string $login_url * @param string $redirect * @@ -202,7 +210,7 @@ public function lostpassword_url( $login_url, $redirect ) { /** - * If a user exists only on BC, try to sync before reset pasword email is sent. + * If a user exists only on BC, try to sync before reset password email is sent. * * @param WP_User|false $user_data WP_User object if found, false if the user does not exist. * @param \WP_Error $errors A WP_Error object containing any errors generated @@ -428,7 +436,7 @@ public function authenticate_new_user( $user, $username, $password ) { if ( Store_Settings::is_msf_on() && ! $is_allow_global_logins && ! $is_belong_to_channel ) { return new \WP_Error( 'incorrect_email', sprintf( - __( 'The access for %s is prohibited. Please create a new user ot try another one', 'bigcommerce' ), + __( 'The access for %s is prohibited. Please create a new user or try another one', 'bigcommerce' ), $username ) ); @@ -465,8 +473,8 @@ public function authenticate_new_user( $user, $username, $password ) { } /** - * Validate password for accounts - * + * Validate password for accounts + * * @param bool $match Whether the passwords match. * @param string $password The plaintext password. * @param string $hash The hashed password. @@ -512,13 +520,13 @@ public function check_password_for_linked_accounts( $match, $password, $hash, $u } } - /** - * Delete WP user - * - * @param $user_id - * - * @param $customer_id - */ + /** + * Delete WP user + * + * @param $user_id + * + * @param $customer_id + */ private function delete_user( $user_id, $customer_id ) { /** * Filter whether to delete WordPress users tied to BigCommerce diff --git a/src/BigCommerce/Accounts/Nav_Menu.php b/src/BigCommerce/Accounts/Nav_Menu.php index ae68cf61..6a36fae0 100644 --- a/src/BigCommerce/Accounts/Nav_Menu.php +++ b/src/BigCommerce/Accounts/Nav_Menu.php @@ -14,101 +14,100 @@ /** * Class Nav_Menu * - * Set menu items + * Responsible for setting and filtering navigation menu items related to account pages. */ class Nav_Menu { - /** - * Filter account menu items + /** + * Filters the account menu items based on the page ID. * - * @param object $menu_item - * - * @return object - * @filter wp_setup_nav_menu_item - */ - public function filter_account_menu_items( $menu_item ) { - if ( $menu_item->object != 'page' ) { - return $menu_item; - } - $page_id = $menu_item->object_id; - switch ( $page_id ) { - case get_option( Login_Page::NAME, 0 ): - return $this->setup_login_menu_item( $menu_item ); - case get_option( Registration_Page::NAME, 0 ): - return $this->setup_registration_menu_item( $menu_item ); - case get_option( Account_Page::NAME, 0 ): - case get_option( Orders_Page::NAME, 0 ): - case get_option( Address_Page::NAME, 0 ): - case get_option( Wishlist_Page::NAME, 0 ): - return $this->setup_account_page_menu_item( $menu_item ); - default: - return $menu_item; - } - - } + * @param object $menu_item The menu item to filter. + * + * @return object The filtered menu item. + * @filter wp_setup_nav_menu_item + */ + public function filter_account_menu_items( $menu_item ) { + if ( $menu_item->object != 'page' ) { + return $menu_item; + } + $page_id = $menu_item->object_id; + switch ( $page_id ) { + case get_option( Login_Page::NAME, 0 ): + return $this->setup_login_menu_item( $menu_item ); + case get_option( Registration_Page::NAME, 0 ): + return $this->setup_registration_menu_item( $menu_item ); + case get_option( Account_Page::NAME, 0 ): + case get_option( Orders_Page::NAME, 0 ): + case get_option( Address_Page::NAME, 0 ): + case get_option( Wishlist_Page::NAME, 0 ): + return $this->setup_account_page_menu_item( $menu_item ); + default: + return $menu_item; + } + } /** - * Return login/logout menu item + * Sets up the login/logout menu item. * - * @param $menu_item + * @param \WP_Post $menu_item The menu item to modify. * - * @return mixed + * @return \WP_Post The modified menu item. */ - public function setup_login_menu_item( $menu_item ) { - if ( is_user_logged_in() && ! is_admin() ) { - $menu_item->url = wp_logout_url(); - /** - * Filter the title of the Sign Out link in the nav menu - * - * @param string $title The menu item title - * @param \WP_Post $menu_item The menu item, a \WP_Post that has passed through wp_setup_nav_menu_item() - */ - $menu_item->title = apply_filters( 'bigcommerce/nav/logout/title', __( 'Sign Out', 'bigcommerce' ), $menu_item ); - } + public function setup_login_menu_item( $menu_item ) { + if ( is_user_logged_in() && ! is_admin() ) { + $menu_item->url = wp_logout_url(); + /** + * Filters the title of the Sign Out link in the navigation menu. + * + * @param string $title The menu item title. + * @param \WP_Post $menu_item The menu item, a \WP_Post that has passed through wp_setup_nav_menu_item(). + */ + $menu_item->title = apply_filters( 'bigcommerce/nav/logout/title', __( 'Sign Out', 'bigcommerce' ), $menu_item ); + } - return $menu_item; - } + return $menu_item; + } /** - * Adds sign up menu item + * Adds the registration/signup menu item. * - * @param $menu_item + * @param \WP_Post $menu_item The menu item to modify. * - * @return mixed + * @return \WP_Post The modified menu item. */ - public function setup_registration_menu_item( $menu_item ) { - if ( is_user_logged_in() && ! is_admin() ) { - $account_page = get_option( Account_Page::NAME, 0 ); - if ( $account_page ) { - $menu_item->url = get_permalink( $account_page ); - /** - * Filter the title of the My Account link in the nav menu - * - * @param string $title The menu item title - * @param \WP_Post $menu_item The menu item, a \WP_Post that has passed through wp_setup_nav_menu_item() - */ - $menu_item->title = apply_filters( 'bigcommerce/nav/account/title', __( 'My Account', 'bigcommerce' ), $menu_item ); - } else { - $menu_item->_invalid = true; - } - } elseif ( ! get_option( 'users_can_register' ) ) { - $menu_item->_invalid = true; - } + public function setup_registration_menu_item( $menu_item ) { + if ( is_user_logged_in() && ! is_admin() ) { + $account_page = get_option( Account_Page::NAME, 0 ); + if ( $account_page ) { + $menu_item->url = get_permalink( $account_page ); + /** + * Filters the title of the My Account link in the navigation menu. + * + * @param string $title The menu item title. + * @param \WP_Post $menu_item The menu item, a \WP_Post that has passed through wp_setup_nav_menu_item(). + */ + $menu_item->title = apply_filters( 'bigcommerce/nav/account/title', __( 'My Account', 'bigcommerce' ), $menu_item ); + } else { + $menu_item->_invalid = true; + } + } elseif ( ! get_option( 'users_can_register' ) ) { + $menu_item->_invalid = true; + } - return $menu_item; - } + return $menu_item; + } /** - * Set an account menu item + * Sets up the account-related menu item. * - * @param $menu_item + * @param \WP_Post $menu_item The menu item to modify. * - * @return mixed + * @return \WP_Post The modified menu item. */ - public function setup_account_page_menu_item( $menu_item ) { - if ( ! is_user_logged_in() ) { - $menu_item->_invalid = true; - } + public function setup_account_page_menu_item( $menu_item ) { + if ( ! is_user_logged_in() ) { + $menu_item->_invalid = true; + } - return $menu_item; - } + return $menu_item; + } } diff --git a/src/BigCommerce/Accounts/Password_Reset.php b/src/BigCommerce/Accounts/Password_Reset.php index 17c81c41..5304314e 100644 --- a/src/BigCommerce/Accounts/Password_Reset.php +++ b/src/BigCommerce/Accounts/Password_Reset.php @@ -5,100 +5,104 @@ use BigCommerce\Api\Customer_Api; /** - * Class Password Reset + * Class Password_Reset * - * Responsible for customer password reset + * Responsible for handling customer password reset and synchronization with BigCommerce. */ class Password_Reset { - /** @var Customer_Api */ - private $customer_api; + /** @var Customer_Api */ + private $customer_api; - public function __construct( Customer_Api $customer_api ) { - $this->customer_api = $customer_api; - } + /** + * Password_Reset constructor. + * + * @param Customer_Api $customer_api The Customer_Api instance for interacting with BigCommerce's API. + */ + public function __construct( Customer_Api $customer_api ) { + $this->customer_api = $customer_api; + } - /** - * When a user submits the reset password form on the front end, - * sync with BigCommerce. - * - * @param \WP_User $user The user. - * @param string $new_pass New user password. - * - * @return void - * @action after_password_reset - */ - public function sync_reset_password_with_bigcommerce( $user, $new_pass ) { - $sync = get_user_meta( $user->ID, User_Profile_Settings::SYNC_PASSWORD, true ); - if ( ! $sync ) { - return; - } + /** + * Syncs the password reset with BigCommerce when a user submits the reset password form on the front end. + * + * @param \WP_User $user The WordPress user object. + * @param string $new_pass The new user password. + * + * @return void + * @action after_password_reset + */ + public function sync_reset_password_with_bigcommerce( $user, $new_pass ) { + $sync = get_user_meta( $user->ID, User_Profile_Settings::SYNC_PASSWORD, true ); + if ( ! $sync ) { + return; + } - $this->set_password( $user, $new_pass ); - } + $this->set_password( $user, $new_pass ); + } - /** - * When a user's password is updated from the admin, sync with BigCommerce. - * - * @param int $user_id User ID. - * @param \WP_User $old_user_data Object containing user's data prior to update. - * - * @return void - * @action profile_update - */ - public function sync_password_change_with_bigcommerce( $user_id, $old_user_data ) { - // $_POST is the only place we can find the plain text password - $pass1 = filter_input( INPUT_POST, 'pass1', FILTER_UNSAFE_RAW ); // phpcs:ignore - if ( empty( $pass1 ) ) { - return; // not a request to update a user's password - } - $sync = get_user_meta( $user_id, User_Profile_Settings::SYNC_PASSWORD, true ); - if ( ! $sync ) { - return; - } - $current_user = new \WP_User( $user_id ); + /** + * Syncs the password change with BigCommerce when a user's password is updated from the admin. + * + * @param int $user_id The user ID. + * @param \WP_User $old_user_data The WP_User object containing user's data prior to update. + * + * @return void + * @action profile_update + */ + public function sync_password_change_with_bigcommerce( $user_id, $old_user_data ) { + // $_POST is the only place we can find the plain text password + $pass1 = filter_input( INPUT_POST, 'pass1', FILTER_UNSAFE_RAW ); // phpcs:ignore + if ( empty( $pass1 ) ) { + return; // not a request to update a user's password + } + $sync = get_user_meta( $user_id, User_Profile_Settings::SYNC_PASSWORD, true ); + if ( ! $sync ) { + return; + } + $current_user = new \WP_User( $user_id ); - if ( $current_user->user_pass === $old_user_data->user_pass ) { - return; // nothing changes - } + if ( $current_user->user_pass === $old_user_data->user_pass ) { + return; // nothing changes + } - $this->set_password( $current_user, $pass1 ); - } + $this->set_password( $current_user, $pass1 ); + } - /** - * Set customer password + /** + * Sets the customer's password in BigCommerce. + * + * @param \WP_User $user The WordPress user object. + * @param string $password The new password to set. * - * @param \WP_User $user - * @param string $password - * - * @return bool Whether the password was updated - */ - private function set_password( $user, $password ) { - $customer = new Customer( $user->ID ); - $customer_id = $customer->get_customer_id(); - if ( ! $customer_id ) { - /* - * If an account is set to sync with BigCommerce, but we don't know - * the customer ID, we'll look it up here. - */ - $customer_id = $this->customer_api->find_customer_id_by_email( $user->user_email ); - } - if ( ! $customer_id ) { - return false; - } + * @return bool Whether the password was successfully updated in BigCommerce. + */ + private function set_password( $user, $password ) { + $customer = new Customer( $user->ID ); + $customer_id = $customer->get_customer_id(); + if ( ! $customer_id ) { + /* + * If an account is set to sync with BigCommerce, but we don't know + * the customer ID, we'll look it up here. + */ + $customer_id = $this->customer_api->find_customer_id_by_email( $user->user_email ); + } + if ( ! $customer_id ) { + return false; + } - $profile = [ - '_authentication' => [ - 'password' => $password, - ], - ]; + $profile = [ + '_authentication' => [ + 'password' => $password, + ], + ]; - try { - $this->customer_api->updateCustomer( $customer_id, $profile ); + try { + $this->customer_api->updateCustomer( $customer_id, $profile ); - return true; - } catch ( \Exception $e ) { - return false; - } - } + return true; + } catch ( \Exception $e ) { + return false; + } + } } diff --git a/src/BigCommerce/Accounts/Register.php b/src/BigCommerce/Accounts/Register.php index 765aeb22..493370c5 100644 --- a/src/BigCommerce/Accounts/Register.php +++ b/src/BigCommerce/Accounts/Register.php @@ -9,147 +9,183 @@ use BigCommerce\Webhooks\Customer\Customer_Channel_Updater; /** - * Handles customer creation - * @class Bigcommerce\Accounts\Register + * Class Register + * + * Handles customer creation and synchronization with BigCommerce. */ class Register { - /** - * @var \BigCommerce\Api_Factory - */ - private $factory; - - /** - * @var \BigCommerce\Taxonomies\Channel\Connections - */ - private $connections; - - public function __construct( Api_Factory $api_factory, Connections $connections ) { - $this->factory = $api_factory; - $this->connections = $connections; - } - - /** - * Create customer if it doesn't exist on Bigcommerce - * - * @param $user_id - * @param $userdata - */ - public function maybe_create_new_customer( $user_id, $userdata ) { - if ( empty( $userdata['role'] ) || $userdata['role'] !== \BigCommerce\Accounts\Roles\Customer::NAME ) { - return; - } - - $customer_id = get_user_meta( $user_id, Customer::CUSTOMER_ID_META, true ); - - // Customer already connected - if ( ! empty( $customer_id ) ) { - return; - } - - $customer_id = $this->is_customer_mail_in_use( $userdata['user_email'] ); - - if ( $customer_id ) { - // Connect existing customer - $customer = new Customer( $user_id ); - $customer->set_customer_id( $customer_id ); - return; - } - - $this->register_new_customer( $user_id, $userdata ); - - $channel = $this->connections->primary(); - $channel_id = get_term_meta( $channel->term_id, Channel::CHANNEL_ID, true ); - update_user_meta( $user_id, Customer_Channel_Updater::CUSTOMER_CHANNEL_META, [ $channel_id] ); - update_user_meta( $user_id, Customer_Channel_Updater::CUSTOMER_ORIGIN_CHANNEL, $channel_id ); - } - - /** - * Check if customer email is already owned - * - * @param $email - * - * @return bool - */ - protected function is_customer_mail_in_use( $email ) { - try { - $customer_api = $this->factory->customer(); - $matches = $customer_api->getCustomers( [ - 'email' => $email, - ] ); - - if ( ! empty( $matches ) ) { - $found_customer = reset( $matches ); - return $found_customer->id; - } - - return false; - } catch( \Exception $exception ) { - do_action( 'bigcommerce/log', Error_Log::DEBUG, __( 'Could not check if user exists.', 'bigcommerce' ), [ - 'user_email' => $email, - ] ); - do_action( 'bigcommerce/log', Error_Log::DEBUG, $exception->getMessage() , [ - 'trace' => $exception->getTraceAsString(), - ] ); - // We are not able to check and due to this we should avoid customer creation - return true; - } - } - - /** - * Create new customer with V3 API and associate primary channel - * - * @param $user_id - * @param $userdata - * - * @return int - */ - protected function register_new_customer( $user_id, $userdata ) { - try { - $customer_api = $this->factory->customers(); - $channel = $this->connections->primary(); - $channel_id = get_term_meta( $channel->term_id, Channel::CHANNEL_ID, true ); - - $new_customer_data = [ - 'first_name' => $userdata['first_name'] ?: $userdata['user_login'], - 'last_name' => $userdata['last_name'] ?: __( 'User', 'bigcommerce' ), - 'email' => $userdata['user_email'], - 'customer_group_id' => 0, - 'authentication' => [ - 'force_password_reset' => true, - 'new_password' => $userdata['user_pass'] - ], - 'origin_channel_id' => ( int ) $channel_id, - 'channels_ids' => [ ( int ) $channel_id ], - ]; - - /** - * Filters customer create arguments. - * - * @param array $new_customer_data Customer data. - */ - $new_customer_data = apply_filters( 'bigcommerce/customer/create/args', $new_customer_data ); - - $response = $customer_api->customersPost( [ $new_customer_data ] ); - - if ( $response && ! empty( $response->id ) ) { - $customer = new Customer( $user_id); - $customer->set_customer_id( $response->id ); - - return $response->id; - } - } catch ( \Exception $exception ) { - do_action( 'bigcommerce/log', Error_Log::DEBUG, __( 'Unable to create customer.', 'bigcommerce' ), [ - 'user_id' => $user_id, - 'userdata' => $userdata, - ] ); - do_action( 'bigcommerce/log', Error_Log::DEBUG, $exception->getMessage() , [ - 'trace' => $exception->getTraceAsString(), - ] ); - - } - - return 0; - } - + /** @var \BigCommerce\Api_Factory */ + private $factory; + + /** @var \BigCommerce\Taxonomies\Channel\Connections */ + private $connections; + + /** + * Register constructor. + * + * @param Api_Factory $api_factory The API factory for interacting with BigCommerce's API. + * @param Connections $connections The connections instance for managing channels. + */ + public function __construct( Api_Factory $api_factory, Connections $connections ) { + $this->factory = $api_factory; + $this->connections = $connections; + } + + /** + * Checks if the customer exists on BigCommerce, creates a new customer if not, + * and associates the customer with the primary channel. + * + * @param int $user_id The user ID. + * @param array $userdata The user data array. + * + * @return void + */ + public function maybe_create_new_customer( $user_id, $userdata ) { + if ( empty( $userdata['role'] ) || $userdata['role'] !== \BigCommerce\Accounts\Roles\Customer::NAME ) { + return; + } + + $customer_id = get_user_meta( $user_id, Customer::CUSTOMER_ID_META, true ); + + // Customer already connected + if ( ! empty( $customer_id ) ) { + return; + } + + $customer_id = $this->is_customer_mail_in_use( $userdata['user_email'] ); + + if ( $customer_id ) { + // Connect existing customer + $customer = new Customer( $user_id ); + $customer->set_customer_id( $customer_id ); + return; + } + + $this->register_new_customer( $user_id, $userdata ); + + $channel = $this->connections->primary(); + $channel_id = get_term_meta( $channel->term_id, Channel::CHANNEL_ID, true ); + update_user_meta( $user_id, Customer_Channel_Updater::CUSTOMER_CHANNEL_META, [ $channel_id] ); + update_user_meta( $user_id, Customer_Channel_Updater::CUSTOMER_ORIGIN_CHANNEL, $channel_id ); + } + + /** + * Checks if the customer email is already registered in BigCommerce. + * + * @param string $email The customer email to check. + * + * @return bool|int Returns the customer ID if found, or false if not found. + */ + protected function is_customer_mail_in_use( $email ) { + try { + $customer_api = $this->factory->customer(); + $matches = $customer_api->getCustomers( [ + 'email' => $email, + ] ); + + if ( ! empty( $matches ) ) { + $found_customer = reset( $matches ); + return $found_customer->id; + } + + return false; + } catch( \Exception $exception ) { + /** + * Log debug information when unable to check if a user exists. + * + * @param string $level The log level (DEBUG) + * @param string $message The log message + * @param array $context Additional context data + */ + do_action( 'bigcommerce/log', Error_Log::DEBUG, __( 'Could not check if user exists.', 'bigcommerce' ), [ + 'user_email' => $email, + ] ); + + /** + * Log debug information about the exception that occurred. + * + * @param string $level The log level (DEBUG) + * @param string $message The exception message + * @param array $context Additional context data including stack trace + */ + do_action( 'bigcommerce/log', Error_Log::DEBUG, $exception->getMessage() , [ + 'trace' => $exception->getTraceAsString(), + ] ); + // We are not able to check and due to this we should avoid customer creation + return true; + } + } + + /** + * Creates a new customer using the V3 API and associates them with the primary channel. + * + * @param int $user_id The user ID. + * @param array $userdata The user data array. + * + * @return int Returns the customer ID if successful, or 0 if creation failed. + */ + protected function register_new_customer( $user_id, $userdata ) { + try { + $customer_api = $this->factory->customers(); + $channel = $this->connections->primary(); + $channel_id = get_term_meta( $channel->term_id, Channel::CHANNEL_ID, true ); + + $new_customer_data = [ + 'first_name' => $userdata['first_name'] ?: $userdata['user_login'], + 'last_name' => $userdata['last_name'] ?: __( 'User', 'bigcommerce' ), + 'email' => $userdata['user_email'], + 'customer_group_id' => 0, + 'authentication' => [ + 'force_password_reset' => true, + 'new_password' => $userdata['user_pass'] + ], + 'origin_channel_id' => ( int ) $channel_id, + 'channels_ids' => [ ( int ) $channel_id ], + ]; + + /** + * Filters customer create arguments. + * + * @param array $new_customer_data Customer data. + */ + $new_customer_data = apply_filters( 'bigcommerce/customer/create/args', $new_customer_data ); + + $response = $customer_api->customersPost( [ $new_customer_data ] ); + + if ( $response && ! empty( $response->id ) ) { + $customer = new Customer( $user_id ); + $customer->set_customer_id( $response->id ); + + return $response->id; + } + } catch ( \Exception $exception ) { + /** + * Log debug information when unable to create a customer. + * + * @param string $level The log level (DEBUG) + * @param string $message The log message + * @param array $context Additional context data + */ + do_action( 'bigcommerce/log', Error_Log::DEBUG, __( 'Unable to create customer.', 'bigcommerce' ), [ + 'user_id' => $user_id, + 'userdata' => $userdata, + ] ); + + /** + * Log debug information about the exception that occurred. + * + * @param string $level The log level (DEBUG) + * @param string $message The exception message + * @param array $context Additional context data including stack trace + */ + do_action( 'bigcommerce/log', Error_Log::DEBUG, $exception->getMessage() , [ + 'trace' => $exception->getTraceAsString(), + ] ); + + } + + return 0; + } + } diff --git a/src/BigCommerce/Accounts/Roles/Customer.php b/src/BigCommerce/Accounts/Roles/Customer.php index aea167df..da3510e0 100644 --- a/src/BigCommerce/Accounts/Roles/Customer.php +++ b/src/BigCommerce/Accounts/Roles/Customer.php @@ -6,16 +6,45 @@ /** * Class Customer * - * A user role with no capabilities, not even `read` + * A user role with no capabilities, not even `read`. This class represents a "Customer" role + * in the BigCommerce accounts system. It implements the `Role` interface and provides + * methods to retrieve the role's ID and label. + * + * @package BigCommerce\Accounts\Roles */ class Customer implements Role { + + /** + * The name of the role. + * + * This constant defines the identifier for the `Customer` role. It is used to retrieve + * and reference the role throughout the application. + * + * @var string + */ const NAME = 'customer'; + /** + * Gets the ID of the customer role. + * + * This method returns the unique identifier for the `Customer` role, which is the + * value of the `NAME` constant (`'customer'`). + * + * @return string The ID of the customer role. + */ public function get_id() { return self::NAME; } + /** + * Gets the label of the customer role. + * + * This method returns the label for the `Customer` role, which is a translatable string. + * It is typically used to display the role's name in a UI. + * + * @return string The label of the customer role. + */ public function get_label() { return __( 'Customer', 'bigcommerce' ); } -} \ No newline at end of file +} diff --git a/src/BigCommerce/Accounts/Roles/Role.php b/src/BigCommerce/Accounts/Roles/Role.php index 77df7ad1..ad2cf092 100644 --- a/src/BigCommerce/Accounts/Roles/Role.php +++ b/src/BigCommerce/Accounts/Roles/Role.php @@ -2,8 +2,35 @@ namespace BigCommerce\Accounts\Roles; +/** + * Interface Role + * + * An interface for defining user roles in the BigCommerce accounts system. Any role class + * that implements this interface must provide methods to retrieve the role's unique identifier + * and its label. + * + * @package BigCommerce\Accounts\Roles + */ interface Role { + + /** + * Gets the ID of the role. + * + * This method must be implemented by any class that represents a user role. It should + * return a unique identifier for the role, typically a string constant or similar value. + * + * @return string The ID of the role. + */ public function get_id(); + /** + * Gets the label of the role. + * + * This method must be implemented by any class that represents a user role. It should + * return a translatable label or name for the role, typically used for display purposes + * in the user interface. + * + * @return string The label of the role. + */ public function get_label(); } diff --git a/src/BigCommerce/Accounts/Sub_Nav.php b/src/BigCommerce/Accounts/Sub_Nav.php index 5277fd37..fd307f6c 100644 --- a/src/BigCommerce/Accounts/Sub_Nav.php +++ b/src/BigCommerce/Accounts/Sub_Nav.php @@ -13,85 +13,92 @@ /** * Class Sub_Nav * - * Responsible for profile settings rendering and saving + * Responsible for rendering and saving profile settings, as well as managing the visibility of the sub-navigation menu + * above the content for account-related pages. */ class Sub_Nav { - /** + /** * Handle subnav visibility above the content * - * @param string $content - * - * @return string - * @filter the_content - */ - public function add_subnav_above_content( $content ) { - if ( ! is_singular() || ! is_user_logged_in() ) { - return $content; - } - $post_id = get_queried_object_id(); - if ( $post_id !== get_the_ID() ) { - return $content; // don't filter if we're not on the main post - } - /** - * Filter whether to display the account subnav before the post content - * on account pages. - * - * @param bool $display True to display the subnav, false to skip it - * @param int $post_id The ID of the current page - */ - if ( ! apply_filters( 'bigcommerce/account/do_subnav', true, $post_id ) ) { - return $content; - } - switch ( $post_id ) { - case get_option( Account_Page::NAME, 0 ): - case get_option( Orders_Page::NAME, 0 ): - case get_option( Address_Page::NAME, 0 ): - case get_option( Wishlist_Page::NAME, 0 ): - return $this->get_subnav() . $content; - default: - return $content; - } - } + * This filter is applied to the page content and will insert the sub-navigation + * if the user is logged in and the page is part of the account-related pages. + * + * @param string $content The content of the page. + * @return string Filtered content with subnav included if applicable. + * @filter the_content + */ + public function add_subnav_above_content( $content ) { + if ( ! is_singular() || ! is_user_logged_in() ) { + return $content; + } + $post_id = get_queried_object_id(); + if ( $post_id !== get_the_ID() ) { + return $content; // don't filter if we're not on the main post + } + /** + * Filter whether to display the account subnav before the post content + * on account pages. + * + * @param bool $display True to display the subnav, false to skip it. + * @param int $post_id The ID of the current page. + */ + if ( ! apply_filters( 'bigcommerce/account/do_subnav', true, $post_id ) ) { + return $content; + } + switch ( $post_id ) { + case get_option( Account_Page::NAME, 0 ): + case get_option( Orders_Page::NAME, 0 ): + case get_option( Address_Page::NAME, 0 ): + case get_option( Wishlist_Page::NAME, 0 ): + return $this->get_subnav() . $content; + default: + return $content; + } + } /** - * Get and render sub nav + * Get and render the sub-navigation menu * - * @return string + * Renders the sub-navigation links component based on available account pages. + * + * @return string The HTML of the sub-navigation menu. */ - private function get_subnav() { - $component = Sub_Nav_Links::factory( [ - Sub_Nav_Links::LINKS => $this->get_links(), - ] ); + private function get_subnav() { + $component = Sub_Nav_Links::factory( [ + Sub_Nav_Links::LINKS => $this->get_links(), + ] ); - return $component->render(); - } + return $component->render(); + } /** - * Get sub nav links + * Get sub-navigation links + * + * Retrieves the links for the account-related pages and formats them for the sub-navigation menu. * - * @return mixed|void + * @return array The list of links to be displayed in the sub-navigation. */ - private function get_links() { - $links = []; - foreach ( [ Account_Page::NAME, Orders_Page::NAME, Address_Page::NAME, Wishlist_Page::NAME ] as $option ) { - $post_id = get_option( $option, 0 ); - if ( $post_id ) { - $links[] = [ - 'url' => get_permalink( $post_id ), - 'label' => get_the_title( $post_id ), - 'current' => ( $post_id == get_queried_object_id() ), - ]; - } - } + private function get_links() { + $links = []; + foreach ( [ Account_Page::NAME, Orders_Page::NAME, Address_Page::NAME, Wishlist_Page::NAME ] as $option ) { + $post_id = get_option( $option, 0 ); + if ( $post_id ) { + $links[] = [ + 'url' => get_permalink( $post_id ), + 'label' => get_the_title( $post_id ), + 'current' => ( $post_id == get_queried_object_id() ), + ]; + } + } - /** - * Filter the links that show in the account subnav. - * - * @param array[] $links Each link will have the properties: - * `url` - The URL of the link - * `label` - The label of the link - * `current` - Whether the link is to the current page - */ - return apply_filters( 'bigcommerce/account/subnav/links', $links ); - } + /** + * Filter the links that show in the account subnav. + * + * @param array[] $links Each link will have the properties: + * `url` - The URL of the link. + * `label` - The label of the link. + * `current` - Whether the link is to the current page. + */ + return apply_filters( 'bigcommerce/account/subnav/links', $links ); + } } diff --git a/src/BigCommerce/Accounts/User_Profile_Settings.php b/src/BigCommerce/Accounts/User_Profile_Settings.php index a0872d7d..1df43979 100644 --- a/src/BigCommerce/Accounts/User_Profile_Settings.php +++ b/src/BigCommerce/Accounts/User_Profile_Settings.php @@ -6,66 +6,72 @@ /** * Class User_Profile_Settings * - * Responsible for profile settings rendering and saving + * Responsible for rendering and saving user profile settings, specifically for synchronizing passwords + * between WordPress and the BigCommerce API. */ class User_Profile_Settings { - const SYNC_PASSWORD = 'bigcommerce_sync_password'; - const NONCE_ACTION = 'bc_user_profile'; - const NONCE_NAME = 'bc_nonce'; + const SYNC_PASSWORD = 'bigcommerce_sync_password'; + const NONCE_ACTION = 'bc_user_profile'; + const NONCE_NAME = 'bc_nonce'; - /** + /** * Render profile settings - * @param \WP_User $user - * - * @return void - * @action show_user_profile - * @action edit_user_profile - */ - public function render_profile_settings( $user ) { - if ( ! current_user_can( 'edit_users' ) ) { - return; - } - $sync = get_user_meta( $user->ID, self::SYNC_PASSWORD, true ); - ?> -

- - - - - -
- - - - -

-
- ID, self::SYNC_PASSWORD, true ); + ?> +

+ + + + + +
+ + + + +

+
+ getCode(), $e->getMessage() ), $_POST, $redirect, [] ); } } - /** - * Cleanup add item request - * - * @param array $args - * @param array $submission - * - * @return array - */ + /** + * Cleans up and sanitizes the add item request. + * + * This method verifies the wishlist ID and product ID, checks the nonce for security, + * and ensures all required fields are provided and valid. + * + * @param array $args The arguments from the request. + * @param array $submission The submission data from the request. + * + * @return array The sanitized request data, including the wishlist and product IDs. + * + * @throws \InvalidArgumentException If the request is invalid or missing required data. + */ protected function sanitize_request( array $args, array $submission ) { $wishlist_id = reset( $args ); if ( empty( $wishlist_id ) || ! is_numeric( $wishlist_id ) ) { diff --git a/src/BigCommerce/Accounts/Wishlists/Actions/Create_Wishlist.php b/src/BigCommerce/Accounts/Wishlists/Actions/Create_Wishlist.php index d3a36b34..22f22824 100644 --- a/src/BigCommerce/Accounts/Wishlists/Actions/Create_Wishlist.php +++ b/src/BigCommerce/Accounts/Wishlists/Actions/Create_Wishlist.php @@ -9,13 +9,35 @@ use BigCommerce\Pages\Wishlist_Page; /** - * Class Create_Wishlist + * Handles the logic for creating a new wishlist for a customer. + * + * This class processes the request to create a wishlist, including validating and sanitizing + * the request data, creating a wishlist, and redirecting the user to the newly created wishlist's page. + * It also handles errors and triggers appropriate actions upon success or failure. * - * Handle wishlist creation logic + * @package BigCommerce\Accounts\Wishlists\Actions */ class Create_Wishlist extends Wishlist_Action { + /** + * The action identifier for creating a wishlist. + * + * This constant is used to identify the specific action for creating a wishlist. + * + * @var string + */ const ACTION = 'create'; + /** + * Handles the request to create a new wishlist. + * + * This method validates the incoming data, sanitizes it, and creates a new wishlist using + * the provided information. Upon successful creation, the user is redirected to the wishlist's page. + * If an error occurs, an error message is triggered. + * + * @param array $args The arguments from the request. + * + * @return void + */ public function handle_request( $args ) { $redirect = get_the_permalink( get_option( Wishlist_Page::NAME, 0 ) ); try { @@ -32,19 +54,40 @@ public function handle_request( $args ) { $wishlist = new Wishlist( $response->getData() ); $redirect = $wishlist->user_url(); - + /** + * Triggers success notification after creating a new wishlist. + * + * @param string $message The success message to display + * @param array $submission The submitted wishlist data + * @param string $redirect The URL to redirect to after creation + * @param array $data Additional data passed to the action + */ do_action( 'bigcommerce/form/success', __( 'Wish List created', 'bigcommerce' ), $submission, $redirect, [] ); } catch ( \Exception $e ) { + /** + * Triggers error notification if wishlist creation fails. + * + * @param \WP_Error $error The error details + * @param array $submission The submitted wishlist data + * @param string $redirect The URL to redirect to after error + * @param array $data Additional data passed to the action + */ do_action( 'bigcommerce/form/error', new \WP_Error( $e->getCode(), $e->getMessage() ), $_POST, $redirect, [] ); } } /** - * Validate and sanitize create request + * Validates and sanitizes the incoming request to create a wishlist. + * + * This method processes the submission data, ensuring required fields are present and sanitized. + * It throws exceptions for invalid or missing data and returns a sanitized array of the request data. * - * @param array $args - * @param array $submission - * @return array + * @param array $args The arguments from the request. + * @param array $submission The submission data from the request. + * + * @return array The sanitized request data, including the wishlist name, public status, and product items. + * + * @throws \InvalidArgumentException If the request is missing required fields or contains invalid data. */ protected function sanitize_request( array $args, array $submission ) { $submission = filter_var_array( $submission, [ diff --git a/src/BigCommerce/Accounts/Wishlists/Actions/Delete_Wishlist.php b/src/BigCommerce/Accounts/Wishlists/Actions/Delete_Wishlist.php index 67869527..4ab68025 100644 --- a/src/BigCommerce/Accounts/Wishlists/Actions/Delete_Wishlist.php +++ b/src/BigCommerce/Accounts/Wishlists/Actions/Delete_Wishlist.php @@ -6,17 +6,34 @@ use BigCommerce\Pages\Wishlist_Page; /** - * Class Delete_Wishlist + * Handles the logic for deleting a wishlist. * - * Handle delete wishlist logic + * This class processes the request to delete a specific wishlist for a customer. It validates + * the provided wishlist ID, deletes the wishlist, and redirects the user to the default wishlist page. + * It also triggers success or error actions based on the outcome of the operation. + * + * @package BigCommerce\Accounts\Wishlists\Actions */ class Delete_Wishlist extends Wishlist_Action { + /** + * The action identifier for deleting a wishlist. + * + * This constant is used to identify the specific action for deleting a wishlist. + * + * @var string + */ const ACTION = 'delete'; /** - * Delete requested wishlist + * Handles the request to delete a specific wishlist. + * + * This method validates the request, retrieves the wishlist using the provided ID, and + * deletes the wishlist from the system. Upon successful deletion, the user is redirected + * to the wishlist page with a success message. If an error occurs, an error message is triggered. * - * @param $args + * @param array $args The arguments from the request. + * + * @return void */ public function handle_request( $args ) { $redirect = get_the_permalink( get_option( Wishlist_Page::NAME, 0 ) ); @@ -25,19 +42,41 @@ public function handle_request( $args ) { $wishlist = $this->get_customer_wishlist( get_current_user_id(), $submission['id'] ); $this->wishlists->deleteWishlist( $wishlist->list_id() ); + /** + * Trigger success message after deleting wishlist. + * + * @param string $message Success message to display + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to + * @param array $data Additional data + */ do_action( 'bigcommerce/form/success', __( 'Wish List deleted', 'bigcommerce' ), $submission, $redirect, [] ); } catch ( \Exception $e ) { + /** + * Trigger error message if deleting wishlist fails. + * + * @param \WP_Error $error The error object + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to + * @param array $data Additional data + */ do_action( 'bigcommerce/form/error', new \WP_Error( $e->getCode(), $e->getMessage() ), $_POST, $redirect, [] ); } } /** - * Validate and sanitize request + * Validates and sanitizes the request to delete a wishlist. * - * @param array $args - * @param array $submission + * This method processes the submission data, ensuring the wishlist ID is valid and sanitizing + * the request for security. It throws exceptions for invalid or missing data and returns a sanitized + * array of the request data. * - * @return int[]|string[] + * @param array $args The arguments from the request. + * @param array $submission The submission data from the request. + * + * @return array The sanitized request data, including the wishlist ID. + * + * @throws \InvalidArgumentException If the request is missing required fields or contains invalid data. */ protected function sanitize_request( array $args, array $submission ) { $wishlist_id = reset( $args ); diff --git a/src/BigCommerce/Accounts/Wishlists/Actions/Edit_Wishlist.php b/src/BigCommerce/Accounts/Wishlists/Actions/Edit_Wishlist.php index c1a764d6..494a38bd 100644 --- a/src/BigCommerce/Accounts/Wishlists/Actions/Edit_Wishlist.php +++ b/src/BigCommerce/Accounts/Wishlists/Actions/Edit_Wishlist.php @@ -7,17 +7,34 @@ use BigCommerce\Pages\Wishlist_Page; /** - * Class Edit_Wishlist + * Handles the logic for editing a wishlist. * - * Handle wishlist edit + * This class processes the request to update the details of an existing wishlist for a customer. + * It validates the provided wishlist ID, updates the wishlist's name and public status, and redirects + * the user to the updated wishlist. It also triggers success or error actions based on the operation result. + * + * @package BigCommerce\Accounts\Wishlists\Actions */ class Edit_Wishlist extends Wishlist_Action { + /** + * The action identifier for editing a wishlist. + * + * This constant is used to identify the specific action for editing a wishlist. + * + * @var string + */ const ACTION = 'edit'; /** - * Update single wishlist + * Handles the request to edit a specific wishlist. + * + * This method validates the request, retrieves the wishlist using the provided ID, + * updates the wishlist with the new details, and redirects the user to the updated wishlist. + * It triggers success or failure actions based on the outcome of the operation. * - * @param $args + * @param array $args The arguments from the request. + * + * @return void */ public function handle_request( $args ) { $redirect = get_the_permalink( get_option( Wishlist_Page::NAME, 0 ) ); @@ -34,18 +51,41 @@ public function handle_request( $args ) { ] ); $this->wishlists->updateWishlist( $submission['id'], $request ); + /** + * Trigger success message after updating wishlist. + * + * @param string $message Success message to display + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to + * @param array $data Additional data + */ do_action( 'bigcommerce/form/success', __( 'Wish List updated', 'bigcommerce' ), $submission, $redirect, [] ); } catch ( \Exception $e ) { + /** + * Trigger error message if updating wishlist fails. + * + * @param \WP_Error $error The error object + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to + * @param array $data Additional data + */ do_action( 'bigcommerce/form/error', new \WP_Error( $e->getCode(), $e->getMessage() ), $_POST, $redirect, [] ); } } /** - * Validate and cleanup request - * @param array $args - * @param array $submission + * Validates and sanitizes the request to edit a wishlist. + * + * This method processes the submission data, ensuring the wishlist ID is valid, sanitizing + * the request for security, and validating the provided wishlist name. It throws exceptions + * for invalid or missing data and returns a sanitized array of the request data. * - * @return array + * @param array $args The arguments from the request. + * @param array $submission The submission data from the request. + * + * @return array The sanitized request data, including the wishlist ID, name, and public status. + * + * @throws \InvalidArgumentException If the request is missing required fields or contains invalid data. */ protected function sanitize_request( array $args, array $submission ) { $wishlist_id = reset( $args ); diff --git a/src/BigCommerce/Accounts/Wishlists/Actions/Remove_Item.php b/src/BigCommerce/Accounts/Wishlists/Actions/Remove_Item.php index 503c7d99..dbe63cc7 100644 --- a/src/BigCommerce/Accounts/Wishlists/Actions/Remove_Item.php +++ b/src/BigCommerce/Accounts/Wishlists/Actions/Remove_Item.php @@ -9,13 +9,35 @@ use BigCommerce\Post_Types\Product\Product; /** - * Class Remove_Item + * Handles the logic for removing an item from a customer's wishlist. * - * Handle item removing request for wishlist + * This class processes the request to remove a specific product from a wishlist. + * It ensures that the provided wishlist and product IDs are valid, removes the item from the wishlist, + * and returns a success or error message accordingly. + * + * @package BigCommerce\Accounts\Wishlists\Actions */ class Remove_Item extends Wishlist_Action { + /** + * The action identifier for removing an item from a wishlist. + * + * This constant is used to identify the specific action for removing an item from the wishlist. + * + * @var string + */ const ACTION = 'remove-item'; + /** + * Handles the request to remove a product from a specific wishlist. + * + * This method validates the request, retrieves the wishlist and product details, + * and removes the product from the wishlist if it exists. A success or failure message is returned + * based on the result of the operation. + * + * @param array $args The arguments from the request. + * + * @return void + */ public function handle_request( $args ) { $redirect = get_the_permalink( get_option( Wishlist_Page::NAME, 0 ) ); try { @@ -46,19 +68,41 @@ public function handle_request( $args ) { $message = __( 'Item removed from Wish List', 'bigcommerce' ); } + /** + * Trigger success message after removing item from wishlist. + * + * @param string $message Success message to display + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to + * @param array $data Additional data + */ do_action( 'bigcommerce/form/success', $message, $submission, $redirect, [] ); } catch ( \Exception $e ) { + /** + * Trigger error message if removing item from wishlist fails. + * + * @param \WP_Error $error The error object + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to + * @param array $data Additional data + */ do_action( 'bigcommerce/form/error', new \WP_Error( $e->getCode(), $e->getMessage() ), $_POST, $redirect, [] ); } } /** - * Sanitize and validate request + * Sanitizes and validates the request to remove an item from a wishlist. * - * @param array $args - * @param array $submission + * This method ensures the wishlist ID and product ID are valid, sanitizes the request data, + * and verifies the nonce to prevent unauthorized requests. It returns the validated data or throws + * an exception if the data is invalid. * - * @return array + * @param array $args The arguments from the request. + * @param array $submission The request data to be validated. + * + * @return array The sanitized and validated request data. + * + * @throws \InvalidArgumentException If the wishlist ID or product ID is invalid, or if the nonce is incorrect. */ protected function sanitize_request( array $args, array $submission ) { $wishlist_id = reset( $args ); diff --git a/src/BigCommerce/Accounts/Wishlists/Actions/Request_Router.php b/src/BigCommerce/Accounts/Wishlists/Actions/Request_Router.php index f0b44c85..ee6cf67d 100644 --- a/src/BigCommerce/Accounts/Wishlists/Actions/Request_Router.php +++ b/src/BigCommerce/Accounts/Wishlists/Actions/Request_Router.php @@ -5,20 +5,43 @@ /** * Class Request_Router * - * Routes requests to the wishlist action endpoint to the - * appropriate action handler + * Routes incoming requests to the appropriate action handler for wishlist-related operations. + * + * This class listens for requests on the wishlist action endpoint and directs them to the appropriate + * handler based on the action specified in the request. + * + * @package BigCommerce\Accounts\Wishlists\Actions */ class Request_Router { - const ACTION = 'wishlist'; - /** - * @param $args + * The action identifier for the wishlist endpoint. * - * @return void - * @action bigcommerce/action_endpoint/ . self::ACTION + * This constant is used to identify the wishlist action endpoint in the routing process. + * + * @var string */ + const ACTION = 'wishlist'; + + /** + * Handles the incoming request by routing it to the appropriate action handler. + * + * This method extracts the action from the request arguments, and then triggers a WordPress action + * to handle the request using the specific action handler associated with the action. + * + * @param array $args The arguments for the wishlist request, including the action and any parameters. + * + * @return void + * + * @action bigcommerce/action_endpoint/ . self::ACTION + */ public function handle_request( array $args ) { $action = array_shift( $args ); + /** + * Routes the request to the appropriate wishlist action handler. + * + * @param string $action The wishlist action to be executed + * @param array $args The arguments for the wishlist request + */ do_action( 'bigcommerce/wishlist_endpoint/' . $action, $args ); } } diff --git a/src/BigCommerce/Accounts/Wishlists/Actions/Wishlist_Action.php b/src/BigCommerce/Accounts/Wishlists/Actions/Wishlist_Action.php index 18db7a8f..78ed05dc 100644 --- a/src/BigCommerce/Accounts/Wishlists/Actions/Wishlist_Action.php +++ b/src/BigCommerce/Accounts/Wishlists/Actions/Wishlist_Action.php @@ -7,27 +7,70 @@ use BigCommerce\Accounts\Wishlists\Wishlist; use BigCommerce\Api\v3\Api\WishlistsApi; +/** + * Abstract class for handling wishlist-related actions. + * + * This class provides the base structure for actions that involve wishlists, such as creating, updating, or deleting + * wishlists. It defines common functionality for working with customer wishlists and handling requests, which must + * be extended by specific actions. + * + * @package BigCommerce\Accounts\Wishlists\Actions + */ abstract class Wishlist_Action { /** @var WishlistsApi */ protected $wishlists; + /** + * Wishlist_Action constructor. + * + * Initializes the action with the WishlistsApi instance, allowing the action to interact with the BigCommerce API + * for wishlist management. + * + * @param WishlistsApi $wishlists The WishlistsApi instance used for wishlist operations. + */ public function __construct( WishlistsApi $wishlists ) { $this->wishlists = $wishlists; } + /** + * Handle the incoming request. + * + * This is an abstract method that must be implemented by subclasses to handle the specific request for a wishlist action + * (e.g., create, update, delete). The method should process the request and return the appropriate response. + * + * @param mixed $args The arguments for the action request, typically including the wishlist ID and any necessary data. + * + * @return void + */ abstract public function handle_request( $args ); + /** + * Sanitize and validate the request data. + * + * This is an abstract method that must be implemented by subclasses to sanitize and validate the request submission + * before performing any operations on the wishlist. + * + * @param array $args The arguments for the action request. + * @param array $submission The submitted form data, typically from a POST request. + * + * @return array Sanitized data to be used in the action handler. + */ abstract protected function sanitize_request( array $args, array $submission ); - /** - * Get the wishlist for the customer - * - * @param int $user_id - * @param int $wishlist_id - * - * @return Wishlist - */ + /** + * Get the wishlist for the customer. + * + * Fetches the wishlist for a given customer based on their user ID and wishlist ID. If the wishlist is not found or + * does not belong to the customer, an exception is thrown. + * + * @param int $user_id The ID of the user (customer). + * @param int $wishlist_id The ID of the wishlist to retrieve. + * + * @return Wishlist The customer's wishlist. + * @throws \RuntimeException If the wishlist cannot be found or accessed. + * @throws \InvalidArgumentException If the wishlist does not belong to the customer. + */ protected function get_customer_wishlist( $user_id, $wishlist_id ) { try { $wishlist = $this->wishlists->getWishlist( $wishlist_id )->getData(); @@ -35,6 +78,7 @@ protected function get_customer_wishlist( $user_id, $wishlist_id ) { throw new \RuntimeException( __( 'Wish List not found', 'bigcommerce' ), 404 ); } + // Check if the wishlist belongs to the customer if ( (int) $wishlist->getCustomerId() !== $this->get_customer_id( $user_id ) ) { throw new \InvalidArgumentException( __( 'Wish List not found', 'bigcommerce' ), 404 ); } @@ -42,13 +86,15 @@ protected function get_customer_wishlist( $user_id, $wishlist_id ) { return new Wishlist( $wishlist ); } - /** - * Get the Customer ID for the user - * - * @param int $user_id - * - * @return int - */ + /** + * Get the Customer ID for the user. + * + * Retrieves the customer ID associated with the given user ID. + * + * @param int $user_id The ID of the user (customer). + * + * @return int The customer ID associated with the user. + */ protected function get_customer_id( $user_id ) { $customer = new Customer( $user_id ); diff --git a/src/BigCommerce/Accounts/Wishlists/Add_Item_View.php b/src/BigCommerce/Accounts/Wishlists/Add_Item_View.php index 16fdb3f1..fa2ecbfa 100644 --- a/src/BigCommerce/Accounts/Wishlists/Add_Item_View.php +++ b/src/BigCommerce/Accounts/Wishlists/Add_Item_View.php @@ -17,25 +17,43 @@ /** * Class Add_Item_View * - * Adds the "Add to Wish List" template after the purchase form - * on the product single view + * Adds the "Add to Wish List" template after the purchase form on the product single view. + * This class manages the display of the "Add to Wishlist" button and the wishlist functionality + * on product detail pages. It checks whether the feature is enabled, if the user is logged in, + * and then allows the user to add a product to an existing wishlist. + * + * @package BigCommerce\Accounts\Wishlists */ class Add_Item_View { /** @var WishlistsApi */ private $wishlists; + /** + * Add_Item_View constructor. + * + * Initializes the Add_Item_View class with the provided WishlistsApi instance, which is used + * to interact with the BigCommerce API to manage wishlists. + * + * @param WishlistsApi $wishlists The WishlistsApi instance to interact with BigCommerce wishlists. + */ public function __construct( WishlistsApi $wishlists ) { $this->wishlists = $wishlists; } - /** - * @param array $data - * @param string $template - * @param array $options - * - * @return array - * @filter bigcommerce/template=components/products/product-single.php/data - */ + /** + * Filters the data of the product single template to add the "Add to Wish List" button. + * + * This method checks if the "Add to Wishlist" feature is enabled, if the user is logged in, + * and if the customer has a wishlist. If all conditions are met, it adds the "Add to Wish List" + * button to the product single template. + * + * @param array $data The template data for the product single page. + * @param string $template The name of the template file. + * @param array $options Additional options for rendering the template. + * + * @return array The modified template data with the "Add to Wish List" button included. + * @filter bigcommerce/template=components/products/product-single.php/data + */ public function filter_product_single_template( $data, $template, $options ) { if ( ! Channel::is_msf_channel_prop_on( Storefront_Processor::SHOW_ADD_TO_WISHLIST ) || ! get_option( Wishlist_Settings::ENABLED ) || ! is_user_logged_in() ) { return $data; @@ -56,11 +74,16 @@ public function filter_product_single_template( $data, $template, $options ) { return $data; } - /** - * @param int $customer_id - * - * @return Account_Wishlist[] - */ + /** + * Fetches the customer's wishlists from the API. + * + * This method retrieves a list of the customer's existing wishlists and returns them as + * an array of Account_Wishlist objects. + * + * @param int $customer_id The ID of the customer to fetch wishlists for. + * + * @return Account_Wishlist[] An array of Account_Wishlist objects representing the customer's wishlists. + */ private function get_wishlists( $customer_id ) { try { return array_map( function ( Api_Wishlist $wishlist ) { diff --git a/src/BigCommerce/Accounts/Wishlists/Public_Wishlist.php b/src/BigCommerce/Accounts/Wishlists/Public_Wishlist.php index 495bd843..75de4710 100644 --- a/src/BigCommerce/Accounts/Wishlists/Public_Wishlist.php +++ b/src/BigCommerce/Accounts/Wishlists/Public_Wishlist.php @@ -7,21 +7,40 @@ use BigCommerce\Templates\No_Results; use BigCommerce\Templates\Product_Archive; +/** + * This class handles the public-facing wishlist view, including customizing the query + * to show only products in the wishlist, setting the page title, customizing the + * `wp_title()` function, and managing the "No Results" message on the wishlist page. + * + * @package BigCommerce\Accounts\Wishlists + */ class Public_Wishlist extends Wishlist_Public_View { /** @var Wishlist */ private $wishlist; + /** + * Public_Wishlist constructor. + * + * Initializes the Public_Wishlist class with the provided Wishlist object, which represents + * the user's wishlist and is used throughout the public wishlist view to display wishlist items + * and handle related operations. + * + * @param Wishlist $wishlist The Wishlist object associated with the user's wishlist. + */ public function __construct( Wishlist $wishlist ) { $this->wishlist = $wishlist; } - /** - * Set the query to only show products in the wishlist - * - * @param \WP_Query $query - * - * @return void - */ + /** + * Set the query to only show products in the wishlist. + * + * This method customizes the main WordPress query to only return products that are part of the + * user's wishlist. If the wishlist is empty, it modifies the query to exclude any results. + * + * @param \WP_Query $query The WordPress query object. + * + * @return void + */ public function filter_main_query( \WP_Query $query ) { if ( ! $query->is_main_query() ) { return; @@ -37,29 +56,35 @@ public function filter_main_query( \WP_Query $query ) { $query->set( 'bigcommerce_id__in', $product_ids ); } - /** - * Set the page title to the name of the wishlist - * - * @param array $template_data - * - * @return array - * @filter bigcommerce/template=components/catalog/product-archive.php/data - */ + /** + * Set the page title to the name of the wishlist. + * + * This method modifies the page title template data to include the name of the wishlist + * in the title of the product archive page. + * + * @param array $template_data The template data for the product archive page. + * + * @return array The modified template data with the updated page title. + * @filter bigcommerce/template=components/catalog/product-archive.php/data + */ public function set_page_title( $template_data ) { $name = $this->wishlist->name(); $template_data[ Product_Archive::TITLE ] = sprintf( __( 'Wish List: %s', 'bigcommerce' ), $name ); return $template_data; } - /** - * Filter the wp_title() for the Wish List page - * - * @param string $title - * @param string $post_type - * - * @return string - * @filter post_type_archive_title - */ + /** + * Filter the wp_title() for the Wish List page. + * + * This method filters the title of the wish list page to include the name of the wishlist. + * It modifies the default `wp_title()` function output for product archive pages. + * + * @param string $title The current title. + * @param string $post_type The post type for the page. + * + * @return string The modified title. + * @filter post_type_archive_title + */ public function set_wp_title( $title, $post_type ) { if ( $post_type === Product::NAME ) { $name = $this->wishlist->name(); @@ -68,14 +93,18 @@ public function set_wp_title( $title, $post_type ) { return $title; } - /** - * Set the No Results message to be wishlist-relevant - * - * @param array $template_data - * - * @return array - * @filter bigcommerce/template=components/catalog/no-results.php/data - */ + /** + * Set the No Results message to be wishlist-relevant. + * + * This method customizes the "No Results" message when the wishlist is empty. It updates the + * template data to show a relevant message and a "Shop Around" button instead of the default + * message when no products are found in the wishlist. + * + * @param array $template_data The template data for the "No Results" page. + * + * @return array The modified template data with the updated message and button label. + * @filter bigcommerce/template=components/catalog/no-results.php/data + */ public function set_no_results_message( $template_data ) { $template_data[ No_Results::NO_RESULTS_MESSAGE ] = __( 'This Wish List does not have any products.', 'bigcommerce' ); $template_data[ No_Results::RESET_BUTTON_LABEL ] = __( 'Shop Around', 'bigcommerce' ); diff --git a/src/BigCommerce/Accounts/Wishlists/Wishlist.php b/src/BigCommerce/Accounts/Wishlists/Wishlist.php index 51e3c72d..a69614aa 100644 --- a/src/BigCommerce/Accounts/Wishlists/Wishlist.php +++ b/src/BigCommerce/Accounts/Wishlists/Wishlist.php @@ -17,59 +17,80 @@ /** * Class Wishlist * - * A wrapper around API wishlists + * A wrapper around API wishlists to manage wishlist data, generate URLs for wishlist actions, + * and handle items in the wishlist. */ class Wishlist { - /** @var \BigCommerce\Api\v3\Model\Wishlist */ + /** @var \BigCommerce\Api\v3\Model\Wishlist The underlying API wishlist object */ private $wishlist; + /** + * Wishlist constructor. + * + * @param \BigCommerce\Api\v3\Model\Wishlist $wishlist The wishlist API model + */ public function __construct( \BigCommerce\Api\v3\Model\Wishlist $wishlist ) { $this->wishlist = $wishlist; } + /** + * Get the ID of the wishlist. + * + * @return int The ID of the wishlist. + */ public function list_id() { return $this->wishlist->getId(); } + /** + * Get the customer ID associated with the wishlist. + * + * @return int The customer ID. + */ public function customer_id() { return $this->wishlist->getCustomerId(); } + /** + * Get the token associated with the wishlist. + * + * @return string The wishlist token. + */ public function token() { return $this->wishlist->getToken(); } /** - * Get the name of the wishlist + * Get the name of the wishlist. * - * @return string + * @return string The name of the wishlist. */ public function name() { return $this->wishlist->getName(); } /** - * Get the number of items in the wishlist + * Get the number of items in the wishlist. * - * @return int + * @return int The number of items. */ public function count() { return count( $this->wishlist->getItems() ); } /** - * Get the underlying API wishlist + * Get the underlying API wishlist object. * - * @return \BigCommerce\Api\v3\Model\Wishlist + * @return \BigCommerce\Api\v3\Model\Wishlist The wishlist API model. */ public function wishlist() { return $this->wishlist; } /** - * Get the items in the wishlist + * Get the product IDs of items in the wishlist. * - * @return int[] + * @return int[] Array of product IDs. */ public function items() { $product_ids = array_map( function ( WishlistItem $item ) { @@ -79,8 +100,8 @@ public function items() { /** * Filter the product IDs in the wishlist * - * @param int[] $product_ids - * @param Wishlist $wishlist + * @param int[] $product_ids The list of product IDs. + * @param Wishlist $wishlist The wishlist object. */ $product_ids = apply_filters( 'bigcommerce/wishlist/items', $product_ids, $this ); @@ -88,27 +109,27 @@ public function items() { } /** - * Get the raw item objects from the API response + * Get the raw item objects from the API response. * - * @return WishlistItem[] + * @return WishlistItem[] Array of raw wishlist item objects. */ public function raw_items() { return $this->wishlist->getItems(); } /** - * Checks if the list is publicly shared + * Check if the wishlist is publicly shared. * - * @return bool + * @return bool True if the wishlist is public, false otherwise. */ public function is_public() { return (bool) $this->wishlist->getIsPublic(); } /** - * Get the public URL to view the wishlist + * Get the public URL to view the wishlist. * - * @return string + * @return string The URL to view the wishlist. */ public function public_url() { if ( ! $this->is_public() ) { @@ -123,16 +144,16 @@ public function public_url() { /** * Filter the URL for a public wishlist * - * @param string $url The wishlist URL - * @param Wishlist $wishlist The wishlist object + * @param string $url The wishlist URL. + * @param Wishlist $wishlist The wishlist object. */ return apply_filters( 'bigcommerce/wishlist/public-url', $url, $this ); } /** - * Get the user's private URL to view the wishlist + * Get the user's private URL to view the wishlist. * - * @return string + * @return string The user's private wishlist URL. */ public function user_url() { $page_id = get_option( Wishlist_Page::NAME, 0 ); @@ -144,85 +165,104 @@ public function user_url() { ], get_permalink( $page_id ) ); /** - * Filter the URL for a user to manage a wishlist + * Filter the URL for a user to manage a wishlist. * - * @param string $url The wishlist URL - * @param Wishlist $wishlist The wishlist object + * @param string $url The wishlist URL. + * @param Wishlist $wishlist The wishlist object. */ return apply_filters( 'bigcommerce/wishlist/user-url', $url, $this ); } /** - * Get the URL to handle update requests for this wishlist + * Get the URL to handle update requests for this wishlist. * - * @return string + * @return string The URL for wishlist updates. */ public function edit_url() { $url = home_url( sprintf( 'bigcommerce/%s/%s/%d', Request_Router::ACTION, Edit_Wishlist::ACTION, $this->list_id() ) ); /** - * Filter the URL for posting an update to a wishlist's settings + * Filter the URL for posting an update to a wishlist's settings. * - * @param string $url The form handler URL - * @param Wishlist $wishlist The wishlist object + * @param string $url The form handler URL. + * @param Wishlist $wishlist The wishlist object. */ return apply_filters( 'bigcommerce/wishlist/edit-url', $url, $this ); } /** - * Get the URL to delete the wishlist + * Get the URL to delete the wishlist. * - * @return string + * @return string The URL to delete the wishlist. */ public function delete_url() { $url = home_url( sprintf( 'bigcommerce/%s/%s/%d', Request_Router::ACTION, Delete_Wishlist::ACTION, $this->list_id() ) ); /** - * Filter the URL for deleting a wishlist + * Filter the URL for deleting a wishlist. * - * @param string $url The form handler URL - * @param Wishlist $wishlist The wishlist object + * @param string $url The form handler URL. + * @param Wishlist $wishlist The wishlist object. */ return apply_filters( 'bigcommerce/wishlist/delete-url', $url, $this ); } + /** + * Get the URL to add an item to the wishlist. + * + * @param int $product_id The ID of the product to add. + * + * @return string The URL for adding an item to the wishlist. + */ public function add_item_url( $product_id ) { $url = home_url( sprintf( 'bigcommerce/%s/%s/%d', Request_Router::ACTION, Add_Item::ACTION, $this->list_id() ) ); $url = add_query_arg( [ 'product_id' => $product_id ], $url ); $url = wp_nonce_url( $url, sprintf( '%s/%d/%d', Add_Item::ACTION, $this->list_id(), $product_id ) ); /** - * Filter the URL for adding an item to a wishlist + * Filter the URL for adding an item to a wishlist. * - * @param string $url The form handler URL - * @param Wishlist $wishlist The wishlist object - * @param int $product_id The ID of the product to remove + * @param string $url The form handler URL. + * @param Wishlist $wishlist The wishlist object. + * @param int $product_id The ID of the product to add. */ return apply_filters( 'bigcommerce/wishlist/add-item-url', $url, $this, $product_id ); } + /** + * Get the URL to remove an item from the wishlist. + * + * @param int $product_id The ID of the product to remove. + * + * @return string The URL for removing an item from the wishlist. + */ public function delete_item_url( $product_id ) { $url = home_url( sprintf( 'bigcommerce/%s/%s/%d', Request_Router::ACTION, Remove_Item::ACTION, $this->list_id() ) ); $url = add_query_arg( [ 'product_id' => $product_id ], $url ); $url = wp_nonce_url( $url, sprintf( '%s/%d/%d', Remove_Item::ACTION, $this->list_id(), $product_id ) ); /** - * Filter the URL for removing an item from a wishlist + * Filter the URL for removing an item from a wishlist. * - * @param string $url The form handler URL - * @param Wishlist $wishlist The wishlist object - * @param int $product_id The ID of the product to remove + * @param string $url The form handler URL. + * @param Wishlist $wishlist The wishlist object. + * @param int $product_id The ID of the product to remove. */ return apply_filters( 'bigcommerce/wishlist/remove-item-url', $url, $this, $product_id ); } + /** + * Get the URL to create a wishlist. + * + * @return string The URL to create a new wishlist. + */ public static function create_url() { $url = home_url( sprintf( 'bigcommerce/%s/%s', Request_Router::ACTION, Create_Wishlist::ACTION ) ); /** - * Filter the URL for creating a wishlist + * Filter the URL for creating a wishlist. * - * @param string $url The form handler URL + * @param string $url The form handler URL. */ return apply_filters( 'bigcommerce/wishlist/create-url', $url ); } diff --git a/src/BigCommerce/Accounts/Wishlists/Wishlist_Public_View.php b/src/BigCommerce/Accounts/Wishlists/Wishlist_Public_View.php index f6e416e2..c6d2e1ce 100644 --- a/src/BigCommerce/Accounts/Wishlists/Wishlist_Public_View.php +++ b/src/BigCommerce/Accounts/Wishlists/Wishlist_Public_View.php @@ -5,22 +5,55 @@ use BigCommerce\Templates\Product_Archive; +/** + * Abstract class for handling wishlist public view actions, including filtering main queries, + * setting the page title, and modifying results when no items are found. + */ abstract class Wishlist_Public_View { + /** + * Filter the main query to display wishlist-specific products. + * + * @param \WP_Query $query The WordPress query object. + * + * @return void + */ abstract public function filter_main_query( \WP_Query $query ); + /** + * Set the page title for the wishlist view. + * + * @param array $template_data The template data for the current page. + * + * @return array The modified template data. + */ abstract public function set_page_title( $template_data ); + /** + * Set the WordPress title for the wishlist page. + * + * @param string $title The current title of the page. + * @param string $post_type The type of post being queried. + * + * @return string The modified page title. + */ abstract public function set_wp_title( $title, $post_type ); + /** + * Set the no results message for the wishlist page. + * + * @param array $template_data The template data for the current page. + * + * @return array The modified template data with updated no results message. + */ abstract public function set_no_results_message( $template_data ); /** - * Remove the refinery component from the product archive template + * Remove the refinery component from the product archive template. * - * @param array $template_data + * @param array $template_data The template data for the current page. * - * @return array + * @return array The modified template data with the refinery component removed. * @filter bigcommerce/template=components/catalog/product-archive.php/data */ public function remove_refinery( $template_data ) { diff --git a/src/BigCommerce/Accounts/Wishlists/Wishlist_Request_Parser.php b/src/BigCommerce/Accounts/Wishlists/Wishlist_Request_Parser.php index 6e0ed43e..254c12ff 100644 --- a/src/BigCommerce/Accounts/Wishlists/Wishlist_Request_Parser.php +++ b/src/BigCommerce/Accounts/Wishlists/Wishlist_Request_Parser.php @@ -10,23 +10,48 @@ /** * Class Wishlist_Request_Parser * - * Filters the product archive to show items in a wishlist + * This class parses and processes wishlist-related requests, such as filtering + * the product archive to display wishlist items. It integrates with the BigCommerce + * Wishlists API to fetch and handle wishlist data and applies necessary filters + * and actions to the WordPress environment. + * + * @package BigCommerce\Accounts\Wishlists */ class Wishlist_Request_Parser { + + /** + * Query parameter for the wishlist identifier. + * + * @var string + */ const LIST_PARAM = 'list'; + + /** + * Query parameter for the wishlist token. + * + * @var string + */ const TOKEN_PARAM = 'token'; /** @var WishlistsApi */ private $wishlists; + /** + * Constructor for Wishlist_Request_Parser. + * + * @param WishlistsApi $wishlists The Wishlists API instance for fetching wishlist data. + */ public function __construct( WishlistsApi $wishlists ) { $this->wishlists = $wishlists; } /** - * Handle wishlist setup request + * Setup the wishlist request. + * + * Determines whether the current request is a wishlist request. If so, it fetches the + * wishlist data and applies appropriate actions and filters to render the wishlist. * - * @param \WP $wp + * @param \WP $wp The WordPress request object. */ public function setup_wishlist_request( \WP $wp ) { if ( ! $this->is_wishlist_request( $wp ) ) { diff --git a/src/BigCommerce/Amp/Amp_Admin_Notices.php b/src/BigCommerce/Amp/Amp_Admin_Notices.php index 954f48e5..df1b4bac 100644 --- a/src/BigCommerce/Amp/Amp_Admin_Notices.php +++ b/src/BigCommerce/Amp/Amp_Admin_Notices.php @@ -1,158 +1,168 @@ screen_id = $screen_id; - $this->amp_is_enabled = $amp_is_enabled; - $this->is_ssl = is_bool( $is_ssl ) ? $is_ssl : is_ssl(); - } - - /** - * Provides the instance's notices. - * - * @return array - */ - public function get_notices() { - return $this->notices; - } - - /** - * Adds a notice to the instance's notices. - * - * @param string $notice Notice text. - */ - public function add_notice( $notice ) { - if ( ! in_array( $notice, $this->notices, true ) ) { - $this->notices[] = $notice; - } - } - - /** - * Adds the SSL notice if applicable. - */ - private function ssl_notice() { - if ( $this->is_ssl ) { - return; - } - - $notice = sprintf( - // Translators: Placeholder is an external URL about HTTPS. - __( - 'This site is using AMP, the official AMP plugin for WordPress. HTTPS is required for some features of BigCommerce for WordPress to work correctly with AMP. Read about updating to HTTPS here.', - 'bigcommerce' - ), - /** - * Filters the URL with information about updating the current site to HTTPS. - * - * @param string URL. - */ - apply_filters( - 'bigcommerce/amp/https_help_url', - esc_url( 'https://make.wordpress.org/support/user-manual/web-publishing/https-for-wordpress/' ) - ) - ); - - /** - * Filters the AMP SSL notice text. - * - * @param string - */ - $notice = apply_filters( 'bigcommerce/amp/amp_ssl_notice', $notice ); - - $this->add_notice( $notice ); - } - - /** - * Displays an admin notice if AMP is active an SSL is not enabled. - */ - public function render_amp_admin_notices() { - if ( ! $this->amp_is_enabled ) { - return; - } - - $screen = get_current_screen(); - if ( ! is_a( $screen, WP_Screen::class ) || $this->screen_id !== $screen->id ) { - return; - } - - $this->ssl_notice(); - - /** - * Filters AMP admin notices. - * - * @param array Array of string messages. - */ - if ( empty( apply_filters( 'bigcommerce/amp/admin_notices', $this->notices ) ) ) { - return; - } - - $list = sprintf( - '
    %s
', - implode( - '', - array_map( - function ( $message ) { - return sprintf( '
  • %s
  • ', $message ); - }, - $this->notices - ) - ) - ); - - echo wp_kses_post( - sprintf( - '

    %s

    %s
    ', - __( 'AMP and BigCommerce', 'bigcommerce' ), - $list - ) - ); - } + /** + * ID of the admin screen on which to display the notice. + * + * @var string + */ + private $screen_id; + + /** + * Whether the AMP for WordPress plugin is active. + * + * @var bool + */ + private $amp_is_enabled; + + /** + * Whether the site uses SSL. + * + * @var bool + */ + private $is_ssl; + + /** + * List of notice items. + * + * @var array + */ + private $notices = []; + + /** + * Constructor + * + * Initializes the Amp_Admin_Notices object with necessary information + * including the screen ID, AMP plugin status, and SSL status. + * + * @param string $screen_id ID of the admin screen where the notice will appear. + * @param bool $amp_is_enabled Whether the AMP plugin is active. Default is false. + * @param bool $is_ssl Whether the site uses SSL. Default is null, which checks the current SSL status. + */ + public function __construct( $screen_id, $amp_is_enabled = false, $is_ssl = null ) { + $this->screen_id = $screen_id; + $this->amp_is_enabled = $amp_is_enabled; + $this->is_ssl = is_bool( $is_ssl ) ? $is_ssl : is_ssl(); + } + + /** + * Provides the instance's notices. + * + * @return array List of notices to be displayed. + */ + public function get_notices() { + return $this->notices; + } + + /** + * Adds a notice to the instance's notices list. + * + * @param string $notice The notice message to be added. + */ + public function add_notice( $notice ) { + if ( ! in_array( $notice, $this->notices, true ) ) { + $this->notices[] = $notice; + } + } + + /** + * Adds the SSL notice if applicable. + * + * This notice is shown if the AMP plugin is active but the site does not use SSL, + * informing the user of the importance of using HTTPS for BigCommerce features. + */ + private function ssl_notice() { + if ( $this->is_ssl ) { + return; + } + + $notice = sprintf( + // Translators: Placeholder is an external URL about HTTPS. + __( + 'This site is using AMP, the official AMP plugin for WordPress. HTTPS is required for some features of BigCommerce for WordPress to work correctly with AMP. Read about updating to HTTPS here.', + 'bigcommerce' + ), + /** + * Filters the URL with information about updating the current site to HTTPS. + * + * @param string URL. + */ + apply_filters( + 'bigcommerce/amp/https_help_url', + esc_url( 'https://make.wordpress.org/support/user-manual/web-publishing/https-for-wordpress/' ) + ) + ); + + /** + * Filters the AMP SSL notice text. + * + * @param string + */ + $notice = apply_filters( 'bigcommerce/amp/amp_ssl_notice', $notice ); + + $this->add_notice( $notice ); + } + + /** + * Displays an admin notice if AMP is active and SSL is not enabled. + * + * This method renders the AMP-related admin notices in the WordPress dashboard. + * It checks whether AMP is active, whether the current screen matches the provided + * screen ID, and whether the SSL notice should be displayed. + */ + public function render_amp_admin_notices() { + if ( ! $this->amp_is_enabled ) { + return; + } + + $screen = get_current_screen(); + if ( ! is_a( $screen, WP_Screen::class ) || $this->screen_id !== $screen->id ) { + return; + } + + $this->ssl_notice(); + + /** + * Filters AMP admin notices. + * + * @param array Array of string messages. + */ + if ( empty( apply_filters( 'bigcommerce/amp/admin_notices', $this->notices ) ) ) { + return; + } + + $list = sprintf( + '
      %s
    ', + implode( + '', + array_map( + function ( $message ) { + return sprintf( '
  • %s
  • ', $message ); + }, + $this->notices + ) + ) + ); + + echo wp_kses_post( + sprintf( + '

    %s

    %s
    ', + __( 'AMP and BigCommerce', 'bigcommerce' ), + $list + ) + ); + } } diff --git a/src/BigCommerce/Amp/Amp_Assets.php b/src/BigCommerce/Amp/Amp_Assets.php index 781c4cc3..148a087d 100644 --- a/src/BigCommerce/Amp/Amp_Assets.php +++ b/src/BigCommerce/Amp/Amp_Assets.php @@ -7,104 +7,117 @@ /** * Class Amp_Assets * - * Load styles and scripts we'll need for our AMP functionality and layouts. + * Handles loading styles and scripts needed for AMP functionality and layouts. * * @package BigCommerce\Amp */ class Amp_Assets { - /** - * @var string Path to the plugin assets directory - */ - private $directory; - - /** - * URL of asset directory - * - * @var string - */ - private $asset_directory_url; - - /** - * @var string Path to the plugin assets directory - */ - private $customizer_template_file; - - /** - * Assets constructor. - */ - public function __construct( $asset_directory, $asset_directory_url, $customizer_template_file ) { - $this->directory = trailingslashit( $asset_directory ); - $this->asset_directory_url = trailingslashit( $asset_directory_url ); - $this->customizer_template_file = $customizer_template_file; - } - - /** - * Add custom CSS. - */ - public function styles() { - $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; - - $post = get_post(); - $css_file = $debug ? 'master-amp.css' : 'master-amp.min.css'; - $cart_page_id = intval( get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ) ); - if ( $post->ID === $cart_page_id ) { - $css_file = $debug ? 'cart-amp.css' : 'cart-amp.min.css'; - } - $css_src = $this->directory . 'css/' . $css_file; - $css_contents = file_get_contents( $css_src ); - - // Use absolute URLs for web fonts. - $css_contents = str_replace( '../fonts', esc_url( $this->asset_directory_url . 'fonts' ), $css_contents ); - - // Remove all !important rules. - $css_contents = str_replace( '!important', '', $css_contents ); - - echo $css_contents; // WPCS: XSS okay. CSS loaded from our own CSS file. - } - - /** - * Get AMP script handles. - * - * This is only relevant in the Classic Mode, as component scripts are automatically in Native/Paired modes. - * This is used in an 'amp_post_template_data' filter. - * - * @see amp_register_default_scripts() - * @return string[] Script handles. - */ - public function scripts() { - $handles = array( - 'amp-carousel', - 'amp-form', - 'amp-bind', - 'amp-sidebar', - 'amp-list', - 'amp-mustache', - ); - - if ( is_archive() ) { - $handles[] = 'amp-lightbox'; - } - - return $handles; - } - - /** - * Filter the main stylesheet when we are in AMP paired mode. - * - * @param string $stylesheet Stylesheet file name. - * - * @return mixed - */ - public function filter_stylesheet( $stylesheet ) { - $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; - $stylesheet = $debug ? 'master-amp.css' : 'master-amp.min.css'; - $post = get_post(); - $cart_page_id = intval( get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ) ); - if ( $post->ID === $cart_page_id ) { - $stylesheet = $debug ? 'cart-amp.css' : 'cart-amp.min.css'; - } - - return $stylesheet; - } + /** + * Path to the plugin assets directory. + * + * @var string + */ + private $directory; + + /** + * URL of the plugin asset directory. + * + * @var string + */ + private $asset_directory_url; + + /** + * Path to the customizer template file. + * + * @var string + */ + private $customizer_template_file; + + /** + * Constructor for the Amp_Assets class. + * + * @param string $asset_directory Path to the plugin assets directory. + * @param string $asset_directory_url URL to the plugin asset directory. + * @param string $customizer_template_file Path to the customizer template file. + */ + public function __construct( $asset_directory, $asset_directory_url, $customizer_template_file ) { + $this->directory = trailingslashit( $asset_directory ); + $this->asset_directory_url = trailingslashit( $asset_directory_url ); + $this->customizer_template_file = $customizer_template_file; + } + + /** + * Outputs custom AMP CSS styles directly in the document. + * + * Loads the appropriate stylesheet based on the current page (e.g., cart or general) + * and performs necessary adjustments like replacing relative paths with absolute URLs. + */ + public function styles() { + $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; + + $post = get_post(); + $css_file = $debug ? 'master-amp.css' : 'master-amp.min.css'; + $cart_page_id = intval( get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ) ); + if ( $post->ID === $cart_page_id ) { + $css_file = $debug ? 'cart-amp.css' : 'cart-amp.min.css'; + } + $css_src = $this->directory . 'css/' . $css_file; + $css_contents = file_get_contents( $css_src ); + + // Use absolute URLs for web fonts. + $css_contents = str_replace( '../fonts', esc_url( $this->asset_directory_url . 'fonts' ), $css_contents ); + + // Remove all !important rules. + $css_contents = str_replace( '!important', '', $css_contents ); + + echo $css_contents; // WPCS: XSS okay. CSS loaded from our own CSS file. + } + + /** + * Retrieves AMP script handles. + * + * Relevant only in Classic Mode; component scripts are automatically included + * in Native/Paired modes. Used in the `amp_post_template_data` filter. + * + * @see amp_register_default_scripts() + * @return string[] List of script handles. + */ + public function scripts() { + $handles = array( + 'amp-carousel', + 'amp-form', + 'amp-bind', + 'amp-sidebar', + 'amp-list', + 'amp-mustache', + ); + + if ( is_archive() ) { + $handles[] = 'amp-lightbox'; + } + + return $handles; + } + + /** + * Filters the main stylesheet when in AMP paired mode. + * + * Determines the appropriate stylesheet (debug or minified version) based on the + * page type (e.g., cart page or general page). + * + * @param string $stylesheet Stylesheet file name. + * @return string Modified stylesheet file name. + */ + public function filter_stylesheet( $stylesheet ) { + $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; + $stylesheet = $debug ? 'master-amp.css' : 'master-amp.min.css'; + $post = get_post(); + $cart_page_id = intval( get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ) ); + if ( $post->ID === $cart_page_id ) { + $stylesheet = $debug ? 'cart-amp.css' : 'cart-amp.min.css'; + } + + return $stylesheet; + } } diff --git a/src/BigCommerce/Amp/Amp_Cart.php b/src/BigCommerce/Amp/Amp_Cart.php index d9bddfbd..87f86f6b 100644 --- a/src/BigCommerce/Amp/Amp_Cart.php +++ b/src/BigCommerce/Amp/Amp_Cart.php @@ -7,116 +7,145 @@ use BigCommerce\Cart\Cart; /** - * Class AMP cart. + * Class Amp_Cart + * + * Handles AMP-specific cart functionalities such as retrieving cart details, + * generating checkout URLs, and managing cart-related redirects. + * + * @package BigCommerce\Amp */ class Amp_Cart { - const CHECKOUT_REDIRECT_ACTION = 'amp_checkout'; - - /** - * Class constructor - * - * @param string $proxy_base Base path of the proxy REST endpoints. - */ - public function __construct( $proxy_base ) { - $this->proxy_base = $proxy_base; - } - - /** - * Provides a URL endpoint to handle AMP checkout. - * - * @param int $cart_id Unused. - * @return string URL. - */ - public function get_checkout_url( $cart_id = null ) { - return home_url( sprintf( '/bigcommerce/%s', self::CHECKOUT_REDIRECT_ACTION ) ); - } - - /** - * Get the cart ID from the cookie - * - * @return string - */ - public function get_cart_id() { - if ( get_option( Settings\Sections\Cart::OPTION_ENABLE_CART, true ) ) { - return filter_input( INPUT_COOKIE, Cart::CART_COOKIE, FILTER_SANITIZE_STRING ) ?: false; + /** + * Action identifier for AMP checkout redirection. + * + * @var string + */ + const CHECKOUT_REDIRECT_ACTION = 'amp_checkout'; + + /** + * Base path of the proxy REST endpoints. + * + * @var string + */ + private $proxy_base; + + /** + * Class constructor. + * + * @param string $proxy_base Base path of the proxy REST endpoints. + */ + public function __construct( $proxy_base ) { + $this->proxy_base = $proxy_base; + } + + /** + * Provides a URL endpoint to handle AMP checkout. + * + * @param int|null $cart_id Unused in this implementation. + * @return string URL to the AMP checkout endpoint. + */ + public function get_checkout_url( $cart_id = null ) { + return home_url( sprintf( '/bigcommerce/%s', self::CHECKOUT_REDIRECT_ACTION ) ); + } + + /** + * Retrieves the cart ID from the browser's cookie. + * + * Checks if the cart functionality is enabled and retrieves the cart ID + * from the cookie set by BigCommerce. + * + * @return string|false Cart ID if available, false otherwise. + */ + public function get_cart_id() { + if ( get_option( Settings\Sections\Cart::OPTION_ENABLE_CART, true ) ) { + return filter_input( INPUT_COOKIE, Cart::CART_COOKIE, FILTER_SANITIZE_STRING ) ?: false; } else { return false; } - } - - /** - * Gets the URL of the designated cart page. - * - * @return string URL. - */ - public function get_cart_url() { - $cart_page_id = get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ); - if ( empty( $cart_page_id ) ) { - $url = home_url( '/' ); - } else { - $url = amp_get_permalink( $cart_page_id ); - } - - /** - * Filter the URL to the cart page - * - * @param string $url The URL to the cart page - * @param int $page_id The ID of the cart page - */ - return apply_filters( 'bigcommerce/cart/permalink', $url, $cart_page_id ); - } - - /** - * Redirects back to the cart page. - * - * @return void - */ - private function back_to_cart() { - wp_safe_redirect( $this->get_cart_url() ); - die(); - } - - /** - * Gets the checkout URL for the current cart and redirects the user there. - * - * @return void - */ - public function handle_redirect_request() { - $cart_id = $this->get_cart_id(); - - if ( empty( $cart_id ) ) { - $this->back_to_cart(); - } - - $request = new WP_REST_Request( - 'POST', - sprintf( '/%scarts/%s/redirect_urls', trailingslashit( $this->proxy_base ), $cart_id ) - ); - $response = rest_do_request( $request ); - - if ( 200 !== $response->status || ! isset( $response->data['data']['checkout_url'] ) ) { - $this->back_to_cart(); - } - - $url = $response->data['data']['checkout_url']; - $host = wp_parse_url( $url, PHP_URL_HOST ); - - if ( empty( $host ) ) { - $this->back_to_cart(); - } - - add_filter( - 'allowed_redirect_hosts', - function( $hosts ) use ( $host ) { - if ( false !== strpos( $host, 'bigcommerce.com' ) ) { - $hosts[] = $host; - } - - return $hosts; - } - ); - - wp_safe_redirect( $response->data['data']['checkout_url'], 303 ); - die(); - } + } + + /** + * Gets the URL of the designated cart page. + * + * Determines the URL of the cart page based on the WordPress option + * for the cart page ID. Falls back to the home URL if no cart page is set. + * + * @return string URL of the cart page. + */ + public function get_cart_url() { + $cart_page_id = get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ); + + if ( empty( $cart_page_id ) ) { + $url = home_url( '/' ); + } else { + $url = amp_get_permalink( $cart_page_id ); + } + + /** + * Filter the URL to the cart page. + * + * @param string $url The URL to the cart page. + * @param int $page_id The ID of the cart page. + */ + return apply_filters( 'bigcommerce/cart/permalink', $url, $cart_page_id ); + } + + /** + * Redirects the user back to the cart page. + * + * Sends an HTTP redirect to the cart page and terminates script execution. + * + * @return void + */ + private function back_to_cart() { + wp_safe_redirect( $this->get_cart_url() ); + die(); + } + + /** + * Handles redirection to the checkout URL for the current cart. + * + * Uses the cart ID to generate a checkout URL via the BigCommerce API. + * If the checkout URL cannot be retrieved, redirects back to the cart page. + * + * @return void + */ + public function handle_redirect_request() { + $cart_id = $this->get_cart_id(); + + if ( empty( $cart_id ) ) { + $this->back_to_cart(); + } + + $request = new WP_REST_Request( + 'POST', + sprintf( '/%scarts/%s/redirect_urls', trailingslashit( $this->proxy_base ), $cart_id ) + ); + $response = rest_do_request( $request ); + + if ( 200 !== $response->status || ! isset( $response->data['data']['checkout_url'] ) ) { + $this->back_to_cart(); + } + + $url = $response->data['data']['checkout_url']; + $host = wp_parse_url( $url, PHP_URL_HOST ); + + if ( empty( $host ) ) { + $this->back_to_cart(); + } + + add_filter( + 'allowed_redirect_hosts', + function( $hosts ) use ( $host ) { + if ( false !== strpos( $host, 'bigcommerce.com' ) ) { + $hosts[] = $host; + } + + return $hosts; + } + ); + + wp_safe_redirect( $response->data['data']['checkout_url'], 303 ); + die(); + } } diff --git a/src/BigCommerce/Amp/Amp_Cart_Menu_Item.php b/src/BigCommerce/Amp/Amp_Cart_Menu_Item.php index 2304a2a6..57d1787b 100644 --- a/src/BigCommerce/Amp/Amp_Cart_Menu_Item.php +++ b/src/BigCommerce/Amp/Amp_Cart_Menu_Item.php @@ -1,54 +1,79 @@ is_cart_menu_item( $menu_item ) ) { - return $menu_item; - } - $menu_item->classes[] = 'menu-item-bigcommerce-cart'; - $menu_item->title = str_replace( ' ', '', $menu_item->title ); - $amp_cart_rest_url = rest_url( sprintf( '/%s/amp-cart?cart_id=CLIENT_ID(%s)', $proxy_base, Cart::CART_COOKIE ) ); - $menu_item->title .= ' - + /** + * Adds AMP-specific classes and cart item count functionality to the cart menu item. + * + * Adds a `menu-item-bigcommerce-cart` class to the cart menu item and replaces the + * menu item's title with dynamic AMP-powered content that displays the current cart item count. + * + * @param object $menu_item The menu item object. + * @param string $proxy_base The base URL or namespace used for proxying API requests. + * @return object Filtered menu item with added AMP-specific functionality. + * + * @filter wp_setup_nav_menu_item + */ + public function add_classes_to_cart_page( $menu_item, $proxy_base ) { + if ( ! get_option( CartSettings::OPTION_ENABLE_CART, true ) || is_admin() ) { + return $menu_item; + } + + if ( ! $this->is_cart_menu_item( $menu_item ) ) { + return $menu_item; + } + + $menu_item->classes[] = 'menu-item-bigcommerce-cart'; + $menu_item->title = str_replace( ' ', '', $menu_item->title ); + $amp_cart_rest_url = rest_url( sprintf( '/%s/amp-cart?cart_id=CLIENT_ID(%s)', $proxy_base, Cart::CART_COOKIE ) ); + $menu_item->title .= ' + '; - return $menu_item; - } + return $menu_item; + } + + /** + * Checks whether the given menu item corresponds to the cart page. + * + * Verifies that the menu item is of type `post_type` and that its object ID matches + * the cart page ID stored in the options. + * + * @param object $menu_item The menu item object to check. + * @return bool True if the menu item is the cart menu item; false otherwise. + */ + private function is_cart_menu_item( $menu_item ) { + if ( 'post_type' !== $menu_item->type ) { + return false; + } - private function is_cart_menu_item( $menu_item ) { - if ( 'post_type' !== $menu_item->type ) { - return false; - } - $cart_page_id = get_option( CartSettings::OPTION_CART_PAGE_ID, 0 ); + $cart_page_id = get_option( CartSettings::OPTION_CART_PAGE_ID, 0 ); - return $menu_item->object_id === $cart_page_id; - } + return $menu_item->object_id === $cart_page_id; + } } \ No newline at end of file diff --git a/src/BigCommerce/Amp/Amp_Controller_Factory.php b/src/BigCommerce/Amp/Amp_Controller_Factory.php index 2ed80596..4566c99e 100644 --- a/src/BigCommerce/Amp/Amp_Controller_Factory.php +++ b/src/BigCommerce/Amp/Amp_Controller_Factory.php @@ -1,6 +1,5 @@ Amp_Cart_Actions::class, - Cart_Items::class => Amp_Cart_Items::class, - Cart_Summary::class => Amp_Cart_Summary::class, - ]; - - public function get_controller( $classname, array $options = [], $template = '' ) { - if ( array_key_exists( $classname, $this->override_class_map ) ) { - $classname = $this->override_class_map[ $classname ]; - } - return parent::get_controller( $classname, $options, $template ); - } + /** + * Mapping of standard template classes to their AMP-specific counterparts. + * + * This array is used to override the default template controllers with + * AMP-compatible versions. Keys are the fully-qualified names of the standard + * classes, and values are the corresponding AMP class names. + * + * @var array + */ + private $override_class_map = [ + Cart_Actions::class => Amp_Cart_Actions::class, + Cart_Items::class => Amp_Cart_Items::class, + Cart_Summary::class => Amp_Cart_Summary::class, + ]; + /** + * Retrieves the appropriate controller for a given class name. + * + * Overrides the default behavior by replacing the standard class name with + * its AMP counterpart if defined in the `$override_class_map`. + * + * @param string $classname Fully-qualified class name of the controller. + * @param array $options Optional parameters passed to the controller. + * @param string $template Optional template name to associate with the controller. + * + * @return object The controller instance. + */ + public function get_controller( $classname, array $options = [], $template = '' ) { + if ( array_key_exists( $classname, $this->override_class_map ) ) { + $classname = $this->override_class_map[ $classname ]; + } + return parent::get_controller( $classname, $options, $template ); + } } diff --git a/src/BigCommerce/Amp/Amp_Template_Override.php b/src/BigCommerce/Amp/Amp_Template_Override.php index d1aed94b..6519a88b 100644 --- a/src/BigCommerce/Amp/Amp_Template_Override.php +++ b/src/BigCommerce/Amp/Amp_Template_Override.php @@ -1,137 +1,159 @@ amp_directory = $amp_directory; - } - - /** - * @param string $path The absolute path to the template - * @param string $relative_path The relative path of the requested template - * - * @return string The filtered path to the template - * @filter bigcommerce/template/path - */ - public function override_template_path( $path, $relative_path ) { + /** + * Directory name containing AMP-specific template overrides. + * + * @var string + */ + private $amp_directory; + + /** + * Constructor for the Amp_Template_Override class. + * + * @param string $amp_directory Name of the directory containing AMP template overrides. Default is 'amp'. + */ + public function __construct( $amp_directory = 'amp' ) { + $this->amp_directory = $amp_directory; + } + + /** + * Filters the path to a requested template, providing AMP-specific versions if available. + * + * @param string $path The absolute path to the requested template. + * @param string $relative_path The relative path of the template within the theme/plugin. + * + * @return string The filtered template path, modified for AMP if applicable. + * @filter bigcommerce/template/path + */ + public function override_template_path( $path, $relative_path ) { /* * If we're not using AMP classic and are using paired/native instead, * then we should only override `components/*` templates. All the other * templates (i.e. single product, archive etc) will be rendered from * the main WP theme template and thus we should not override that. */ - if ( ! $this->is_classic() && ! strpos( $path, 'components' ) ) { - return $path; - } - - $amp_path = ''; - $amp_relative_path = trailingslashit( $this->amp_directory ) . $relative_path; - - /** - * This filter is documented in src/BigCommerce/Templates/Controller.php - */ - $theme_dir = apply_filters( 'bigcommerce/template/directory/theme', '', $amp_relative_path ); - - /** - * This filter is documented in src/BigCommerce/Templates/Controller.php - */ - $plugin_dir = apply_filters( 'bigcommerce/template/directory/plugin', '', $amp_relative_path ); - if ( ! empty( $theme_dir ) ) { - $amp_path = locate_template( trailingslashit( $theme_dir ) . $amp_relative_path ); - } - - // no template in the theme, so fall back to the plugin default - if ( empty( $amp_path ) && ! empty( $plugin_dir ) ) { - $amp_path = trailingslashit( $plugin_dir ) . $amp_relative_path; - } - - // check that we actually have an AMP override for this template - if ( ! empty( $amp_path ) && file_exists( $amp_path ) ) { - $path = $amp_path; - } - - return $path; - } - - /** - * Override classic template paths for the custom AMP classic theme. - * - * @param string $file The absolute path to the amp template. - * @param string $template_type The type of template being served. - * @param \WP_Post $post The post object of the current post being viewed. - * - * @return string - * @filter amp_post_template_file - */ - public function override_classic_amp_template_path( $file, $template_type, $post ) { - $template = $template_type . '-' . $post->post_type . '.php'; - $file = $this->override_template_path( $file, $template ); - return $file; - } - - /** - * Load header file from the plugin. - * - * @param string $file Template file path. - * @param string $type Template type. - * @param array $container \BigCommerce\Container\Amp - * - * @return string - */ - public function override_classic_header_bar_template( $file, $type, $container ) { - if ( 'header-bar' === $type ) { - $file = $this->override_template_path( $file, 'components/header/header-bar.php' ); - } - return $file; - } - - /** - * Is classic mode enabled for AMP rendering? - * - * @return bool - */ - public function is_classic() { - if ( is_callable( [ '\AMP_Options_Manager', 'get_option' ] ) ) { - $theme_support = \AMP_Options_Manager::get_option( 'theme_support', false ); - - if ( 'native' === $theme_support || 'paired' === $theme_support ) { - return false; - } - } - - return true; - } - - /** - * Adds header_nav_menu to the AMP data in classic mode. - * - * @param array $data AMP template data. - * @return array Filtered data. - */ - public function provide_header_nav_menu( $data ) { - if ( ! isset( $data['header_nav_menu'] ) ) { - $data['header_nav_menu'] = wp_nav_menu( - array( - 'theme_location' => 'amp-menu', - 'container' => 'false', - 'depth' => 1, - 'echo' => false, - ) - ); - } - - return $data; - } + if ( ! $this->is_classic() && ! strpos( $path, 'components' ) ) { + return $path; + } + + $amp_path = ''; + $amp_relative_path = trailingslashit( $this->amp_directory ) . $relative_path; + + /** + * Filter the theme directory for AMP templates. + * + * @param string $theme_dir The directory for AMP templates within the theme. + * @param string $amp_relative_path The relative path of the requested template. + */ + $theme_dir = apply_filters( 'bigcommerce/template/directory/theme', '', $amp_relative_path ); + + /** + * Filter the plugin directory for AMP templates. + * + * @param string $plugin_dir The directory for AMP templates within the plugin. + * @param string $amp_relative_path The relative path of the requested template. + */ + $plugin_dir = apply_filters( 'bigcommerce/template/directory/plugin', '', $amp_relative_path ); + + if ( ! empty( $theme_dir ) ) { + $amp_path = locate_template( trailingslashit( $theme_dir ) . $amp_relative_path ); + } + + // no template in the theme, so fall back to the plugin default + if ( empty( $amp_path ) && ! empty( $plugin_dir ) ) { + $amp_path = trailingslashit( $plugin_dir ) . $amp_relative_path; + } + + // check that we actually have an AMP override for this template + if ( ! empty( $amp_path ) && file_exists( $amp_path ) ) { + $path = $amp_path; + } + + return $path; + } + + /** + * Overrides template paths for classic AMP templates. + * + * @param string $file The absolute path to the AMP template. + * @param string $template_type The type of template being served (e.g., single, archive). + * @param \WP_Post $post The current post object. + * + * @return string The overridden template path. + * @filter amp_post_template_file + */ + public function override_classic_amp_template_path( $file, $template_type, $post ) { + $template = $template_type . '-' . $post->post_type . '.php'; + $file = $this->override_template_path( $file, $template ); + return $file; + } + + /** + * Overrides the header bar template for AMP classic mode. + * + * @param string $file Template file path. + * @param string $type Template type (e.g., 'header-bar'). + * @param array $container \BigCommerce\Container\Amp + * + * @return string The overridden template file path. + */ + public function override_classic_header_bar_template( $file, $type, $container ) { + if ( 'header-bar' === $type ) { + $file = $this->override_template_path( $file, 'components/header/header-bar.php' ); + } + return $file; + } + + /** + * Determines whether AMP is in classic mode. + * + * Classic mode renders AMP templates for all pages, while paired/native mode only + * renders AMP templates for specific components. + * + * @return bool True if classic mode is enabled; false otherwise. + */ + public function is_classic() { + if ( is_callable( [ '\AMP_Options_Manager', 'get_option' ] ) ) { + $theme_support = \AMP_Options_Manager::get_option( 'theme_support', false ); + + if ( 'native' === $theme_support || 'paired' === $theme_support ) { + return false; + } + } + + return true; + } + + /** + * Provides the header navigation menu data in AMP classic mode. + * + * @param array $data AMP template data. + * + * @return array Filtered data with `header_nav_menu` included. + */ + public function provide_header_nav_menu( $data ) { + if ( ! isset( $data['header_nav_menu'] ) ) { + $data['header_nav_menu'] = wp_nav_menu( + array( + 'theme_location' => 'amp-menu', + 'container' => 'false', + 'depth' => 1, + 'echo' => false, + ) + ); + } + + return $data; + } } diff --git a/src/BigCommerce/Amp/Classic.php b/src/BigCommerce/Amp/Classic.php index 1d1379c5..8befdc6c 100644 --- a/src/BigCommerce/Amp/Classic.php +++ b/src/BigCommerce/Amp/Classic.php @@ -5,16 +5,21 @@ /** * Class Classic * - * Specific customizations for the classic AMP mode. + * Provides customizations for the classic AMP mode, including + * registering specific menus for AMP compatibility. * * @package BigCommerce\Amp */ class Classic { - /** - * Register the AMP Header menu. - */ - public function register_amp_menu() { - register_nav_menu( 'amp-menu', 'AMP Hamburger Menu' ); - } + /** + * Registers the AMP Header menu. + * + * This menu is used for the AMP hamburger menu in classic AMP mode. + * + * @return void + */ + public function register_amp_menu() { + register_nav_menu( 'amp-menu', 'AMP Hamburger Menu' ); + } } diff --git a/src/BigCommerce/Amp/Overrides.php b/src/BigCommerce/Amp/Overrides.php index 6123cd42..191a5727 100644 --- a/src/BigCommerce/Amp/Overrides.php +++ b/src/BigCommerce/Amp/Overrides.php @@ -8,22 +8,25 @@ /** * Class Overrides * - * Overrides template variables. + * Provides custom AMP-specific overrides and modifications, + * including handling image sources, enabling AMP buttons, + * and defining allowed HTML tags for AMP templates. * * @package BigCommerce\Amp */ class Overrides { - /** - * Add AMP Img Src - * - * Adds 'image_src' to the data passed to the product featured image template. - * - * @param array $data Data to be sent to the template. - * @param string $template Current template. - * - * @return array - */ + /** + * Add AMP image source. + * + * Adds `image_src` and `image_srcset` to the data passed to the product featured image template + * for AMP compatibility. + * + * @param array $data Data to be sent to the template. + * @param string $template Current template being rendered. + * + * @return array Modified data array. + */ public function add_amp_img_src( $data, $template ) { if ( 'components/products/product-featured-image.php' === $template ) { $featured_image = wp_get_attachment_image_src( $data['attachment_id'], Image_Sizes::BC_MEDIUM ); @@ -51,16 +54,16 @@ public function add_amp_img_src( $data, $template ) { return $data; } - /** - * AMP Enable Button - * - * Enable the AMP submit button when a proper variant has been chosen using array filters. - * - * @param string $button Button HTML. - * @param int $post_id Post ID. - * - * @return string - */ + /** + * Enable AMP button. + * + * Dynamically enables the AMP submit button when a proper product variant is selected. + * + * @param string $button Original button HTML. + * @param int $post_id ID of the current post or product. + * + * @return string Modified button HTML. + */ public function amp_enable_button( $button, $post_id ) { $insert = '[disabled]="' . esc_attr( 'variants' . $post_id . '.allVariants.filter( a => a.options.filter( b => ( keys( variants' . $post_id . '.currentOptions ).filter( key => variants' . $post_id . '.currentOptions[ key ] == b.id && key == b.option_id ? true : false ) ).length ? true : false ).length == a.options.length ? a : false )[0].disabled != false ? \'disabled\' : false' ) . '"'; $button = str_replace( 'type="submit"', 'type="submit" ' . $insert, $button ); @@ -68,13 +71,15 @@ public function amp_enable_button( $button, $post_id ) { return $button; } - /** - * AMP Add Redirect Headers - * - * Identify if we are attempting a redirect from an AMP form and if so, add the proper headers to redirect in AMP. - * - * @param string $url URL to be redirected to. - */ + /** + * Add AMP redirect headers. + * + * Adds necessary headers for AMP redirects and ensures proper URL formatting. + * + * @param string $url The URL to redirect to. + * + * @return void + */ public function add_amp_redirect_headers( $url ) { $amp_source_origin = filter_input( INPUT_GET, '__amp_source_origin', FILTER_SANITIZE_STRING ) ?: false; @@ -100,11 +105,13 @@ public function add_amp_redirect_headers( $url ) { } } - /** - * Filter Fallback Image - * - * @return string - */ + /** + * Filter fallback image for AMP. + * + * Returns a formatted AMP-compliant image placeholder. + * + * @return string AMP-compliant `` HTML for the fallback image. + */ public function filter_fallback_image() { $url = bigcommerce()->container()[ Assets::PATH ] . '/img/public/'; $srcset = [ @@ -121,14 +128,14 @@ public function filter_fallback_image() { ); } - /** - * AMP Kses Allowed HTML - * - * @param array $allowed_tags Array of allowed tags - * @param string $context Context of kses tags. - * - * @return array - */ + /** + * Customize allowed HTML tags for AMP context. + * + * @param array $allowed_tags Array of allowed HTML tags. + * @param string $context Context for filtering. + * + * @return array Modified array of allowed tags. + */ public function amp_kses_allowed_html( $allowed_tags, $context ) { if ( 'bigcommerce/amp' === $context ) { /** diff --git a/src/BigCommerce/Analytics/Events/Add_To_Cart.php b/src/BigCommerce/Analytics/Events/Add_To_Cart.php index 9297a3fd..08109563 100644 --- a/src/BigCommerce/Analytics/Events/Add_To_Cart.php +++ b/src/BigCommerce/Analytics/Events/Add_To_Cart.php @@ -11,68 +11,96 @@ /** * Class Add_To_Cart * - * Add analytics tracking to purchase buttons and set success message tracking attributes + * Adds analytics tracking attributes to purchase buttons and success messages. + * + * This class is responsible for enhancing the add-to-cart functionality by embedding + * tracking attributes into the purchase buttons and success messages. The tracking + * attributes are used to collect analytics data about the user's interactions. + * + * @package BigCommerce\Analytics\Events */ class Add_To_Cart { + /** + * Sets tracking attributes on the success message displayed after adding a product to the cart. + * + * This function parses the data provided by the cart action and applies tracking attributes + * to the success message. The tracking data includes details such as cart ID, product ID, + * variant ID, and product name. + * + * @param array $args Attributes of the success message. + * @param array $data Data related to the cart action. + * + * @return array Modified success message attributes with tracking data. + */ + public function set_tracking_attributes_on_success_message( $args, $data ) { + if ( ! array_key_exists( 'data', $data ) ) { + return $args; + } + + $data = $data['data']; + if ( array_key_exists( 'key', $data ) && $data['key'] == 'add_to_cart' ) { + $data = wp_parse_args( $data, [ + 'cart_id' => '', + 'post_id' => 0, + 'product_id' => 0, + 'variant_id' => 0, + ] ); - /** - * @param array $args - * @param array $data - * - * @return array - */ - public function set_tracking_attributes_on_success_message( $args, $data ) { - if ( ! array_key_exists( 'data', $data ) ) { - return $args; - } - $data = $data['data']; - if ( array_key_exists( 'key', $data ) && $data['key'] == 'add_to_cart' ) { - $data = wp_parse_args( $data, [ - 'cart_id' => '', - 'post_id' => 0, - 'product_id' => 0, - 'variant_id' => 0, - ] ); + $track_data = [ + 'cart_id' => $data['cart_id'], + 'post_id' => $data['post_id'], + 'product_id' => $data['product_id'], + 'variant_id' => $data['variant_id'], + 'name' => get_the_title( $data['post_id'] ), + ]; + /** + * Modifies the tracking data options for analytics. + * + * This allows for customization of analytics tracking behavior. + * + * @param array $track_data Tracking data options. + * + * @return array Modified tracking data options. + */ + $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); - $track_data = [ - 'cart_id' => $data['cart_id'], - 'post_id' => $data['post_id'], - 'product_id' => $data['product_id'], - 'variant_id' => $data['variant_id'], - 'name' => get_the_title( $data['post_id'] ), - ]; - $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); + $args[ Message::ATTRIBUTES ] = array_merge( $args[ Message::ATTRIBUTES ], [ + 'data-tracking-trigger' => 'ready', + 'data-tracking-event' => 'add_to_cart_message', + 'data-tracking-data' => wp_json_encode( $track_data ), + ] ); + } - $args[ Message::ATTRIBUTES ] = array_merge( $args[ Message::ATTRIBUTES ], [ - 'data-tracking-trigger' => 'ready', - 'data-tracking-event' => 'add_to_cart_message', - 'data-tracking-data' => wp_json_encode( $track_data ), - ] ); - } + return $args; + } - return $args; - } + /** + * Adds tracking attributes to the purchase button for analytics purposes. + * + * The tracking attributes include information about the product being purchased, such as + * product ID, post ID, and product name. This data is embedded into the button's attributes + * for tracking the add-to-cart action. + * + * @param array $attributes Attributes of the purchase button. + * @param Product $product The product object associated with the button. + * + * @return array Modified button attributes with tracking data. + * @filter bigcommerce/button/purchase/attributes + */ + public function add_tracking_attributes_to_purchase_button( $attributes, $product ) { + $track_data = [ + 'post_id' => $product->post_id(), + 'product_id' => $product->bc_id(), + 'name' => get_the_title( $product->post_id() ), + ]; - /** - * @param array $attributes - * @param Product $product - * - * @return array - * @filter bigcommerce/button/purchase/attributes - */ - public function add_tracking_attributes_to_purchase_button( $attributes, $product ) { - $track_data = [ - 'post_id' => $product->post_id(), - 'product_id' => $product->bc_id(), - 'name' => get_the_title( $product->post_id() ), - ]; - $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); + $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); - return array_merge( $attributes, [ - 'data-tracking-trigger' => 'ready', - 'data-tracking-event' => 'add_to_cart', - 'data-tracking-data' => wp_json_encode( $track_data ), - ] ); - } + return array_merge( $attributes, [ + 'data-tracking-trigger' => 'ready', + 'data-tracking-event' => 'add_to_cart', + 'data-tracking-data' => wp_json_encode( $track_data ), + ] ); + } } diff --git a/src/BigCommerce/Analytics/Events/View_Product.php b/src/BigCommerce/Analytics/Events/View_Product.php index 33dcef09..eff4aca8 100644 --- a/src/BigCommerce/Analytics/Events/View_Product.php +++ b/src/BigCommerce/Analytics/Events/View_Product.php @@ -12,102 +12,129 @@ /** * Class View_Product * - * Add analytics events to the permalink and buttons + * Adds analytics events to product permalink and buttons for tracking. + * + * This class is responsible for attaching analytics tracking attributes to the product's view + * buttons and permalink. It tracks events such as product views by adding the necessary data + * attributes to the HTML elements. The tracking includes product information like product ID, + * name, and SKU if enabled in the settings. + * + * @package BigCommerce\Analytics\Events */ class View_Product { - /** - * @param array $options - * @param string $template - * - * @return array - * @filter bigcommerce/template=components/products/view-product-button.php/options - */ - public function add_tracking_attributes_to_button( $options = [], $template = '' ) { - if ( empty( $options[ View_Product_Button::PRODUCT ] ) ) { - return $options; - } - /** @var Product $product */ - $product = $options[ View_Product_Button::PRODUCT ]; - - if ( empty( $options[ View_Product_Button::ATTRIBUTES ] ) ) { - $options[ View_Product_Button::ATTRIBUTES ] = []; - } - - $track_data = [ - 'post_id' => $product->post_id(), - 'product_id' => $product->bc_id(), - 'name' => get_the_title( $product->post_id() ), - ]; - $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); - - $options[ View_Product_Button::ATTRIBUTES ] = array_merge( $options[ View_Product_Button::ATTRIBUTES ], [ - 'data-tracking-trigger' => 'click', - 'data-tracking-event' => 'view_product', - 'data-tracking-data' => wp_json_encode( $track_data ), - ] ); - - return $options; - } - - /** - * @param array $options - * @param string $template - * - * @return array - * @filter bigcommerce/template=components/products/product-title.php/options - */ - public function add_tracking_attributes_to_permalink( $options, $template ) { - if ( empty( $options[ Product_Title::USE_PERMALINK ] ) || empty( $options[ Product_Title::PRODUCT ] ) ) { - return $options; - } - - if ( empty( $options[ View_Product_Button::ATTRIBUTES ] ) ) { - $options[ View_Product_Button::ATTRIBUTES ] = []; - } - - $product = $options[ Product_Title::PRODUCT ]; - - $track_data = [ - 'post_id' => $product->post_id(), - 'product_id' => $product->bc_id(), - 'name' => get_the_title( $product->post_id() ), - ]; - $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); - - $options[ Product_Title::LINK_ATTRIBUTES ] = array_merge( $options[ Product_Title::LINK_ATTRIBUTES ], [ - 'data-tracking-trigger' => 'click', - 'data-tracking-event' => 'view_product', - 'data-tracking-data' => wp_json_encode( $track_data ), - ] ); - - return $options; - } - - /** - * Update tracking data for product if Analytics options are set to SKU tracking - * - * @param $track_data - * - * @return mixed - */ - public function change_track_data( $track_data ) { - $should_track_sku = (bool) get_option( Analytics::TRACK_PRODUCT_SKU, 0 ); - - if ( empty( $should_track_sku ) ) { - return $track_data; - } - - try { - $product = new Product( $track_data['post_id'] ); - $track_data['sku'] = $product->get_property( 'sku' ); - - if ( ! empty( $track_data['variant_id'] ) ) { - $track_data['variant_sku'] = $product->get_variant_sku( $track_data['variant_id'] ); - } - - return $track_data; - } catch ( \Exception $exception ) { - return $track_data; - } - } + + /** + * Adds tracking attributes to the product view button. + * + * This function embeds tracking data into the attributes of the product view button. + * The tracking attributes include product details like product ID, post ID, and product name. + * It triggers the 'view_product' event when the button is clicked. + * + * @param array $options Options for the button. + * @param string $template The template name for the button. + * + * @return array Modified options with added tracking attributes. + * @filter bigcommerce/template=components/products/view-product-button.php/options + */ + public function add_tracking_attributes_to_button( $options = [], $template = '' ) { + if ( empty( $options[ View_Product_Button::PRODUCT ] ) ) { + return $options; + } + + /** @var Product $product */ + $product = $options[ View_Product_Button::PRODUCT ]; + + if ( empty( $options[ View_Product_Button::ATTRIBUTES ] ) ) { + $options[ View_Product_Button::ATTRIBUTES ] = []; + } + + $track_data = [ + 'post_id' => $product->post_id(), + 'product_id' => $product->bc_id(), + 'name' => get_the_title( $product->post_id() ), + ]; + + $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); + + $options[ View_Product_Button::ATTRIBUTES ] = array_merge( $options[ View_Product_Button::ATTRIBUTES ], [ + 'data-tracking-trigger' => 'click', + 'data-tracking-event' => 'view_product', + 'data-tracking-data' => wp_json_encode( $track_data ), + ] ); + + return $options; + } + + /** + * Adds tracking attributes to the product permalink. + * + * This function attaches tracking data to the product permalink's attributes. + * The tracking includes product details such as product ID, post ID, and product name. + * The 'view_product' event is triggered when the permalink is clicked. + * + * @param array $options Options for the permalink. + * @param string $template The template name for the permalink. + * + * @return array Modified options with added tracking attributes. + * @filter bigcommerce/template=components/products/product-title.php/options + */ + public function add_tracking_attributes_to_permalink( $options, $template ) { + if ( empty( $options[ Product_Title::USE_PERMALINK ] ) || empty( $options[ Product_Title::PRODUCT ] ) ) { + return $options; + } + + if ( empty( $options[ View_Product_Button::ATTRIBUTES ] ) ) { + $options[ View_Product_Button::ATTRIBUTES ] = []; + } + + $product = $options[ Product_Title::PRODUCT ]; + + $track_data = [ + 'post_id' => $product->post_id(), + 'product_id' => $product->bc_id(), + 'name' => get_the_title( $product->post_id() ), + ]; + + $track_data = apply_filters( Analytics::TRACK_BY_HOOK, $track_data ); + + $options[ Product_Title::LINK_ATTRIBUTES ] = array_merge( $options[ Product_Title::LINK_ATTRIBUTES ], [ + 'data-tracking-trigger' => 'click', + 'data-tracking-event' => 'view_product', + 'data-tracking-data' => wp_json_encode( $track_data ), + ] ); + + return $options; + } + + /** + * Updates tracking data to include SKU information if enabled in Analytics settings. + * + * If SKU tracking is enabled in the Analytics options, this function appends the SKU + * to the tracking data for the product. If a variant ID is provided, the variant's SKU + * is also included. If the product cannot be loaded, the original tracking data is returned. + * + * @param array $track_data The existing tracking data. + * + * @return array The updated tracking data, potentially including SKU information. + */ + public function change_track_data( $track_data ) { + $should_track_sku = (bool) get_option( Analytics::TRACK_PRODUCT_SKU, 0 ); + + if ( empty( $should_track_sku ) ) { + return $track_data; + } + + try { + $product = new Product( $track_data['post_id'] ); + $track_data['sku'] = $product->get_property( 'sku' ); + + if ( ! empty( $track_data['variant_id'] ) ) { + $track_data['variant_sku'] = $product->get_variant_sku( $track_data['variant_id'] ); + } + + return $track_data; + } catch ( \Exception $exception ) { + return $track_data; + } + } } diff --git a/src/BigCommerce/Analytics/Facebook_Pixel.php b/src/BigCommerce/Analytics/Facebook_Pixel.php index d0b6adfe..31ae9039 100644 --- a/src/BigCommerce/Analytics/Facebook_Pixel.php +++ b/src/BigCommerce/Analytics/Facebook_Pixel.php @@ -9,36 +9,53 @@ /** * Class Facebook_Pixel * - * Render Facebook pixel tracking code + * Renders the Facebook Pixel tracking code on the site. + * + * This class is responsible for injecting the Facebook Pixel tracking code into the + * `` section of the website. The tracking code is used to track user interactions + * for the purpose of running analytics and ad targeting on Facebook. + * The tracking code is only added if a valid Facebook Pixel ID is set in the settings. + * + * @package BigCommerce\Analytics */ class Facebook_Pixel { - /** - * @return void - * @action wp_head - */ - public function render_tracking_code() { - $code = get_option( Analytics::FACEBOOK_PIXEL ); - if ( empty( $code ) ) { - return; - } - ?> - - - - - ` section of the webpage using the `wp_head` action hook. + * If no Facebook Pixel ID is set, the function does nothing. + * + * @return void + * @action wp_head + */ + public function render_tracking_code() { + $code = get_option( Analytics::FACEBOOK_PIXEL ); + + if ( empty( $code ) ) { + return; + } + + ?> + + + + + ` section of the website. The tracking code is used to gather analytics + * data about site visitors, including traffic and user behavior. The tracking code + * is only added if a valid Google Analytics ID is set in the settings. + * + * @package BigCommerce\Analytics */ class Google_Analytics { - /** - * @return void - * @action wp_head - */ - public function render_tracking_code() { - $code = get_option( Analytics::GOOGLE_ANALYTICS ); - if ( empty( $code ) ) { - return; - } - ?> - - - - - ` section of the webpage using the `wp_head` action hook. + * If no Google Analytics ID is set, the function does nothing. + * + * @return void + * @action wp_head + */ + public function render_tracking_code() { + $code = get_option( Analytics::GOOGLE_ANALYTICS ); + + if ( empty( $code ) ) { + return; + } + + ?> + + + + + ` section of the website. The code is used to collect data on user behavior, + * page views, and other user interactions. The tracking code is only added if a valid + * Segment key is set in the settings. + * + * @package BigCommerce\Analytics */ class Segment { - /** - * @return void - * @action wp_head - */ - public function render_tracking_code() { - $key = get_option( Analytics::SEGMENT ); - $settings = $this->get_settings(); - ?> - - - - ` section of the webpage using the `wp_head` action hook. + * If no Segment key is set, the function does nothing. + * + * @return void + * @action wp_head */ - private function get_settings() { - $settings = []; + public function render_tracking_code() { + $key = get_option( Analytics::SEGMENT ); + $settings = $this->get_settings(); + ?> + + + + true, 'includeSearch' => true, - 'nonInteration' => false, + 'nonIntegration' => false, 'sendUserId' => true, 'trackingId' => $google, ]; } - $facebook = get_option( Analytics::FACEBOOK_PIXEL ); - if ( $facebook ) { - $settings[ 'Facebook Pixel' ] = [ - 'pixelId' => $facebook, - 'initWithExistingTraits' => true, - ]; - } + $google = get_option( Analytics::GOOGLE_ANALYTICS ); + if ( $google ) { + $settings[ 'Google Analytics' ] = [ + 'enhancedEcommerce' => true, + 'includeSearch' => true, + 'nonIntegration' => false, + 'sendUserId' => true, + 'trackingId' => $google, + ]; + } - /** - * Filter the configuration object passed to Segment + $facebook = get_option( Analytics::FACEBOOK_PIXEL ); + if ( $facebook ) { + $settings[ 'Facebook Pixel' ] = [ + 'pixelId' => $facebook, + 'initWithExistingTraits' => true, + ]; + } + + /** + * Filter the configuration object passed to Segment * * @param array $settings Settings. - */ - $settings = apply_filters( 'bigcommerce/analytics/segment/settings', $settings ); - return (object) $settings; - } - + */ + $settings = apply_filters( 'bigcommerce/analytics/segment/settings', $settings ); + return (object) $settings; + } } diff --git a/src/BigCommerce/Api/Api_Config_Renewal.php b/src/BigCommerce/Api/Api_Config_Renewal.php index 400c2263..be128b6a 100644 --- a/src/BigCommerce/Api/Api_Config_Renewal.php +++ b/src/BigCommerce/Api/Api_Config_Renewal.php @@ -6,40 +6,75 @@ use BigCommerce\Container\Settings; use BigCommerce\Settings\Sections\Api_Credentials; +/** + * Class Api_Config_Renewal + * + * Handles the renewal of API configuration settings. + * + * This class is responsible for updating the configuration of the BigCommerce API + * based on new credentials (store URL, client ID, client secret, and access token). + * After updating the configuration, it reconfigures the BigCommerce API client + * with the new credentials. + * + * @package BigCommerce\Api + */ class Api_Config_Renewal { - private $config; - - public function __construct(Configuration $config ) { - $this->config = $config; - } - - public function renewal_config( $option, $value ) { - switch ( $option ) { - case Api_Credentials::OPTION_STORE_URL: - $this->config->setHost( $value ); - break; - case Api_Credentials::OPTION_CLIENT_ID: - $this->config->setClientId( $value ); - break; - case Api_Credentials::OPTION_CLIENT_SECRET: - $this->config->setClientSecret( $value ); - break; - case Api_Credentials::OPTION_ACCESS_TOKEN: - $this->config->setAccessToken( $value ); - break; - } - - $hash = bigcommerce()->container()[ Settings::CREDENTIALS_SCREEN ]->get_store_hash( $this->config->getHost() ); - - \Bigcommerce\Api\Client::configure( [ - 'client_id' => $this->config->getClientId(), - 'auth_token' => $this->config->getAccessToken(), - 'client_secret' => $this->config->getClientSecret(), - 'store_hash' => $hash, - ] ); - - return $this->config; - } + /** + * @var Configuration + */ + private $config; + /** + * Api_Config_Renewal constructor. + * + * Initializes the API configuration renewal process. + * + * @param Configuration $config The configuration object used to store and manage API credentials. + */ + public function __construct(Configuration $config ) { + $this->config = $config; + } + + /** + * Renews the API configuration based on the provided option and value. + * + * This function updates the API configuration by setting the new value for + * the specified option (store URL, client ID, client secret, or access token). + * After updating the configuration, it reconfigures the BigCommerce API client + * with the new credentials. + * + * @param string $option The configuration option to renew (e.g., 'store_url', 'client_id'). + * @param string $value The new value for the configuration option. + * + * @return Configuration The updated configuration object. + */ + public function renewal_config( $option, $value ) { + switch ( $option ) { + case Api_Credentials::OPTION_STORE_URL: + $this->config->setHost( $value ); + break; + case Api_Credentials::OPTION_CLIENT_ID: + $this->config->setClientId( $value ); + break; + case Api_Credentials::OPTION_CLIENT_SECRET: + $this->config->setClientSecret( $value ); + break; + case Api_Credentials::OPTION_ACCESS_TOKEN: + $this->config->setAccessToken( $value ); + break; + } + + $hash = bigcommerce()->container()[ Settings::CREDENTIALS_SCREEN ]->get_store_hash( $this->config->getHost() ); + + \Bigcommerce\Api\Client::configure( [ + 'client_id' => $this->config->getClientId(), + 'auth_token' => $this->config->getAccessToken(), + 'client_secret' => $this->config->getClientSecret(), + 'store_hash' => $hash, + ] ); + + return $this->config; + } + } diff --git a/src/BigCommerce/Api/Api_Data_Sanitizer.php b/src/BigCommerce/Api/Api_Data_Sanitizer.php index 0c291bda..1c818094 100644 --- a/src/BigCommerce/Api/Api_Data_Sanitizer.php +++ b/src/BigCommerce/Api/Api_Data_Sanitizer.php @@ -1,47 +1,109 @@ format( 'Y-m-d H:i:s' ); - } + /** + * Sanitizes a date value. + * + * This method formats a `DateTime` object to a string in 'Y-m-d H:i:s' format. + * If the value is not a `DateTime` object, it returns the current time in + * MySQL format. + * + * @param mixed $value The value to sanitize. + * + * @return string The sanitized date value in 'Y-m-d H:i:s' format. + */ + protected function sanitize_date( $value ) { + if ( $value instanceof \DateTime ) { + return $value->format( 'Y-m-d H:i:s' ); + } - return current_time( 'mysql', true ); - } + return current_time( 'mysql', true ); + } } diff --git a/src/BigCommerce/Api/Api_Scopes_Validator.php b/src/BigCommerce/Api/Api_Scopes_Validator.php index 787d7879..2f249e4c 100644 --- a/src/BigCommerce/Api/Api_Scopes_Validator.php +++ b/src/BigCommerce/Api/Api_Scopes_Validator.php @@ -4,88 +4,131 @@ use BigCommerce\Logging\Error_Log; +/** + * Validates the API scopes for several resources, ensuring that the correct permissions + * are in place during the onboarding process. This includes validating scopes for + * customers, orders, and payment methods. + * + * @package BigCommerce\Api + */ class Api_Scopes_Validator extends v2ApiAdapter { - const CUSTOMERS_RESOURCE = '/customers'; - const MARKETING_RESOURCE = '/gift_certificates'; - const ORDERS_RESOURCE = '/orders'; - const PAYMENT_METHODS_RESOURCE = '/payments/methods'; - - /** - * Validate scopes for several API items in order to make pre check during onboarding process - * - * @return bool - * - * @throws \Exception - */ - public function validate() { - $customer = $this->validate_customers_modify_scope(); - - if ( ! $customer ) { - throw new \Exception( __( 'Customers API scopes are invalid', 'bigcommerce' ), 500 ); - } - - $this->cleanup_scope_check_resource( self::CUSTOMERS_RESOURCE, $customer ); - - $resources = [ - self::ORDERS_RESOURCE, - self::PAYMENT_METHODS_RESOURCE, - ]; - - foreach ( $resources as $path ) { - if ( ! $this->validate_scopes( $path ) ) { - throw new \Exception( sprintf( __( 'API scopes are invalid. Requested resource: %s', 'bigcommerce' ), $path ), 500 ); - } - } - - return true; - } - - private function validate_customers_modify_scope() { - try { - $result = $this->createResource( self::CUSTOMERS_RESOURCE, [ - 'company' => 'Bigcommerce', - 'email' => sprintf( 'api-scopecheck-%d@gmail.com', time() ), - 'first_name' => 'Api', - 'last_name' => 'Scope', - 'phone' => '1234567890', - ] ); - - if ( ! $result || ! isset( $result->id ) ) { - return false; - } - - return $result->id; - } catch ( \Exception $e ) { - do_action( 'bigcommerce/log', Error_Log::ERROR, __( 'Could not proceed with current API scopes for customers', 'bigcommerce' ), [ - 'trace' => $e->getTraceAsString(), - ] ); - - return false; - } - } - - private function validate_scopes( $path = '' ) { - try { - $result = $this->getResource( $path ); - - if ( ! $result ) { - return false; - } - - return true; - } catch ( \Exception $e ) { - do_action( 'bigcommerce/log', Error_Log::ERROR, __( 'Could not proceed with current API scopes for Marketing', 'bigcommerce' ), [ - 'trace' => $e->getTraceAsString(), - ] ); - - return false; - } - } - - private function cleanup_scope_check_resource( $path, $id ) { - $deletePath = sprintf( $path . '/%d', $id ); - $this->deleteResource( $deletePath ); - } - + /** + * Customers resource endpoint. + * @var string + */ + const CUSTOMERS_RESOURCE = '/customers'; + + /** + * Marketing resource endpoint (gift certificates). + * @var string + */ + const MARKETING_RESOURCE = '/gift_certificates'; + + /** + * Orders resource endpoint. + * @var string + */ + const ORDERS_RESOURCE = '/orders'; + + /** + * Payment methods resource endpoint. + * @var string + */ + const PAYMENT_METHODS_RESOURCE = '/payments/methods'; + + /** + * Validates scopes for several API items to ensure that the necessary permissions + * are in place during the onboarding process. + * + * This method checks the scopes for customers, orders, and payment methods and + * throws an exception if any of them are invalid. + * + * @return bool Returns true if all scopes are valid. + * + * @throws \Exception If any of the scopes are invalid. + */ + public function validate() { + $customer = $this->validate_customers_modify_scope(); + + if ( ! $customer ) { + throw new \Exception( __( 'Customers API scopes are invalid', 'bigcommerce' ), 500 ); + } + + $this->cleanup_scope_check_resource( self::CUSTOMERS_RESOURCE, $customer ); + + $resources = [ + self::ORDERS_RESOURCE, + self::PAYMENT_METHODS_RESOURCE, + ]; + + foreach ( $resources as $path ) { + if ( ! $this->validate_scopes( $path ) ) { + throw new \Exception( sprintf( __( 'API scopes are invalid. Requested resource: %s', 'bigcommerce' ), $path ), 500 ); + } + } + + return true; + } + + private function validate_customers_modify_scope() { + try { + $result = $this->createResource( self::CUSTOMERS_RESOURCE, [ + 'company' => 'Bigcommerce', + 'email' => sprintf( 'api-scopecheck-%d@gmail.com', time() ), + 'first_name' => 'Api', + 'last_name' => 'Scope', + 'phone' => '1234567890', + ] ); + + if ( ! $result || ! isset( $result->id ) ) { + return false; + } + + return $result->id; + } catch ( \Exception $e ) { + /** + * Fires when customer API scope validation fails + * + * @param string $level The error level (Error_Log::ERROR) + * @param string $message The error message + * @param array $data Additional error data including stack trace + */ + do_action( 'bigcommerce/log', Error_Log::ERROR, __( 'Could not proceed with current API scopes for customers', 'bigcommerce' ), [ + 'trace' => $e->getTraceAsString(), + ] ); + + return false; + } + } + + private function validate_scopes( $path = '' ) { + try { + $result = $this->getResource( $path ); + + if ( ! $result ) { + return false; + } + + return true; + } catch ( \Exception $e ) { + /** + * Fires when marketing API scope validation fails + * + * @param string $level The error level (Error_Log::ERROR) + * @param string $message The error message + * @param array $data Additional error data including stack trace + */ + do_action( 'bigcommerce/log', Error_Log::ERROR, __( 'Could not proceed with current API scopes for Marketing', 'bigcommerce' ), [ + 'trace' => $e->getTraceAsString(), + ] ); + + return false; + } + } + + private function cleanup_scope_check_resource( $path, $id ) { + $deletePath = sprintf( $path . '/%d', $id ); + $this->deleteResource( $deletePath ); + } } diff --git a/src/BigCommerce/Api/Banners_Api.php b/src/BigCommerce/Api/Banners_Api.php index ddf10bd8..c7f6dd5e 100644 --- a/src/BigCommerce/Api/Banners_Api.php +++ b/src/BigCommerce/Api/Banners_Api.php @@ -6,13 +6,35 @@ /** * Class Banners_Api * - * Get banners data from banners v2 api collection + * Retrieves banner data from the Banners v2 API collection. This class allows you + * to fetch banners and their associated details, such as name, content, location, + * and visibility. * * @package BigCommerce\Api */ class Banners_Api extends v2ApiAdapter { - public function get_banners() { + /** + * Fetches a list of banners from the Banners v2 API. + * + * This method retrieves the banners collection from the API and maps each banner + * to a simplified array format containing its relevant data such as ID, name, content, + * item ID, location, creation date, visibility, and more. + * + * @return array Returns an array of banners with the following keys: + * - 'id' (int) + * - 'name' (string) + * - 'content' (string) + * - 'page' (string) + * - 'item_id' (int) + * - 'location' (string) + * - 'date_created' (int) + * - 'date_type' (string) + * - 'date_from' (int) + * - 'date_to' (int) + * - 'visible' (bool) + */ + public function get_banners() { return array_map( function ( $banner ) { return [ 'id' => (int) $banner->id, @@ -29,6 +51,5 @@ public function get_banners() { ]; }, $this->getCollection( '/banners' ) ?: [] ); - } - + } } diff --git a/src/BigCommerce/Api/Base_Client.php b/src/BigCommerce/Api/Base_Client.php index bd8bbe40..3a8e8493 100644 --- a/src/BigCommerce/Api/Base_Client.php +++ b/src/BigCommerce/Api/Base_Client.php @@ -4,30 +4,42 @@ use BigCommerce\Api\v3\ApiClient; +/** + * Base API client class that extends the ApiClient and manages the configuration + * of the API client. This class is designed to handle the configuration for + * API communication and can be extended for specific API clients. + * + * @package BigCommerce\Api + */ class Base_Client extends ApiClient { - /** - * Configuration - * - * @var Configuration - */ - protected $config; + /** + * Configuration for the API client + * + * @var Configuration + */ + protected $config; - /** - * Constructor of the class - * - * @param Configuration $config config for this ApiClient - */ - public function __construct( Configuration $config = null ) { - parent::__construct( $config ); - } + /** + * Constructor for the Base_Client class + * + * Initializes the API client with the provided configuration. If no configuration + * is provided, it will use the default configuration. + * + * @param Configuration|null $config The configuration for this ApiClient. + */ + public function __construct( Configuration $config = null ) { + parent::__construct( $config ); + } - /** - * Get the config - * - * @return Configuration - */ - public function getConfig() { - return $this->config; - } + /** + * Gets the configuration of the API client + * + * Returns the configuration object used by the API client. + * + * @return Configuration Returns the Configuration object used by this API client. + */ + public function getConfig() { + return $this->config; + } } \ No newline at end of file diff --git a/src/BigCommerce/Api/Caching_Client.php b/src/BigCommerce/Api/Caching_Client.php index 0fec2c23..e36c1d76 100644 --- a/src/BigCommerce/Api/Caching_Client.php +++ b/src/BigCommerce/Api/Caching_Client.php @@ -7,35 +7,45 @@ use BigCommerce\Api\v3\ObjectSerializer; /** - * Class Caching_Client + * Implements a short-term caching mechanism around API requests to reduce redundant calls, + * particularly useful for operations like cart handling. The cache is invalidated after + * any write operation to ensure data consistency. * - * Wraps a short-term cache around API requests. - * This avoids making the same request (especially - * for the cart) over and over. - * - * The cache is flushed every time a write operation - * occurs. + * @package BigCommerce\Api */ class Caching_Client extends Base_Client { - /** @var string */ - private $cache_group = 'bigcommerce_api'; - /** @var string */ - private $generation_key = ''; - /** - * Make the HTTP call (Sync) - * - * @param string $resourcePath path to method endpoint - * @param string $method method to call - * @param array $queryParams parameters to be place in query URL - * @param array $postData parameters to be placed in POST body - * @param array $headerParams parameters to be place in request header - * @param string $responseType expected response type of the endpoint - * @param string $endpointPath path to method endpoint before expanding parameters - * - * @throws \BigCommerce\Api\v3\ApiException on a non 2xx response - * @return array - */ + /** + * Cache group identifier for WordPress caching. + * + * @var string + */ + private $cache_group = 'bigcommerce_api'; + + /** + * Cache generation key for versioning. + * + * @var string + */ + private $generation_key = ''; + + /** + * Perform an API call, utilizing caching for read operations. + * + * If the operation is a write, the cache generation key is updated to invalidate previous cache. + * For read operations, the cache is checked first before making an API request. + * + * @param string $resourcePath Path to the API endpoint. + * @param string $method HTTP method (e.g., GET, POST). + * @param array $queryParams Query parameters for the request. + * @param array $postData Data to include in the POST body. + * @param array $headerParams Headers to include in the request. + * @param string|null $responseType Expected response type (optional). + * @param string|null $endpointPath Endpoint path before parameter expansion (optional). + * + * @throws \BigCommerce\Api\v3\ApiException If a non-2xx response is received. + * @return array Response data from the API or cache. + */ public function callApi( $resourcePath, $method, $queryParams, $postData, $headerParams, $responseType = null, $endpointPath = null ) { if ( $this->is_write_operation( $resourcePath, $method, $queryParams, $postData ) ) { // any write operation increments the cache key diff --git a/src/BigCommerce/Api/Configuration.php b/src/BigCommerce/Api/Configuration.php index b7fd5e62..d53f2327 100644 --- a/src/BigCommerce/Api/Configuration.php +++ b/src/BigCommerce/Api/Configuration.php @@ -3,13 +3,22 @@ namespace BigCommerce\Api; - +/** + * Extends the base Configuration class to provide additional + * functionality, such as filtering default headers for BigCommerce API requests. + * + * This class allows developers to modify API behavior through WordPress filters. + * + * @package BigCommerce\Api + */ class Configuration extends \BigCommerce\Api\v3\Configuration { /** - * Gets the default header + * Retrieves the default headers for API requests. + * + * Allows modification of the headers via the `bigcommerce/api/default_headers` WordPress filter. * - * @return array An array of default header(s) + * @return array An array of default headers to be included with API requests. */ public function getDefaultHeaders() { /** diff --git a/src/BigCommerce/Api/ConfigurationRequiredException.php b/src/BigCommerce/Api/ConfigurationRequiredException.php index 2ae0f2f2..0e1f5f84 100644 --- a/src/BigCommerce/Api/ConfigurationRequiredException.php +++ b/src/BigCommerce/Api/ConfigurationRequiredException.php @@ -6,4 +6,14 @@ use BigCommerce\Api\v3\ApiException; +/** + * A specific exception type that extends `ApiException` to signal + * that a required configuration is missing when making API requests. + * + * This allows for more granular exception handling within the BigCommerce API SDK. + * + * @package BigCommerce\Api + * + * @extends \BigCommerce\Api\v3\ApiException + */ class ConfigurationRequiredException extends ApiException {} \ No newline at end of file diff --git a/src/BigCommerce/Api/Currencies_Api.php b/src/BigCommerce/Api/Currencies_Api.php index 6203ab21..e945b1b3 100644 --- a/src/BigCommerce/Api/Currencies_Api.php +++ b/src/BigCommerce/Api/Currencies_Api.php @@ -4,13 +4,28 @@ namespace BigCommerce\Api; /** - * Class Currencies_Api - * - * Get currencies from v2 api collection + * Handles retrieval of currencies from the BigCommerce v2 API. + * Provides a method to fetch and process a collection of currencies, + * returning their properties as an associative array. * * @package BigCommerce\Api + * @extends v2ApiAdapter */ class Currencies_Api extends v2ApiAdapter { + + /** + * Retrieve the list of currencies from the BigCommerce API. + * + * Fetches currencies from the `/currencies` endpoint and processes + * them into an array of associative arrays, each representing a currency + * and its updateable fields. + * + * @return array An array of currencies, where each currency is represented + * as an associative array of its properties. + * + * @throws \Exception Handles exceptions gracefully, returning an empty array + * if the API call fails. + */ public function get_currencies() { try { $currencies = array_map( function ( Resource $resource ) { diff --git a/src/BigCommerce/Api/Customer_Api.php b/src/BigCommerce/Api/Customer_Api.php index 788596bd..f004f213 100644 --- a/src/BigCommerce/Api/Customer_Api.php +++ b/src/BigCommerce/Api/Customer_Api.php @@ -4,17 +4,28 @@ namespace BigCommerce\Api; /** - * Class Customer_Api + * Provides methods for interacting with BigCommerce customers via the v2 API. + * Includes functionality for validating customer passwords and retrieving customer + * information by email address. * - * @method mixed updateCustomer( $customer_id, $profile ) + * @method mixed updateCustomer( int $customer_id, array $profile ) Updates a customer's profile. + * @package BigCommerce\Api + * @extends v2ApiAdapter */ class Customer_Api extends v2ApiAdapter { + /** - * @param int $customer_id - * @param string $password + * Validate a customer's password. + * + * Checks if the provided password matches the stored password for the given customer ID. + * Throws an exception if the customer ID does not exist. + * + * @param int $customer_id The ID of the customer to validate. + * @param string $password The password to validate. * - * @return bool - * @throws \InvalidArgumentException When the given customer ID does not exist in BigCommerce + * @return bool True if the password is valid, false otherwise. + * + * @throws \InvalidArgumentException If the customer ID is not found. */ public function validatePassword( $customer_id, $password ) { $path = sprintf( '/customers/%d/validate', $customer_id ); @@ -35,11 +46,14 @@ public function validatePassword( $customer_id, $password ) { } /** - * Find the customer ID associated with the given email address + * Find the customer ID associated with a given email address. + * + * Searches for a customer by email and returns their ID. Returns 0 if no customer + * is found or if an error occurs during the API request. * - * @param string $email + * @param string $email The email address to search for. * - * @return int The customer ID, 0 if not found + * @return int The customer ID if found, or 0 if not found or on failure. */ public function find_customer_id_by_email( $email ) { try { diff --git a/src/BigCommerce/Api/Marketing_Api.php b/src/BigCommerce/Api/Marketing_Api.php index 53355779..e42f17a3 100644 --- a/src/BigCommerce/Api/Marketing_Api.php +++ b/src/BigCommerce/Api/Marketing_Api.php @@ -6,16 +6,27 @@ use BigCommerce\Api\v3\ApiException; /** - * Class Marketing_Api + * Provides methods for interacting with marketing-related resources in BigCommerce, + * including gift certificates. * - * @method array getGiftCertificates( $filter = [] ) + * @method array getGiftCertificates( array $filter = [] ) Retrieve a list of gift certificates with optional filtering. + * + * @package BigCommerce\Api + * @extends v2ApiAdapter */ class Marketing_Api extends v2ApiAdapter { + /** - * @param $code + * Retrieve a gift certificate by its code. + * + * Searches for a gift certificate matching the given code and returns the resource if found. + * Throws an exception if no matching gift certificate is found. + * + * @param string $code The gift certificate code to search for. + * + * @return Resource The gift certificate resource object. * - * @return Resource - * @throws ApiException when the Gift Certificate cannot be retrieved + * @throws ApiException If no gift certificate matches the provided code, or if the API call fails. */ public function get_gift_certificate_by_code( $code ) { $response = $this->getGiftCertificates( [ diff --git a/src/BigCommerce/Api/Null_Client.php b/src/BigCommerce/Api/Null_Client.php index 3821f168..b5588d92 100644 --- a/src/BigCommerce/Api/Null_Client.php +++ b/src/BigCommerce/Api/Null_Client.php @@ -3,21 +3,34 @@ namespace BigCommerce\Api; +/** + * A placeholder API client that disables API calls. + * This class is typically used when API configuration is missing or incomplete. + * + * Attempts to make API calls using this client will throw an exception. + * + * @package BigCommerce\Api + * @extends Base_Client + */ class Null_Client extends Base_Client { /** - * (Doesn't) make the HTTP call (Sync) + * Attempt to make an API call. * - * @param string $resourcePath path to method endpoint - * @param string $method method to call - * @param array $queryParams parameters to be place in query URL - * @param array $postData parameters to be placed in POST body - * @param array $headerParams parameters to be place in request header - * @param string $responseType expected response type of the endpoint - * @param string $endpointPath path to method endpoint before expanding parameters + * This method always throws an exception because the client is configured to prevent API calls. + * It is intended to signal that required API configuration settings are missing. * - * @throws \BigCommerce\Api\v3\ApiException on a non 2xx response - * @return mixed + * @param string $resourcePath Path to the API method endpoint. + * @param string $method HTTP method to use for the request (e.g., GET, POST). + * @param array $queryParams Parameters to include in the query string of the URL. + * @param array $postData Parameters to include in the body of the request. + * @param array $headerParams Headers to include in the request. + * @param string|null $responseType The expected response type (optional). + * @param string|null $endpointPath The original endpoint path before parameter substitution (optional). + * + * @throws ConfigurationRequiredException Always thrown with a message indicating missing settings. + * + * @return mixed This method does not return a value; it always throws an exception. */ public function callApi( $resourcePath, $method, $queryParams, $postData, $headerParams, $responseType = null, $endpointPath = null ) { throw new ConfigurationRequiredException( __( 'Unable to connect to BigCommerce API. Missing required settings', 'bigcommerce' ) ); diff --git a/src/BigCommerce/Api/Payments_Api.php b/src/BigCommerce/Api/Payments_Api.php index 97e4546c..9c4694f7 100644 --- a/src/BigCommerce/Api/Payments_Api.php +++ b/src/BigCommerce/Api/Payments_Api.php @@ -3,16 +3,25 @@ namespace BigCommerce\Api; - +/** + * Provides methods for interacting with the Payments API in BigCommerce. + * Includes functionality to retrieve payment methods and count them with optional filters. + * + * @package BigCommerce\Api + * @extends v2ApiAdapter + */ class Payments_Api extends v2ApiAdapter { /** - * A temporary workaround because the API does not return a consistent - * data type for the /payments/methods endpoint + * Retrieve the count of available payment methods. + * + * This method counts payment methods returned from the `/payments/methods` endpoint. + * It includes a workaround for inconsistent data types in the API response. * - * @param bool $include_test_mode + * @param bool $include_test_mode Whether to include methods in test mode in the count. + * Defaults to `false`, which excludes test mode methods. * - * @return bool + * @return int|bool The number of payment methods, or `false` if the API response is empty or invalid. */ public function get_payment_methods_count( $include_test_mode = false ) { $connection = $this->getConnection(); @@ -34,6 +43,13 @@ public function get_payment_methods_count( $include_test_mode = false ) { return count( $response ); } + /** + * Retrieve all available payment methods. + * + * This method fetches the collection of payment methods from the `/payments/methods` endpoint. + * + * @return array An array of payment method resources. + */ public function get_payment_methods() { return $this->getCollection( '/payments/methods' ); } diff --git a/src/BigCommerce/Api/Request_Headers.php b/src/BigCommerce/Api/Request_Headers.php index cb81f65c..2016572e 100644 --- a/src/BigCommerce/Api/Request_Headers.php +++ b/src/BigCommerce/Api/Request_Headers.php @@ -6,12 +6,24 @@ use BigCommerce\Plugin; +/** + * Provides functionality for adding custom headers to API requests, including plugin-specific + * information like WordPress version, plugin version, and PHP version. + * + * @package BigCommerce\Api + */ class Request_Headers { /** - * @param array $headers + * Add plugin-related information to the request headers. + * + * This method adds additional headers containing details about the client type, client version, + * plugin version, and PHP version to the provided headers array. + * + * @param array $headers The existing array of request headers to which plugin info will be added. + * + * @return array The updated array of headers with added plugin information. * - * @return array * @filter bigcommerce/api/default_headers */ public function add_plugin_info_headers( $headers ) { diff --git a/src/BigCommerce/Api/Shipping_Api.php b/src/BigCommerce/Api/Shipping_Api.php index 74dbca66..d149a3e1 100644 --- a/src/BigCommerce/Api/Shipping_Api.php +++ b/src/BigCommerce/Api/Shipping_Api.php @@ -4,28 +4,33 @@ namespace BigCommerce\Api; /** - * Class Shipping_Api - * - * Handle api v2 request for shipping data: zones, methods + * Handles API v2 requests for shipping data, including zones and shipping methods. + * Provides methods to fetch available shipping zones, count shipping methods, + * and retrieve shipping methods by zone. * * @package BigCommerce\Api */ class Shipping_Api extends v2ApiAdapter { - /** - * Get shipping zones - * - * @return array - */ + /** + * Get shipping zones. + * + * This method retrieves the list of shipping zones configured in the BigCommerce store. + * + * @return array An array of shipping zones. + */ public function get_zones() { return $this->getCollection( '/shipping/zones', 'ShippingZone' ); } - /** - * Get count of available shipping methods - * - * @return float|int - */ + /** + * Get the count of available shipping methods. + * + * This method retrieves all shipping zones and counts the available shipping methods + * for each zone. If any errors occur during the retrieval process, it returns 0. + * + * @return int|float The total count of shipping methods available across all zones. + */ public function count_shipping_methods() { try { $zones = $this->get_zones(); @@ -43,13 +48,15 @@ public function count_shipping_methods() { return array_sum( array_map( 'count', $methods ) ); } - /** - * Retrieve the list of available shipping methods by zone_id - * - * @param $zone_id - * - * @return array - */ + /** + * Retrieve the list of available shipping methods by zone ID. + * + * This method retrieves the list of shipping methods for a specific shipping zone. + * + * @param int $zone_id The ID of the shipping zone for which to retrieve methods. + * + * @return array An array of shipping methods for the specified zone. + */ public function get_shipping_methods( $zone_id ) { return $this->getCollection( sprintf( '/shipping/zones/%d/methods', $zone_id ) ) ?: []; } diff --git a/src/BigCommerce/Api/Store_Api.php b/src/BigCommerce/Api/Store_Api.php index 5ed33c55..c5687301 100644 --- a/src/BigCommerce/Api/Store_Api.php +++ b/src/BigCommerce/Api/Store_Api.php @@ -7,25 +7,25 @@ use Firebase\JWT\JWT; /** - * Class Store_Api - * - * Handle retrieving information about store from APIv2 + * Handle retrieving information about the store from APIv2. * * @package BigCommerce\Api */ class Store_Api extends v2ApiAdapter { /** - * Get customr login token by id + * Get customer login token by ID. * - * @param $id - * @param string $redirectUrl - * @param string $requestIp - * @param int $channel_id + * This method generates a JWT token to allow a customer to log in. The token can + * be used to authenticate the customer in future API requests. * - * @return string + * @param int $id The ID of the customer. + * @param string $redirectUrl Optional URL to redirect the customer after login. + * @param string $requestIp Optional IP address of the requestor. + * @param int $channel_id Optional channel ID for the customer login. * - * @throws \Exception + * @return string The generated JWT login token. + * @throws \Exception If the client secret is missing or other errors occur. */ public function getCustomerLoginToken( $id, $redirectUrl = '', $requestIp = '', $channel_id = 0 ) { $config = $this->apiClient->getConfig(); @@ -94,9 +94,11 @@ private function update_server_time() { } /** - * Return the list of store analytics settings + * Return the list of store analytics settings. + * + * This method retrieves the store's analytics settings, such as tracking options. * - * @return array|array[] + * @return array The store's analytics settings. */ public function get_analytics_settings() { try { @@ -116,12 +118,15 @@ public function get_analytics_settings() { } /** - * Update store analytics setting by id + * Update store analytics setting by ID. + * + * This method updates the analytics settings for a given store using the provided + * settings array. * - * @param $id - * @param array $settings + * @param int $id The ID of the analytics setting to update. + * @param array $settings The new settings for the store. * - * @return bool + * @return bool True if the update was successful, false otherwise. */ public function update_analytics_settings( $id, array $settings ) { try { @@ -137,11 +142,13 @@ public function update_analytics_settings( $id, array $settings ) { } } - /** - * Check if site wide https option is enabled in BC - * - * @return bool - */ + /** + * Check if site-wide HTTPS option is enabled in BigCommerce. + * + * This method checks if the site-wide HTTPS option is enabled for the store. + * + * @return bool True if HTTPS is enabled, false otherwise. + */ public function get_sitewidehttps_enabled() { $resource = $this->get_store_resource(); @@ -154,11 +161,13 @@ public function get_sitewidehttps_enabled() { return ! empty( $resource ) ? $resource->sitewidehttps_enabled : false; } - /** - * Get store domain - * - * @return bool - */ + /** + * Get store domain. + * + * This method retrieves the domain name associated with the store. + * + * @return bool The domain name of the store if available, otherwise false. + */ public function get_domain() { $resource = $this->get_store_resource(); @@ -169,14 +178,16 @@ public function get_domain() { return $this->store_resource_exists( $resource, 'domain' ); } - /** - * Check whether the provided resource exists - * - * @param $resource - * @param $property - * - * @return bool - */ + /** + * Check whether the provided resource exists. + * + * This method checks if a specific property exists in a given resource. + * + * @param mixed $resource The resource object to check. + * @param string $property The property name to check for. + * + * @return bool True if the property exists in the resource, false otherwise. + */ public function store_resource_exists( $resource, $property) { if ( empty( $resource ) ) { return false; @@ -185,11 +196,13 @@ public function store_resource_exists( $resource, $property) { return $resource->{$property}; } - /** - * Get store resource - * - * @return false|Resource - */ + /** + * Get store resource. + * + * This method retrieves the store resource containing details about the store. + * + * @return false|Resource The store resource, or false if an error occurs. + */ public function get_store_resource() { try { return $this->getResource( '/store' ); diff --git a/src/BigCommerce/Api/Tax_Class_Api.php b/src/BigCommerce/Api/Tax_Class_Api.php index a03cea7b..809676f3 100644 --- a/src/BigCommerce/Api/Tax_Class_Api.php +++ b/src/BigCommerce/Api/Tax_Class_Api.php @@ -4,17 +4,20 @@ namespace BigCommerce\Api; /** - * Class Tax_Class_Api + * Handle tax data requests. * - * Handle tax data requests + * This class provides methods for interacting with the BigCommerce API to retrieve tax class data. * * @package BigCommerce\Api */ class Tax_Class_Api extends v2ApiAdapter { + /** - * Retrieve tax classes from BC + * Retrieve tax classes from BigCommerce. * - * @return array + * This method fetches a collection of tax classes available in the BigCommerce store. + * + * @return array A list of tax classes. */ public function get_tax_classes() { return $this->getCollection( '/tax_classes', 'TaxClass' ); diff --git a/src/BigCommerce/Api/Webhooks_Api.php b/src/BigCommerce/Api/Webhooks_Api.php index c93fd35c..38318002 100644 --- a/src/BigCommerce/Api/Webhooks_Api.php +++ b/src/BigCommerce/Api/Webhooks_Api.php @@ -1,25 +1,64 @@ client_class, 'listWebhooks' ] ); } + /** + * Create a new webhook. + * + * Creates a new webhook by calling the client class's `createWebhook` method. + * + * @param mixed $object The webhook object to create. + * + * @return mixed The result of the create operation. + */ public function createWebhook( $object ) { return call_user_func( [ $this->client_class, 'createWebhook' ], $object ); } + /** + * Delete a webhook by ID. + * + * Deletes the specified webhook by calling the client class's `deleteWebhook` method. + * + * @param int $id The ID of the webhook to delete. + * + * @return mixed The result of the delete operation. + */ public function deleteWebhook( $id ) { return call_user_func( [ $this->client_class, 'deleteWebhook' ], $id ); } + /** + * Update an existing webhook. + * + * Updates the specified webhook by calling the client class's `updateWebhook` method. + * + * @param int $id The ID of the webhook to update. + * @param mixed $object The updated webhook data. + * + * @return mixed The result of the update operation. + */ public function updateWebhook( $id, $object ) { return call_user_func( [ $this->client_class, 'updateWebhook' ], $id, $object ); } diff --git a/src/BigCommerce/Api/v2ApiAdapter.php b/src/BigCommerce/Api/v2ApiAdapter.php index 7266e087..be1192dd 100644 --- a/src/BigCommerce/Api/v2ApiAdapter.php +++ b/src/BigCommerce/Api/v2ApiAdapter.php @@ -1,31 +1,45 @@ apiClient = $apiClient; } + /** + * Magic method to call methods on the client class. + * + * Dynamically calls methods on the client class if available. Throws an exception if the method does not exist. + * + * @param string $method The method name to call. + * @param array $args The arguments to pass to the method. + * + * @return mixed The result of the method call. + * + * @throws \BadMethodCallException If the method is not found. + */ public function __call( $method, $args ) { if ( is_callable( [ $this->client_class, $method ] ) ) { return call_user_func_array( [ $this->client_class, $method ], $args ); @@ -33,6 +47,13 @@ public function __call( $method, $args ) { throw new \BadMethodCallException( sprintf( 'Unknown method: %s', $method ) ); } + /** + * Retrieve the store hash from the API client configuration. + * + * Extracts the store hash from the API client's configuration using the host URL. + * + * @return string The store hash. + */ protected function get_store_hash() { $config = $this->apiClient->getConfig(); $host = $config->getHost(); diff --git a/src/BigCommerce/Assets/Admin/JS_Config.php b/src/BigCommerce/Assets/Admin/JS_Config.php index 3cf52b70..fb1bc7a9 100644 --- a/src/BigCommerce/Assets/Admin/JS_Config.php +++ b/src/BigCommerce/Assets/Admin/JS_Config.php @@ -12,15 +12,38 @@ use BigCommerce\Taxonomies\Flag\Flag; use BigCommerce\Taxonomies\Product_Category\Product_Category; + +/** + * Handles the configuration for JavaScript assets in the BigCommerce admin. + * This includes paths to images and icons, as well as various settings related + * to product categories, flags, brands, and AJAX actions used in the admin interface. + * + * @package BigCommerce\Assets\Admin + */ class JS_Config { private $data; private $gutenberg; private $directory; + /** + * Constructor + * + * Initializes the JS_Config object with a specified asset directory. + * + * @param string $asset_directory The directory containing the assets. + */ public function __construct( $asset_directory ) { $this->directory = trailingslashit( $asset_directory ); } + /** + * Get JS configuration data + * + * Retrieves the JavaScript configuration data, including paths for images and icons, + * as well as other relevant settings such as product categories and AJAX actions. + * + * @return array The JavaScript configuration data. + */ public function get_data() { if ( ! isset( $this->data ) ) { $this->data = [ @@ -46,6 +69,8 @@ public function get_data() { /** * Filters admin js config object. * + * Allows modification of the JS configuration data before it is returned. + * * @param array $data Js config data. */ $this->data = apply_filters( 'bigcommerce/admin/js_config', $this->data ); @@ -54,6 +79,13 @@ public function get_data() { return $this->data; } + /** + * Get Gutenberg JS configuration data + * + * Retrieves the Gutenberg-specific JavaScript configuration data. + * + * @return array The Gutenberg JavaScript configuration data. + */ public function get_gutenberg_data() { if ( ! isset( $this->gutenberg ) ) { $this->gutenberg = []; @@ -61,6 +93,8 @@ public function get_gutenberg_data() { /** * Filters gutenberg js config data. * + * Allows modification of the Gutenberg-specific JS configuration data. + * * @param array $gutenberg Js config data. */ $this->gutenberg = apply_filters( 'bigcommerce/gutenberg/js_config', $this->gutenberg ); diff --git a/src/BigCommerce/Assets/Admin/JS_Localization.php b/src/BigCommerce/Assets/Admin/JS_Localization.php index 27e3466b..287035a7 100644 --- a/src/BigCommerce/Assets/Admin/JS_Localization.php +++ b/src/BigCommerce/Assets/Admin/JS_Localization.php @@ -1,12 +1,19 @@ directory = trailingslashit( $asset_directory ); - $this->version = $version; - $this->config = $config; - $this->localization = $localization; - } - - /** - * @action admin_enqueue_scripts - */ - public function enqueue_scripts() { - $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; - - $manifest_scripts = $debug ? 'manifest.js' : 'manifest.min.js'; - $vendor_scripts = $debug ? 'vendor.js' : 'vendor.min.js'; - $admin_scripts = $debug ? 'scripts.js' : 'scripts.min.js'; - $gutenberg_scripts = $debug ? 'scripts.js' : 'scripts.min.js'; - - $manifest_src = $this->directory . 'js/dist/admin/' . $manifest_scripts; - $vendor_src = $this->directory . 'js/dist/admin/' . $vendor_scripts; - $admin_src = $this->directory . 'js/dist/admin/' . $admin_scripts; - $gutenberg_src = $this->directory . 'js/dist/admin/gutenberg/' . $gutenberg_scripts; - - wp_register_script( 'bigcommerce-admin-manifest', $manifest_src, [ - 'wp-util', - 'media-upload', - 'media-views', - ], $this->version, true ); - wp_register_script( 'bigcommerce-admin-vendors', $vendor_src, [ 'bigcommerce-admin-manifest' ], $this->version, true ); - wp_register_script( 'bigcommerce-admin-scripts', $admin_src, [ 'bigcommerce-admin-vendors', 'wp-i18n' ], $this->version, true ); - wp_register_script( 'bigcommerce-gutenberg-scripts', $gutenberg_src, [ - 'wp-i18n', - 'wp-block-editor', - 'wp-element', - 'wp-blocks', - 'wp-plugins', - 'wp-components', - 'bigcommerce-admin-scripts', - ], $this->version, false ); - add_action( 'admin_print_scripts-post.php', function() { - wp_add_inline_script( 'wp-edit-post', 'window._wpLoadBlockEditor.then( window.bigcommerce_gutenberg_config.initPlugins() );' ); - }); - - wp_localize_script( 'bigcommerce-admin-scripts', 'bigcommerce_admin_config', $this->config->get_data() ); - wp_localize_script( 'bigcommerce-admin-scripts', 'bigcommerce_admin_i18n', $this->localization->get_data() ); - wp_localize_script( 'bigcommerce-gutenberg-scripts', 'bigcommerce_gutenberg_config', $this->config->get_gutenberg_data() ); - - /* - * Rather than enqueuing this immediately, delay until after - * admin_print_footer_scripts:50. This is when the WP visual - * editor prints the tinymce config. - */ - add_action( 'admin_print_footer_scripts', [ $this, 'print_footer_scripts' ], 60, 0 ); - } - - /** - * @action admin_print_footer_scripts - */ - public function print_footer_scripts() { - // do not enqueue gutenberg scripts - - wp_enqueue_script( 'bigcommerce-admin-scripts' ); - - // since footer scripts have already printed, process the queue again on the next available action - add_action( "admin_footer-" . $GLOBALS[ 'hook_suffix' ], '_wp_footer_scripts' ); - } + + /** + * @var string $directory Path to the plugin assets directory. + */ + private $directory; + + /** + * @var string $version The asset build version. + */ + private $version; + + /** + * @var JS_Config $config Configuration for JavaScript. + */ + private $config; + + /** + * @var JS_Localization $localization Localization data for JavaScript. + */ + private $localization; + + /** + * Constructor. + * + * @param string $asset_directory Path to the plugin assets directory. + * @param string $version Asset build version. + * @param JS_Config $config Configuration object for JavaScript. + * @param JS_Localization $localization Localization object for JavaScript. + */ + public function __construct( $asset_directory, $version, JS_Config $config, JS_Localization $localization ) { + $this->directory = trailingslashit( $asset_directory ); + $this->version = $version; + $this->config = $config; + $this->localization = $localization; + } + + /** + * Enqueue admin and Gutenberg scripts. + * + * Registers and enqueues required scripts, and localizes them with configuration + * and localization data. Delays certain script outputs until after the admin footer scripts. + */ + public function enqueue_scripts() { + $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; + + $manifest_scripts = $debug ? 'manifest.js' : 'manifest.min.js'; + $vendor_scripts = $debug ? 'vendor.js' : 'vendor.min.js'; + $admin_scripts = $debug ? 'scripts.js' : 'scripts.min.js'; + $gutenberg_scripts = $debug ? 'scripts.js' : 'scripts.min.js'; + + $manifest_src = $this->directory . 'js/dist/admin/' . $manifest_scripts; + $vendor_src = $this->directory . 'js/dist/admin/' . $vendor_scripts; + $admin_src = $this->directory . 'js/dist/admin/' . $admin_scripts; + $gutenberg_src = $this->directory . 'js/dist/admin/gutenberg/' . $gutenberg_scripts; + + wp_register_script( 'bigcommerce-admin-manifest', $manifest_src, [ + 'wp-util', + 'media-upload', + 'media-views', + ], $this->version, true ); + wp_register_script( 'bigcommerce-admin-vendors', $vendor_src, [ 'bigcommerce-admin-manifest' ], $this->version, true ); + wp_register_script( 'bigcommerce-admin-scripts', $admin_src, [ 'bigcommerce-admin-vendors', 'wp-i18n' ], $this->version, true ); + wp_register_script( 'bigcommerce-gutenberg-scripts', $gutenberg_src, [ + 'wp-i18n', + 'wp-block-editor', + 'wp-element', + 'wp-blocks', + 'wp-plugins', + 'wp-components', + 'bigcommerce-admin-scripts', + ], $this->version, false ); + + add_action( 'admin_print_scripts-post.php', function() { + wp_add_inline_script( 'wp-edit-post', 'window._wpLoadBlockEditor.then( window.bigcommerce_gutenberg_config.initPlugins() );' ); + }); + + wp_localize_script( 'bigcommerce-admin-scripts', 'bigcommerce_admin_config', $this->config->get_data() ); + wp_localize_script( 'bigcommerce-admin-scripts', 'bigcommerce_admin_i18n', $this->localization->get_data() ); + wp_localize_script( 'bigcommerce-gutenberg-scripts', 'bigcommerce_gutenberg_config', $this->config->get_gutenberg_data() ); + + add_action( 'admin_print_footer_scripts', [ $this, 'print_footer_scripts' ], 60, 0 ); + add_action( 'admin_print_footer_scripts', [ $this, 'print_footer_scripts' ], 60, 0 ); + } + + /** + * Print footer scripts. + * + * Enqueues the admin scripts and reprocesses the script queue + * to ensure correct execution timing. + */ + public function print_footer_scripts() { + // Do not enqueue Gutenberg scripts. + + wp_enqueue_script( 'bigcommerce-admin-scripts' ); + + add_action( "admin_footer-" . $GLOBALS['hook_suffix'], '_wp_footer_scripts' ); + } } diff --git a/src/BigCommerce/Assets/Admin/Styles.php b/src/BigCommerce/Assets/Admin/Styles.php index 1eb623d4..75837742 100644 --- a/src/BigCommerce/Assets/Admin/Styles.php +++ b/src/BigCommerce/Assets/Admin/Styles.php @@ -1,38 +1,55 @@ directory = trailingslashit( $asset_directory ); - $this->version = $version; - } - - /** - * @action admin_enqueue_scripts - */ - public function enqueue_styles() { - $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; - - $css_file = $debug ? 'bc-admin.css' : 'bc-admin.min.css'; - $gutenberg_css_file = $debug ? 'bc-gutenberg.css' : 'bc-gutenberg.min.css'; - - $css_src = $this->directory . 'css/' . $css_file; - $gutenberg_css_src = $this->directory . 'css/' . $gutenberg_css_file; - - wp_enqueue_style( 'bigcommerce-admin-styles', $css_src, [], $this->version ); - wp_enqueue_style( 'bigcommerce-gutenberg-admin-styles', $gutenberg_css_src, [], $this->version ); - } + /** + * @var string Path to the plugin assets directory. + */ + private $directory; + + /** + * @var string The asset build version. + */ + private $version; + + /** + * Constructor. + * + * Initializes the class with the provided directory path and version. + * + * @param string $asset_directory Path to the plugin assets directory. + * @param string $version Asset build version. + */ + public function __construct( $asset_directory, $version ) { + $this->directory = trailingslashit( $asset_directory ); + $this->version = $version; + } + + /** + * Enqueue admin and Gutenberg styles. + * + * Registers and enqueues the required CSS styles for the BigCommerce admin panel + * and Gutenberg editor. The styles are minified for production, with debug support + * for unminified versions. + * + * @action admin_enqueue_scripts + */ + public function enqueue_styles() { + $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; + + $css_file = $debug ? 'bc-admin.css' : 'bc-admin.min.css'; + $gutenberg_css_file = $debug ? 'bc-gutenberg.css' : 'bc-gutenberg.min.css'; + + $css_src = $this->directory . 'css/' . $css_file; + $gutenberg_css_src = $this->directory . 'css/' . $gutenberg_css_file; + + wp_enqueue_style( 'bigcommerce-admin-styles', $css_src, [], $this->version ); + wp_enqueue_style( 'bigcommerce-gutenberg-admin-styles', $gutenberg_css_src, [], $this->version ); + } } \ No newline at end of file diff --git a/src/BigCommerce/Assets/Theme/Image_Sizes.php b/src/BigCommerce/Assets/Theme/Image_Sizes.php index a0d90219..d0c5872e 100644 --- a/src/BigCommerce/Assets/Theme/Image_Sizes.php +++ b/src/BigCommerce/Assets/Theme/Image_Sizes.php @@ -1,67 +1,144 @@ [ - 'width' => 86, - 'height' => 86, - 'crop' => true, - ], - self::BC_THUMB_LARGE => [ - 'width' => 167, - 'height' => 167, - 'crop' => true, - ], - self::BC_SMALL => [ - 'width' => 270, - 'height' => 270, - 'crop' => true, - ], - self::BC_MEDIUM => [ - 'width' => 370, - 'height' => 370, - 'crop' => true, - ], - self::BC_EXTRA_MEDIUM => [ - 'width' => 960, - 'height' => 960, - 'crop' => true, - ], - self::BC_LARGE => [ - 'width' => 1280, - 'height' => 1280, - 'crop' => true, - ], - self::BC_CATEGORY_IMAGE => [ - 'width' => 1600, - 'height' => 0, - 'crop' => false, - ], - ]; + /** + * List of custom image sizes, each defined by width, height, and cropping settings. + * + * The size array defines different image sizes, including thumbnail, small, medium, + * large, and category images. The cropping property determines whether the image should + * be cropped to fit the dimensions or not. + * + * @var array + */ + private $sizes = [ + self::BC_THUMB => [ + 'width' => 86, + 'height' => 86, + 'crop' => true, + ], + self::BC_THUMB_LARGE => [ + 'width' => 167, + 'height' => 167, + 'crop' => true, + ], + self::BC_SMALL => [ + 'width' => 270, + 'height' => 270, + 'crop' => true, + ], + self::BC_MEDIUM => [ + 'width' => 370, + 'height' => 370, + 'crop' => true, + ], + self::BC_EXTRA_MEDIUM => [ + 'width' => 960, + 'height' => 960, + 'crop' => true, + ], + self::BC_LARGE => [ + 'width' => 1280, + 'height' => 1280, + 'crop' => true, + ], + self::BC_CATEGORY_IMAGE => [ + 'width' => 1600, + 'height' => 0, + 'crop' => false, + ], + ]; - /** - * @return void - * @action after_setup_theme - */ - public function register_sizes() { - foreach ( $this->sizes as $key => $attributes ) { - add_image_size( $key, $attributes['width'], $attributes['height'], $attributes['crop'] ); - } - } + /** + * Registers custom image sizes with WordPress. + * + * This method loops through the defined image sizes and registers each one using + * the `add_image_size` function. The sizes are registered when the theme is set up. + * + * @return void + * @action after_setup_theme + */ + public function register_sizes() { + foreach ( $this->sizes as $key => $attributes ) { + add_image_size( $key, $attributes['width'], $attributes['height'], $attributes['crop'] ); + } + } } diff --git a/src/BigCommerce/Assets/Theme/JS_Config.php b/src/BigCommerce/Assets/Theme/JS_Config.php index 2a4a5551..ea755221 100644 --- a/src/BigCommerce/Assets/Theme/JS_Config.php +++ b/src/BigCommerce/Assets/Theme/JS_Config.php @@ -7,27 +7,55 @@ use BigCommerce\Taxonomies\Channel\Connections; use BigCommerce\Settings\Sections\Currency; +/** + * Handles the configuration for JavaScript data, which includes store settings, + * product messages, channel data, and other theme-specific data required for the frontend. + * + * @package BigCommerce\Assets\Theme + */ class JS_Config { /** - * @var array + * @var array $data Configuration data for JavaScript. + * + * Contains various data elements that will be used in JavaScript files, such as store domain, + * product availability messages, channel data, and currency information. */ private $data; /** - * @var string + * @var string $directory Path to the asset directory for the theme. + * + * This directory is used to locate various assets like images to be referenced in JavaScript. */ private $directory; /** - * @var Connections + * @var Connections $connections An instance of the Connections class to fetch the current channel data. + * + * This is used to retrieve the current active channel and its relevant data for JavaScript configuration. */ private $connections; + /** + * JS_Config constructor. + * + * @param string $asset_directory The directory path where theme assets are stored. + * @param Connections $connections The Connections object used to get channel-related data. + */ public function __construct( $asset_directory, $connections ) { $this->directory = trailingslashit( $asset_directory ); $this->connections = $connections; } + /** + * Retrieves the configuration data for JavaScript. + * + * This method fetches the data used in JavaScript files, including store domain, product messages, + * channel data, currency information, and the logout URL. If the data has already been generated, + * it returns the cached version. + * + * @return array The configuration data for JavaScript. + */ public function get_data() { if ( ! isset( $this->data ) ) { $this->data = [ diff --git a/src/BigCommerce/Assets/Theme/JS_Localization.php b/src/BigCommerce/Assets/Theme/JS_Localization.php index 587de8e1..b02c03ff 100644 --- a/src/BigCommerce/Assets/Theme/JS_Localization.php +++ b/src/BigCommerce/Assets/Theme/JS_Localization.php @@ -5,13 +5,21 @@ use BigCommerce\Templates\Cart_Empty; +/** + * Handles the localization of JavaScript strings for the theme. This class generates an array of text + * strings used in JavaScript, which can be filtered and sanitized before being passed to the frontend. + * + * @package BigCommerce\Assets\Theme + */ class JS_Localization { /** - * stores all text strings needed in the admin scripts.js file + * Generates the localization data for JavaScript. * - * The code below is an example of structure. Check the readme js section for more info on how to use. + * This method returns an array of text strings that are used in various parts of the frontend, + * including cart messages, account actions, and error handling. The strings are internationalized + * and can be filtered using WordPress hooks. * - * @return array + * @return array The localization data for JavaScript. */ public function get_data() { $empty_cart_data = Cart_Empty::factory()->get_data(); diff --git a/src/BigCommerce/Assets/Theme/Scripts.php b/src/BigCommerce/Assets/Theme/Scripts.php index 5015b390..dfea8472 100644 --- a/src/BigCommerce/Assets/Theme/Scripts.php +++ b/src/BigCommerce/Assets/Theme/Scripts.php @@ -6,6 +6,12 @@ use BigCommerce\Pages\Checkout_Page; +/** + * Manages the enqueuing of JavaScript files for the theme. It handles the inclusion of asset files, + * conditional script loading based on page type, and localization of JavaScript data. + * + * @package BigCommerce\Assets\Theme + */ class Scripts { /** * @var string Path to the plugin assets directory @@ -27,6 +33,16 @@ class Scripts { */ private $localization; + /** + * Scripts constructor. + * + * Initializes the Scripts class with the asset directory, version, and necessary dependencies. + * + * @param string $asset_directory The path to the plugin assets directory. + * @param string $version The version of the asset build. + * @param JS_Config $config The JS_Config object for configuration data. + * @param JS_Localization $localization The JS_Localization object for localized strings. + */ public function __construct( $asset_directory, $version, JS_Config $config, JS_Localization $localization ) { $this->directory = trailingslashit( $asset_directory ); $this->version = $version; @@ -35,7 +51,11 @@ public function __construct( $asset_directory, $version, JS_Config $config, JS_L } /** - * Enqueue scripts + * Enqueues JavaScript files for the frontend. + * + * This method registers and enqueues the necessary JavaScript files for the theme, including + * manifest, vendor, and plugin scripts. It also conditionally loads the BigCommerce checkout SDK + * if the current page is the checkout page. * * @action wp_enqueue_scripts */ diff --git a/src/BigCommerce/Assets/Theme/Styles.php b/src/BigCommerce/Assets/Theme/Styles.php index eb77c17c..bcfd3a7a 100644 --- a/src/BigCommerce/Assets/Theme/Styles.php +++ b/src/BigCommerce/Assets/Theme/Styles.php @@ -1,11 +1,16 @@ directory = trailingslashit( $asset_directory ); $this->version = $version; } /** + * Enqueues the CSS styles for the frontend. + * + * This method registers and enqueues the main stylesheet, allowing for customization of the + * stylesheet filename through filters. It also conditionally loads the stylesheet based on + * the theme settings (e.g., whether the full CSS file should be loaded). + * * @action wp_enqueue_scripts */ public function enqueue_styles() { diff --git a/src/BigCommerce/Banners/Banners.php b/src/BigCommerce/Banners/Banners.php index 96883c30..7cb8665f 100644 --- a/src/BigCommerce/Banners/Banners.php +++ b/src/BigCommerce/Banners/Banners.php @@ -9,32 +9,93 @@ use BigCommerce\Customizer\Sections\Banners as Banners_Settings; use BigCommerce\Customizer\Sections\Colors; - +/** + * Handles the management and display of banners on various pages of the BigCommerce WordPress theme. It + * provides methods to configure JavaScript settings, fetch banners from the API, and filter banners based + * on the current page context, visibility, and date range. + * + * @package BigCommerce\Banners + */ class Banners { + /** + * Cache key for storing banners data. + * + * @var string + */ const CACHE = 'bigcommerce_banners'; + + /** + * Time-to-live (TTL) for banner cache in seconds. + * + * @var int + */ const CACHE_TTL = '3600'; + /** + * Page type for the home page. + * + * @var string + */ const PAGE_HOME = 'home_page'; + + /** + * Page type for the product category page. + * + * @var string + */ const PAGE_CATEGORY = 'category_page'; + + /** + * Page type for the brand page. + * + * @var string + */ const PAGE_BRAND = 'brand_page'; + + /** + * Page type for the search page. + * + * @var string + */ const PAGE_SEARCH = 'search_page'; + + /** + * Constant used to define custom date ranges for banners. + * + * @var string + */ const DATE_TYPE_CUSTOM = 'custom'; + /** + * @var object The banners API instance used to fetch banners. + */ private $banners_api; + /** + * Banners constructor. + * + * Initializes the Banners class with a banners API instance. + * + * @param object $banners_api The banners API instance. + */ public function __construct( $banners_api ) { $this->banners_api = $banners_api; } /** - * @param array $config + * Adds banner configuration to the JS config. + * + * This method adds the banner settings, including background color, text color, and the context-based + * banners, to the JavaScript configuration. The configuration is later localized in the theme. * - * @return array + * @param array $config The current JavaScript configuration. + * + * @return array The modified JavaScript configuration. * @filter bigcommerce/js_config */ public function js_config( $config ) { - $config[ 'banners' ] = [ + $config['banners'] = [ 'bg_color' => get_theme_mod( Colors::BANNER_COLOR, Colors::COLOR_BANNER_GREY ), 'text_color' => get_theme_mod( Colors::BANNER_TEXT, Colors::COLOR_WHITE ), 'items' => $this->get_context_banners(), @@ -44,9 +105,13 @@ public function js_config( $config ) { } /** - * Get banners for the current contenxt - * - * @return array + * Retrieves banners for the current page context. + * + * This method filters banners based on the current page type (home, category, brand, search), visibility, + * and any custom date ranges that are defined for each banner. Only banners that match the current context + * will be returned. + * + * @return array The filtered list of banners for the current context. */ public function get_context_banners() { $enable_banners = get_option( Banners_Settings::ENABLE_BANNERS, false ) === 'yes'; @@ -61,7 +126,7 @@ public function get_context_banners() { $queried_object = get_queried_object(); $bc_id = 0; - if ( is_a( $queried_object, 'WP_Term' ) && in_array( $page, [ self::PAGE_CATEGORY, self::PAGE_BRAND ]) ) { + if ( is_a( $queried_object, 'WP_Term' ) && in_array( $page, [ self::PAGE_CATEGORY, self::PAGE_BRAND ] ) ) { $bc_id = (int) get_term_meta( $queried_object->term_id, 'bigcommerce_id', true ); } @@ -76,7 +141,7 @@ public function get_context_banners() { if ( $banner['date_type'] === self::DATE_TYPE_CUSTOM ) { $in_range = $current_date >= $banner['date_from'] && $current_date <= $banner['date_to']; - if ( ! $in_range ) { + if ( ! $in_range ) { return false; } } @@ -88,9 +153,12 @@ public function get_context_banners() { } /** - * Get banners - * - * @return array + * Fetches banners from the banners API. + * + * This method checks for cached banners and fetches them from the API if they are not already cached. + * The fetched banners are stored in the WordPress transient cache for future use. + * + * @return array The list of banners retrieved from the API or cache. */ public function get_banners() { $cache = get_transient( self::CACHE ); @@ -101,7 +169,7 @@ public function get_banners() { try { $banners = $this->banners_api->get_banners(); - } catch (\Throwable $th) { + } catch ( \Throwable $th ) { $banners = []; } @@ -111,7 +179,12 @@ public function get_banners() { } /** - * @return string + * Determines the current page type. + * + * This method checks the WordPress environment to determine the type of page being viewed + * (home, category, brand, search) and returns the corresponding page type constant. + * + * @return string The current page type constant (e.g., 'home_page', 'category_page'). */ private function get_current_page() { if ( is_front_page() ) { diff --git a/src/BigCommerce/CLI/Command.php b/src/BigCommerce/CLI/Command.php index 3861cbff..ba30adec 100644 --- a/src/BigCommerce/CLI/Command.php +++ b/src/BigCommerce/CLI/Command.php @@ -5,25 +5,73 @@ use WP_CLI; +/** + * This is an abstract base class for creating custom WP-CLI commands in the BigCommerce CLI namespace. + * It registers the command with WP-CLI and provides methods for handling command-specific logic. + * + * @package BigCommerce\CLI + */ abstract class Command extends \WP_CLI_Command { - public function register() { - if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { - return; - } + /** + * Register the command with WP-CLI. + * + * This method checks if WP-CLI is defined and active. If so, it registers the command + * with WP-CLI, using the specific command name defined in the child class. + * + * @return void + */ + public function register() { + if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { + return; + } - WP_CLI::add_command( 'bigcommerce ' . $this->command(), [ $this, 'run' ], [ - 'shortdesc' => $this->description(), - 'synopsis' => $this->arguments(), - ] ); - } + WP_CLI::add_command( 'bigcommerce ' . $this->command(), [ $this, 'run' ], [ + 'shortdesc' => $this->description(), + 'synopsis' => $this->arguments(), + ] ); + } - abstract protected function command(); + /** + * Get the command name. + * + * This method must be implemented in the child class to return the specific command name. + * + * @return string The name of the WP-CLI command. + */ + abstract protected function command(); - abstract protected function description(); + /** + * Get a short description of the command. + * + * This method must be implemented in the child class to provide a brief description + * of the command's functionality, which will be shown in the WP-CLI help output. + * + * @return string The short description of the command. + */ + abstract protected function description(); - abstract protected function arguments(); + /** + * Get the command arguments. + * + * This method must be implemented in the child class to return the arguments + * required by the command. The arguments will be shown in the WP-CLI help output. + * + * @return string The arguments for the command. + */ + abstract protected function arguments(); - abstract public function run( $args, $assoc_args ); + /** + * Run the command. + * + * This method must be implemented in the child class to define the logic + * for executing the command. It accepts arguments and associative arguments + * passed to the command via WP-CLI. + * + * @param array $args The positional arguments passed to the command. + * @param array $assoc_args The associative arguments passed to the command. + * @return void + */ + abstract public function run( $args, $assoc_args ); } \ No newline at end of file diff --git a/src/BigCommerce/CLI/Documentation/Build_Docs.php b/src/BigCommerce/CLI/Documentation/Build_Docs.php index a7c8a9e5..fc6cd3ba 100644 --- a/src/BigCommerce/CLI/Documentation/Build_Docs.php +++ b/src/BigCommerce/CLI/Documentation/Build_Docs.php @@ -8,60 +8,67 @@ use WP_CLI; /** - * Class Build_Docs - * * Register build docs command and related functionality * * @package BigCommerce\CLI\Documentation */ class Build_Docs extends Command { - private $plugin_dir; + /** + * @var string The directory path of the plugin being documented. + */ + private $plugin_dir; - public function __construct( $plugin_dir ) { - $this->plugin_dir = $plugin_dir; - } + /** + * Constructor for the Build_Docs class. + * + * @param string $plugin_dir Directory path of the plugin. + */ + public function __construct( $plugin_dir ) { + $this->plugin_dir = $plugin_dir; + } /** - * Declare command name + * Declare command name. * - * @return string + * @return string The CLI command name. */ - protected function command() { - return 'docs build'; - } + protected function command() { + return 'docs build'; + } /** - * Provide a command description + * Provide a command description. * - * @return string|void + * @return string|void The CLI command description. */ - protected function description() { - return __( 'Builds plugin documentation', 'bigcommerce' ); - } + protected function description() { + return __( 'Builds plugin documentation', 'bigcommerce' ); + } /** - * Declare command arguments + * Declare command arguments. * - * @return array[] + * @return array[] List of command arguments. */ - protected function arguments() { - return [ - [ - 'type' => 'positional', - 'name' => 'file', - 'optional' => false, - 'description' => __( 'Path to the JSON file to export', 'bigcommerce' ), - ], - ]; - } + protected function arguments() { + return [ + [ + 'type' => 'positional', + 'name' => 'file', + 'optional' => false, + 'description' => __( 'Path to the JSON file to export', 'bigcommerce' ), + ], + ]; + } /** - * Get files data and write it to provided file + * Get files data and write it to the provided file. * - * @param $args - * @param $assoc_args + * @param array $args Positional arguments passed to the command. + * @param array $assoc_args Associative arguments passed to the command. * - * @throws WP_CLI\ExitException + * @throws WP_CLI\ExitException If there is an issue during execution. + * @return void */ public function run( $args, $assoc_args ) { if ( ! function_exists( '\WP_Parser\parse_files' ) ) { diff --git a/src/BigCommerce/CLI/Documentation/Data_Importer.php b/src/BigCommerce/CLI/Documentation/Data_Importer.php index 4bf03e5c..c2c18bfc 100644 --- a/src/BigCommerce/CLI/Documentation/Data_Importer.php +++ b/src/BigCommerce/CLI/Documentation/Data_Importer.php @@ -6,19 +6,24 @@ use WP_Parser\Importer; +/** + * Extends WP_Parser's Importer class to modify the import behavior for class methods and hooks. + * + * @package BigCommerce\CLI\Documentation + */ class Data_Importer extends Importer { - - /** - * Create a post for a class method. - * - * @param array $data Method. - * @param int $parent_post_id Optional; post ID of the parent (class) this - * method belongs to. Defaults to zero (no parent). - * @param bool $import_ignored Optional; defaults to false. If true, functions - * marked `@ignore` will be imported. - * @return bool|int Post ID of this function, false if any failure. - */ + /** + * Create a post for a class method, selectively importing hooks for protected or private methods. + * + * @param array $data The method data to import. + * @param int $parent_post_id Optional; post ID of the parent (class) this + * method belongs to. Defaults to zero (no parent). + * @param bool $import_ignored Optional; if true, functions marked `@ignore` + * will also be imported. Defaults to false. + * + * @return bool|int Post ID of the method if successfully imported, false otherwise. + */ protected function import_method( array $data, $parent_post_id = 0, $import_ignored = false ) { if ( in_array( $data[ 'visibility' ], [ 'private', 'protected' ] ) ) { // import the hooks diff --git a/src/BigCommerce/CLI/Documentation/Import_Docs.php b/src/BigCommerce/CLI/Documentation/Import_Docs.php index 2b0fce8b..1fa0d39e 100644 --- a/src/BigCommerce/CLI/Documentation/Import_Docs.php +++ b/src/BigCommerce/CLI/Documentation/Import_Docs.php @@ -11,88 +11,115 @@ /** * Class Import_Docs * - * Imports provides json file previously built by docs build command + * Handles the import of plugin documentation from a previously built JSON file. + * + * @package BigCommerce\CLI\Documentation */ class Import_Docs extends Command { - private $plugin_dir; - - public function __construct( $plugin_dir ) { - $this->plugin_dir = $plugin_dir; - } - - protected function command() { - return 'docs import'; - } - - protected function description() { - return __( 'Imports plugin documentation', 'bigcommerce' ); - } - - protected function arguments() { - return [ - [ - 'type' => 'positional', - 'name' => 'file', - 'optional' => false, - 'description' => __( 'Path to the JSON file to import', 'bigcommerce' ), - ], - ]; - } + /** + * @var string Directory of the plugin being documented. + */ + private $plugin_dir; /** - * Run docs import process + * Import_Docs constructor. * - * @param $args - * @param $assoc_args - * - * @throws WP_CLI\ExitException + * @param string $plugin_dir Directory of the plugin. */ - public function run( $args, $assoc_args ) { - if ( ! class_exists( '\WP_Parser\Importer' ) ) { - WP_CLI::error( __( 'Please install and activate WP Parser from https://github.com/WordPress/phpdoc-parser before importing documentation.', 'bigcommerce' ) ); - exit; - } - - $file = reset( $args ); + public function __construct( $plugin_dir ) { + $this->plugin_dir = $plugin_dir; + } - // Get the data from the , and check it's valid. - $phpdoc = false; - - if ( is_readable( $file ) ) { - $phpdoc = file_get_contents( $file ); - } + /** + * Declare the command name. + * + * @return string + */ + protected function command() { + return 'docs import'; + } - if ( ! $phpdoc ) { - WP_CLI::error( sprintf( "Can't read %1\$s. Does the file exist?", $file ) ); - exit; - } + /** + * Provide a command description. + * + * @return string + */ + protected function description() { + return __( 'Imports plugin documentation', 'bigcommerce' ); + } - $phpdoc = json_decode( $phpdoc, true ); - if ( is_null( $phpdoc ) ) { - WP_CLI::error( sprintf( "JSON in %1\$s can't be decoded", $file ) ); - exit; - } + /** + * Declare command arguments. + * + * @return array[] + */ + protected function arguments() { + return [ + [ + 'type' => 'positional', + 'name' => 'file', + 'optional' => false, + 'description' => __( 'Path to the JSON file to import', 'bigcommerce' ), + ], + ]; + } - // Import data - $this->run_import( $phpdoc ); - } + /** + * Execute the documentation import process. + * + * @param array $args Positional arguments passed to the command. + * @param array $assoc_args Associative arguments passed to the command. + * + * @throws WP_CLI\ExitException + */ + public function run( $args, $assoc_args ) { + if ( ! class_exists( '\WP_Parser\Importer' ) ) { + WP_CLI::error( __( 'Please install and activate WP Parser from https://github.com/WordPress/phpdoc-parser before importing documentation.', 'bigcommerce' ) ); + exit; + } + + $file = reset( $args ); + + // Get the data from the , and check it's valid. + $phpdoc = false; + + if ( is_readable( $file ) ) { + $phpdoc = file_get_contents( $file ); + } + + if ( ! $phpdoc ) { + WP_CLI::error( sprintf( "Can't read %1\$s. Does the file exist?", $file ) ); + exit; + } + + $phpdoc = json_decode( $phpdoc, true ); + if ( is_null( $phpdoc ) ) { + WP_CLI::error( sprintf( "JSON in %1\$s can't be decoded", $file ) ); + exit; + } + + // Import data + $this->run_import( $phpdoc ); + } /** - * @param $data + * Execute the data import using the WP Parser importer. + * + * @param array $data Parsed JSON data to import. * * @throws WP_CLI\ExitException */ - private function run_import( $data ) { - if ( ! wp_get_current_user()->exists() ) { - WP_CLI::error( 'Please specify a valid user: --user=' ); - exit; - } + private function run_import( $data ) { + if ( ! wp_get_current_user()->exists() ) { + WP_CLI::error( 'Please specify a valid user: --user=' ); + exit; + } // Run the importer - $importer = new Data_Importer(); - $importer->setLogger( new WP_CLI_Logger() ); - $importer->import( $data, true, false ); + $importer = new Data_Importer(); + $importer->setLogger( new WP_CLI_Logger() ); + $importer->import( $data, true, false ); - WP_CLI::line(); - } + WP_CLI::line(); + } } diff --git a/src/BigCommerce/CLI/Documentation/README.md b/src/BigCommerce/CLI/Documentation/README.md index 7490eef5..c2e0d71d 100644 --- a/src/BigCommerce/CLI/Documentation/README.md +++ b/src/BigCommerce/CLI/Documentation/README.md @@ -8,7 +8,7 @@ ## Installation -Clone the BigCommerce and WP Parser respositories into your WordPress plugins directory +Clone the BigCommerce and WP Parser repositories into your WordPress plugins directory ``` cd wp-content/plugins/ diff --git a/src/BigCommerce/CLI/Import_Products.php b/src/BigCommerce/CLI/Import_Products.php index ccedaa91..b69274de 100644 --- a/src/BigCommerce/CLI/Import_Products.php +++ b/src/BigCommerce/CLI/Import_Products.php @@ -1,25 +1,24 @@ plugin_dir = $plugin_dir; - } - - protected function command() { - return 'resources build'; - } - - protected function description() { - return __( 'Builds plugin resources JSON from a CSV file', 'bigcommerce' ); - } - - protected function arguments() { - return [ - [ - 'type' => 'positional', - 'name' => 'file', - 'optional' => false, - 'description' => __( 'Path to the CSV file with resource data', 'bigcommerce' ), - ], - [ - 'type' => 'flag', - 'name' => 'pretty', - 'optional' => true, - 'description' => __( 'Apply JSON pretty formatting to the output', 'bigcommerce' ), - ], - ]; - } + /** + * @var string Directory of the plugin being processed. + */ + private $plugin_dir; /** - * Run resource build process from provided csv file + * Build_Resources constructor. * - * @param $args - * @param $assoc_args + * @param string $plugin_dir Directory of the plugin. + */ + public function __construct( $plugin_dir ) { + $this->plugin_dir = $plugin_dir; + } + + /** + * Declare the command name. + * + * @return string + */ + protected function command() { + return 'resources build'; + } + + /** + * Provide a command description. + * + * @return string + */ + protected function description() { + return __( 'Builds plugin resources JSON from a CSV file', 'bigcommerce' ); + } + + /** + * Declare command arguments. + * + * @return array[] + */ + protected function arguments() { + return [ + [ + 'type' => 'positional', + 'name' => 'file', + 'optional' => false, + 'description' => __( 'Path to the CSV file with resource data', 'bigcommerce' ), + ], + [ + 'type' => 'flag', + 'name' => 'pretty', + 'optional' => true, + 'description' => __( 'Apply JSON pretty formatting to the output', 'bigcommerce' ), + ], + ]; + } + + /** + * Execute the resource build process from the provided CSV file. + * + * @param array $args Positional arguments passed to the command. + * @param array $assoc_args Associative arguments passed to the command. * * @throws WP_CLI\ExitException */ - public function run( $args, $assoc_args ) { - $path = $args[ 0 ]; - if ( ! file_exists( $path ) || ! is_readable( $path ) ) { - \WP_CLI::error( __( 'Unable to read input file.', 'bigcommerce' ) ); - } + public function run( $args, $assoc_args ) { + $path = $args[ 0 ]; + if ( ! file_exists( $path ) || ! is_readable( $path ) ) { + \WP_CLI::error( __( 'Unable to read input file.', 'bigcommerce' ) ); + } - if ( ! class_exists( 'League\Csv\Reader' ) ) { + if ( ! class_exists( 'League\Csv\Reader' ) ) { \WP_CLI::error( __( 'Missing league/csv library. Unable to build resources json.', 'bigcommerce' ) ); } $csv = Reader::createFromPath( $path, 'r' ); $keys = $csv->fetchOne(); $csv->setOffset( 1 ); - $groups = []; - foreach ( $csv->fetchAssoc( $keys ) as $record ) { - if ( ! array_key_exists( $record[ 'Tab' ], $groups ) ) { - $groups[ $record[ 'Tab' ] ] = new Resource_Group( $record[ 'Tab' ] ); - } - - $groups[ $record[ 'Tab' ] ]->add_resource( ( new Resource() ) - ->set_name( $record[ 'Name' ] ) - ->set_description( $record[ 'Description' ] ) - ->set_url( $record[ 'URL' ] ) - ->set_thumbnail( $record[ 'Thumbnail' ] ) - ->set_hires_thumbnail( $record[ 'HiRes Thumbnail' ] ) - ->set_categories( array_filter( explode( ',', $record[ 'Categories' ] ) ) ) - ); - } - - $output = [ - 'version' => 1, - 'sections' => array_values( $groups ), - ]; - - $flags = 0; - if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty', false ) ) { - $flags |= JSON_PRETTY_PRINT; - } - - echo wp_json_encode( $output, $flags ); - - } + $groups = []; + foreach ( $csv->fetchAssoc( $keys ) as $record ) { + if ( ! array_key_exists( $record[ 'Tab' ], $groups ) ) { + $groups[ $record[ 'Tab' ] ] = new Resource_Group( $record[ 'Tab' ] ); + } + + $groups[ $record[ 'Tab' ] ]->add_resource( ( new Resource() ) + ->set_name( $record[ 'Name' ] ) + ->set_description( $record[ 'Description' ] ) + ->set_url( $record[ 'URL' ] ) + ->set_thumbnail( $record[ 'Thumbnail' ] ) + ->set_hires_thumbnail( $record[ 'HiRes Thumbnail' ] ) + ->set_categories( array_filter( explode( ',', $record[ 'Categories' ] ) ) ) + ); + } + + $output = [ + 'version' => 1, + 'sections' => array_values( $groups ), + ]; + + $flags = 0; + if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'pretty', false ) ) { + $flags |= JSON_PRETTY_PRINT; + } + + echo wp_json_encode( $output, $flags ); + + } } diff --git a/src/BigCommerce/CLI/Resources/Resource.php b/src/BigCommerce/CLI/Resources/Resource.php index b19dbdca..5c004b85 100644 --- a/src/BigCommerce/CLI/Resources/Resource.php +++ b/src/BigCommerce/CLI/Resources/Resource.php @@ -3,155 +3,216 @@ namespace BigCommerce\CLI\Resources; +/** + * Class Resource + * + * Represents a resource with various properties such as URL, name, description, thumbnails, categories, and external status. + * Implements the JsonSerializable interface to allow conversion to JSON. + * + * @package BigCommerce\CLI\Resources + */ class Resource implements \JsonSerializable { - private $url = ''; - private $name = ''; - private $description = ''; - private $thumbnail = ''; - private $hires_thumbnail = ''; - private $external = true; - private $categories = []; - - /** - * @return string - */ - public function get_url() { - return $this->url; - } - - /** - * @param string $url - * - * @return Resource - */ - public function set_url( $url ) { - $this->url = $url; - - return $this; - } - - /** - * @return string - */ - public function get_name() { - return $this->name; - } - - /** - * @param string $name - * - * @return Resource - */ - public function set_name( $name ) { - $this->name = $name; - - return $this; - } - - /** - * @return string - */ - public function get_description() { - return $this->description; - } - - /** - * @param string $description - * - * @return Resource - */ - public function set_description( $description ) { - $this->description = $description; - - return $this; - } - - /** - * @return string - */ - public function get_thumbnail() { - return $this->thumbnail; - } - - /** - * @param string $thumbnail - * - * @return Resource - */ - public function set_thumbnail( $thumbnail ) { - $this->thumbnail = $thumbnail; - - return $this; - } - - /** - * @return string - */ - public function get_hires_thumbnail() { - return $this->hires_thumbnail; - } - - /** - * @param string $hires_thumbnail - * - * @return Resource - */ - public function set_hires_thumbnail( $hires_thumbnail ) { - $this->hires_thumbnail = $hires_thumbnail; - - return $this; - } - - /** - * @return bool - */ - public function get_external() { - return $this->external; - } - - /** - * @param bool $external - * - * @return Resource - */ - public function set_external( $external ) { - $this->external = $external; - - return $this; - } - - /** - * @return array - */ - public function get_categories() { - return $this->categories; - } - - /** - * @param string[] $categories - * - * @return Resource - */ - public function set_categories( array $categories ) { - $this->categories = $categories; - - return $this; - } - - - public function jsonSerialize() { - return [ - 'name' => $this->get_name(), - 'description' => $this->get_description(), - 'thumbnail' => [ - 'small' => $this->get_thumbnail(), - 'large' => $this->get_hires_thumbnail(), - ], - 'url' => $this->get_url(), - 'categories' => $this->get_categories(), - 'isExternal' => (bool) $this->get_external(), - ]; - } + + /** + * @var string URL of the resource. + */ + private $url = ''; + + /** + * @var string Name of the resource. + */ + private $name = ''; + + /** + * @var string Description of the resource. + */ + private $description = ''; + + /** + * @var string Thumbnail image URL of the resource. + */ + private $thumbnail = ''; + + /** + * @var string High-resolution thumbnail image URL of the resource. + */ + private $hires_thumbnail = ''; + + /** + * @var bool Whether the resource is external or not. + */ + private $external = true; + + /** + * @var string[] List of categories associated with the resource. + */ + private $categories = []; + + /** + * Get the URL of the resource. + * + * @return string The URL of the resource. + */ + public function get_url() { + return $this->url; + } + + /** + * Set the URL of the resource. + * + * @param string $url The URL of the resource. + * @return Resource The current instance of the resource. + */ + public function set_url( $url ) { + $this->url = $url; + + return $this; + } + + /** + * Get the name of the resource. + * + * @return string The name of the resource. + */ + public function get_name() { + return $this->name; + } + + /** + * Set the name of the resource. + * + * @param string $name The name of the resource. + * @return Resource The current instance of the resource. + */ + public function set_name( $name ) { + $this->name = $name; + + return $this; + } + + /** + * Get the description of the resource. + * + * @return string The description of the resource. + */ + public function get_description() { + return $this->description; + } + + /** + * Set the description of the resource. + * + * @param string $description The description of the resource. + * @return Resource The current instance of the resource. + */ + public function set_description( $description ) { + $this->description = $description; + + return $this; + } + + /** + * Get the thumbnail URL of the resource. + * + * @return string The thumbnail URL of the resource. + */ + public function get_thumbnail() { + return $this->thumbnail; + } + + /** + * Set the thumbnail URL of the resource. + * + * @param string $thumbnail The thumbnail URL of the resource. + * @return Resource The current instance of the resource. + */ + public function set_thumbnail( $thumbnail ) { + $this->thumbnail = $thumbnail; + + return $this; + } + + /** + * Get the high-resolution thumbnail URL of the resource. + * + * @return string The high-resolution thumbnail URL of the resource. + */ + public function get_hires_thumbnail() { + return $this->hires_thumbnail; + } + + /** + * Set the high-resolution thumbnail URL of the resource. + * + * @param string $hires_thumbnail The high-resolution thumbnail URL of the resource. + * @return Resource The current instance of the resource. + */ + public function set_hires_thumbnail( $hires_thumbnail ) { + $this->hires_thumbnail = $hires_thumbnail; + + return $this; + } + + /** + * Get the external status of the resource. + * + * @return bool Whether the resource is external or not. + */ + public function get_external() { + return $this->external; + } + + /** + * Set the external status of the resource. + * + * @param bool $external Whether the resource is external or not. + * @return Resource The current instance of the resource. + */ + public function set_external( $external ) { + $this->external = $external; + + return $this; + } + + /** + * Get the categories associated with the resource. + * + * @return string[] The list of categories associated with the resource. + */ + public function get_categories() { + return $this->categories; + } + + /** + * Set the categories associated with the resource. + * + * @param string[] $categories The list of categories to associate with the resource. + * @return Resource The current instance of the resource. + */ + public function set_categories( array $categories ) { + $this->categories = $categories; + + return $this; + } + + /** + * Specify data to be serialized to JSON. + * + * @return array Data representing the object for JSON encoding. + */ + public function jsonSerialize() { + return [ + 'name' => $this->get_name(), + 'description' => $this->get_description(), + 'thumbnail' => [ + 'small' => $this->get_thumbnail(), + 'large' => $this->get_hires_thumbnail(), + ], + 'url' => $this->get_url(), + 'categories' => $this->get_categories(), + 'isExternal' => (bool) $this->get_external(), + ]; + } } \ No newline at end of file diff --git a/src/BigCommerce/CLI/Resources/Resource_Group.php b/src/BigCommerce/CLI/Resources/Resource_Group.php index 524e1b78..846f38aa 100644 --- a/src/BigCommerce/CLI/Resources/Resource_Group.php +++ b/src/BigCommerce/CLI/Resources/Resource_Group.php @@ -5,34 +5,74 @@ use BigCommerce\CLI\Resources\Resource; +/** + * Represents a group of resources, which are categorized by a label. + * Implements the JsonSerializable interface to allow conversion to JSON. + * + * @package BigCommerce\CLI\Resources + */ class Resource_Group implements \JsonSerializable { - private $label; - private $resources = []; + /** + * @var string The label of the resource group. + */ + private $label; - public function __construct( $label ) { - $this->label = $label; - } + /** + * @var Resource[] List of resources within the group. + */ + private $resources = []; - public function add_resource( Resource $resource ) { - $this->resources[] = $resource; + /** + * Resource_Group constructor. + * + * @param string $label The label for the resource group. + */ + public function __construct( $label ) { + $this->label = $label; + } - return $this; - } + /** + * Add a resource to the group. + * + * @param Resource $resource The resource to add to the group. + * + * @return $this The current instance of the group. + */ + public function add_resource( Resource $resource ) { + $this->resources[] = $resource; - public function get_label() { - return $this->label; - } + return $this; + } - public function get_resources() { - return $this->resources; - } + /** + * Get the label of the resource group. + * + * @return string The label of the group. + */ + public function get_label() { + return $this->label; + } - public function jsonSerialize() { - return [ - 'label' => $this->get_label(), - 'resources' => $this->get_resources(), - ]; - } + /** + * Get the list of resources in the group. + * + * @return Resource[] The resources within the group. + */ + public function get_resources() { + return $this->resources; + } + + /** + * Specify data to be serialized to JSON. + * + * @return array Data representing the object for JSON encoding. + */ + public function jsonSerialize() { + return [ + 'label' => $this->get_label(), + 'resources' => $this->get_resources(), + ]; + } } \ No newline at end of file diff --git a/src/BigCommerce/CLI/Update_Country_Cache.php b/src/BigCommerce/CLI/Update_Country_Cache.php index fa460b98..f1ea6c52 100644 --- a/src/BigCommerce/CLI/Update_Country_Cache.php +++ b/src/BigCommerce/CLI/Update_Country_Cache.php @@ -7,89 +7,120 @@ use Bigcommerce\Api\Client; /** - * Class Update_Country_Cache + * Updates the country and state cache in a JSON file located at assets/data/countries.json. + * This command fetches the latest country and state data from the BigCommerce API and stores it in a specified output file. + * If no output file is provided, it defaults to a predefined file path. * - * Updates the country/state cache in assets/data/countries.json - * Usage: - * wp bigcommerce countries update + * Usage: wp bigcommerce countries update --output=/path/to/file.json + * + * @package BigCommerce + * @subpackage CLI */ class Update_Country_Cache extends Command { - private $default_output_file = ''; - - public function __construct( $default_output_file ) { - $this->default_output_file = $default_output_file; - } - - protected function command() { - return 'countries update'; - } - - protected function description() { - return __( 'Update the cache of countries and states in countries.json', 'bigcommerce' ); - } - - protected function arguments() { - return [ - [ - 'type' => 'assoc', - 'name' => 'output', - 'description' => __( 'The path to the output json file', 'bigcommerce' ), - 'optional' => true, - ], - ]; - } + private $default_output_file = ''; + + /** + * Constructor to initialize the default output file. + * + * @param string $default_output_file The default file path for the JSON output. + */ + public function __construct( $default_output_file ) { + $this->default_output_file = $default_output_file; + } + + /** + * Declare the WP-CLI command for updating the country cache. + * + * @return string The WP-CLI command to execute. + */ + protected function command() { + return 'countries update'; + } + + /** + * Add a description for the WP-CLI command. + * + * @return string The description of the command. + */ + protected function description() { + return __( 'Update the cache of countries and states in countries.json', 'bigcommerce' ); + } + + /** + * Declare the command arguments for the update cache operation. + * + * @return array[] The command arguments, including an optional output file argument. + */ + protected function arguments() { + return [ + [ + 'type' => 'assoc', + 'name' => 'output', + 'description' => __( 'The path to the output json file', 'bigcommerce' ), + 'optional' => true, + ], + ]; + } + + /** + * Executes the update process for the country and state cache. + * Fetches data from the BigCommerce API and writes it to the specified output file. + * + * @param array $args Arguments passed to the command. + * @param array $assoc_args Associated arguments (e.g., output file path). + * + * @throws \WP_CLI\ExitException If there is an error in the process, an exit exception is thrown. + */ + public function run( $args, $assoc_args ) { + $output_file = empty( $assoc_args[ 'output' ] ) ? $this->default_output_file : $assoc_args[ 'output' ]; + if ( ! is_writable( $output_file ) ) { + \WP_CLI::error( sprintf( __( 'Cannot write to %s.', 'bigcommerce' ), $output_file ) ); + } + $countries = $this->get_country_data(); + if ( empty( $countries ) ) { + \WP_CLI::error( __( 'Unable to retrieve country data from the BigCommerce API', 'bigcommerce' ) ); + } + $json = wp_json_encode( $countries ); + \WP_CLI::debug( sprintf( __( 'Writing country json to %s', 'bigcommerce' ), $output_file ) ); + file_put_contents( $output_file, $json ); + \WP_CLI::success( __( 'Update complete', 'bigcommerce' ) ); + } /** - * @param $args - * @param $assoc_args + * Fetches the country and state data from the BigCommerce API. + * Retrieves a list of countries and their respective states, if available. * - * @throws \WP_CLI\ExitException + * @return array An array of countries with associated state data. */ - public function run( $args, $assoc_args ) { - $output_file = empty( $assoc_args[ 'output' ] ) ? $this->default_output_file : $assoc_args[ 'output' ]; - if ( ! is_writable( $output_file ) ) { - \WP_CLI::error( sprintf( __( 'Cannot write to %s.', 'bigcommerce' ), $output_file ) ); - } - $countries = $this->get_country_data(); - if ( empty( $countries ) ) { - \WP_CLI::error( __( 'Unable to retrieve country data from the BigCommerce API', 'bigcommerce' ) ); - } - $json = wp_json_encode( $countries ); - \WP_CLI::debug( sprintf( __( 'Writing country json to %s', 'bigcommerce' ), $output_file ) ); - file_put_contents( $output_file, $json ); - \WP_CLI::success( __( 'Update complete', 'bigcommerce' ) ); - } - - - public function get_country_data() { - try { - $countries = Client::getCollection( '/countries?limit=250' ); - - if ( ! is_array( $countries ) ) { - return []; - } - - $progress = \WP_CLI\Utils\make_progress_bar( __( 'Importing state lists', 'tribe' ), count( $countries ) ); - - $countries = array_map( function ( $country ) use ( $progress ) { - try { - $states = Client::getCollection( sprintf( '/countries/%d/states?limit=250', $country->id ) ); - } catch ( \Exception $e ) { - $states = null; - \WP_CLI::warning( sprintf( __( 'Error fetching states for %s. Error message: %s', 'bigcommerce' ), $country->country, $e->getMessage() ) ); - } - $country = $country->getCreateFields(); - $country->states = $states ? array_map( function ( $state ) { - return $state->getCreateFields(); - }, $states ) : null; - $progress->tick(); - - return $country; - }, $countries ); - } catch ( \Exception $e ) { - return []; - } - - return $countries; - } + public function get_country_data() { + try { + $countries = Client::getCollection( '/countries?limit=250' ); + + if ( ! is_array( $countries ) ) { + return []; + } + + $progress = \WP_CLI\Utils\make_progress_bar( __( 'Importing state lists', 'tribe' ), count( $countries ) ); + + $countries = array_map( function ( $country ) use ( $progress ) { + try { + $states = Client::getCollection( sprintf( '/countries/%d/states?limit=250', $country->id ) ); + } catch ( \Exception $e ) { + $states = null; + \WP_CLI::warning( sprintf( __( 'Error fetching states for %s. Error message: %s', 'bigcommerce' ), $country->country, $e->getMessage() ) ); + } + $country = $country->getCreateFields(); + $country->states = $states ? array_map( function ( $state ) { + return $state->getCreateFields(); + }, $states ) : null; + $progress->tick(); + + return $country; + }, $countries ); + } catch ( \Exception $e ) { + return []; + } + + return $countries; + } } diff --git a/src/BigCommerce/Cache/Cache_Handler.php b/src/BigCommerce/Cache/Cache_Handler.php index 0db67fb5..d2f66a15 100644 --- a/src/BigCommerce/Cache/Cache_Handler.php +++ b/src/BigCommerce/Cache/Cache_Handler.php @@ -5,25 +5,54 @@ /** * Cache_Handler class * - * Flushes catalog api WP_Object_Cache data + * Responsible for flushing the catalog API WP_Object_Cache to ensure that product information is up-to-date + * from the BigCommerce catalog. + * + * @package BigCommerce\Cache */ class Cache_Handler { + /** + * The catalog API path for products. + * + * @var string + */ private $catalog_path = '/catalog/products/'; + /** + * The default HTTP header parameters used for API requests. + * + * @var array + */ private $header_params = [ 'Accept' => 'application/json', 'Content-Type' => 'application/json', ]; + /** + * The type of response expected from the API for product requests. + * + * @var string + */ private $product_response_type = '\BigCommerce\Api\v3\Model\ProductResponse'; + + /** + * The group key used in WordPress object caching for BigCommerce API data. + * + * @var string + */ private $group_key = 'bigcommerce_api'; /** - * Flush WP_Object_Cache for catalog API in order to get up-to-date product info from BC catalog + * Flushes the WordPress object cache for the product catalog. + * + * This method ensures that the cache is cleared for the specified product, allowing fresh product information + * to be retrieved from the BigCommerce catalog. * - * @param $product_id - * @param array $query_params + * @param int $product_id The ID of the product to flush the cache for. + * @param array $query_params Optional query parameters to customize the cache key. + * + * @return void */ public function flush_product_catalog_object_cache( $product_id, array $query_params = [] ): void { $default_params = [ @@ -37,12 +66,14 @@ public function flush_product_catalog_object_cache( $product_id, array $query_pa } /** - * Build a cache key + * Builds a serialized cache key for a product based on product ID and query parameters. + * + * This method generates a unique cache key used to store and retrieve the product's data from the cache. * - * @param $product_id - * @param array $query_params + * @param int $product_id The ID of the product. + * @param array $query_params Optional query parameters to customize the cache key. * - * @return string + * @return string The generated cache key. */ private function build_serialized_key( $product_id, array $query_params = [] ): string { $args = [ diff --git a/src/BigCommerce/Cart/Add_To_Cart.php b/src/BigCommerce/Cart/Add_To_Cart.php index 25a8ae60..b4c87bb0 100644 --- a/src/BigCommerce/Cart/Add_To_Cart.php +++ b/src/BigCommerce/Cart/Add_To_Cart.php @@ -11,180 +11,217 @@ * Handles requests from the Add to Cart button for products */ class Add_To_Cart { - const ACTION = 'cart'; - - /** - * @param int $post_id - * @param CartApi $cart_api - * - * @return void - * @action bigcommerce/action_endpoint/ . self::ACTION - */ - public function handle_request( $post_id, CartApi $cart_api ) { - if ( ! $this->validate_request( $post_id, $_POST ) ) { - $error = new \WP_Error( 'unknown_product', __( 'We were unable to process your request. Please go back and try again.', 'bigcommerce' ) ); - do_action( 'bigcommerce/form/error', $error, $_POST, home_url( '/' ) ); - - return; - } - - $product = new Product( $post_id ); - $product_id = $product->bc_id(); - $variant_id = $this->get_variant_id( $product, $_POST ); - - $options = []; - - // Options are sanitized bellow - $submitted_options = empty( $_POST[ 'option' ] ) ? [] : (array) $_POST[ 'option' ]; // phpcs:ignore - $option_config = $product->options(); - $modifier_config = $product->modifiers(); - foreach ( $option_config as $config ) { - if ( array_key_exists( $config[ 'id' ], $submitted_options ) ) { - $options[ $config[ 'id' ] ] = absint( $submitted_options[ $config[ 'id' ] ] ); - } - } - foreach ( $modifier_config as $config ) { - if ( array_key_exists( $config[ 'id' ], $submitted_options ) ) { - $options[ $config[ 'id' ] ] = $this->sanitize_option( $submitted_options[ $config[ 'id' ] ], $config ); - } - } - - $quantity = array_key_exists( 'quantity', $_POST ) ? absint( $_POST[ 'quantity' ] ) : 1; - - $cart = new Cart( $cart_api ); - try { - $response = $cart->add_line_item( $product_id, $options, $quantity ); - $this->handle_response( $response, $cart, $post_id, $product_id, $variant_id ); - } catch ( ApiException $e ) { - $this->handle_exception( $e, $cart ); - } - } - - private function sanitize_option( $value, $config ) { - switch ( $config[ 'type' ] ) { - case 'date': - return strtotime( $value ); - case 'multi_line_text': - return sanitize_textarea_field( $value ); - case 'numbers_only_text': - return filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION|FILTER_FLAG_ALLOW_THOUSAND ); - case 'text': - return sanitize_text_field( $value ); - default: // checkboxes, selects, and radios - return (int) $value; - } - } - - /** - * @param \BigCommerce\Api\v3\Model\Cart|null $response - * @param Cart $cart - * @param int $post_id - * - * @param int $product_id - * @param int $variant_id - * - * @return void - */ - protected function handle_response( $response, Cart $cart, $post_id, $product_id, $variant_id ) { - $cart_url = $cart->get_cart_url(); - /** - * Triggered when a form is successfully processed. - * - * @param string $message The message that will display to the user - * @param array $submission The data submitted to the form - * @param string $url The URL to redirect the user to - * @param array $data Additional data to store with the message - */ - do_action( 'bigcommerce/form/success', __( '1 item added to Cart', 'bigcommerce' ), $_POST, $cart_url, [ - 'key' => 'add_to_cart', - 'cart_id' => $cart->get_cart_id(), - 'post_id' => $post_id, - 'product_id' => $product_id, - 'variant_id' => $variant_id, - ] ); - wp_safe_redirect( esc_url_raw( $cart_url ), 303 ); - exit(); - } - - /** - * @param ApiException $e - * @param Cart $cart - * - * @return void - */ - protected function handle_exception( ApiException $e, $cart ) { - if ( strpos( (string) $e->getCode(), '4' ) === 0 ) { - $body = $e->getResponseBody(); - if ( $body && ! empty( $body->title ) ) { - $message = sprintf( '[%d] %s', $e->getCode(), $body->title ); - } else { - $message = $e->getMessage(); - } - $error = new \WP_Error( 'api_error', sprintf( - __( 'There was an error adding this product to your cart. Error message: "%s"', 'bigcommerce' ), - $message - ), [ 'exception' => [ 'message' => $e->getMessage(), 'code' => $e->getCode() ] ] ); - } else { - $error = new \WP_Error( 'api_error', __( 'There was an error adding this product to your cart. It might be out of stock or unavailable.', 'bigcommerce' ), [ - 'exception' => [ - 'message' => $e->getMessage(), - 'code' => $e->getCode(), - ], - ] ); - } - do_action( 'bigcommerce/form/error', $error, $_POST, $cart->get_cart_url() ); - } - - protected function validate_request( $post_id, $submission ) { - $post = get_post( $post_id ); - if ( empty( $post ) ) { - return false; - } - if ( Product::NAME !== $post->post_type ) { - return false; - } - if ( $post->post_status !== 'publish' ) { - return false; - } - - return true; - } + const ACTION = 'cart'; /** - * Get product variant id from submission + * Handles the request to add a product to the cart. * - * @param Product $product - * @param $submission + * @param int $post_id The ID of the product post. + * @param CartApi $cart_api The CartApi instance to interact with the cart API. + * + * @return void + * @action bigcommerce/action_endpoint/ . self::ACTION + */ + public function handle_request( $post_id, CartApi $cart_api ) { + if ( ! $this->validate_request( $post_id, $_POST ) ) { + $error = new \WP_Error( 'unknown_product', __( 'We were unable to process your request. Please go back and try again.', 'bigcommerce' ) ); + /** + * Fires when there is an error processing the add to cart form. + * + * @param \WP_Error $error The error object + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to after handling submission + * @param array $data Additional data about the submission + */ + do_action('bigcommerce/form/error', $error, $_POST, home_url('/')); + + return; + } + + $product = new Product( $post_id ); + $product_id = $product->bc_id(); + $variant_id = $this->get_variant_id( $product, $_POST ); + + $options = []; + + // Options are sanitized below + $submitted_options = empty( $_POST[ 'option' ] ) ? [] : (array) $_POST[ 'option' ]; // phpcs:ignore + $option_config = $product->options(); + $modifier_config = $product->modifiers(); + foreach ( $option_config as $config ) { + if ( array_key_exists( $config[ 'id' ], $submitted_options ) ) { + $options[ $config[ 'id' ] ] = absint( $submitted_options[ $config[ 'id' ] ] ); + } + } + foreach ( $modifier_config as $config ) { + if ( array_key_exists( $config[ 'id' ], $submitted_options ) ) { + $options[ $config[ 'id' ] ] = $this->sanitize_option( $submitted_options[ $config[ 'id' ] ], $config ); + } + } + + $quantity = array_key_exists( 'quantity', $_POST ) ? absint( $_POST[ 'quantity' ] ) : 1; + + $cart = new Cart( $cart_api ); + try { + $response = $cart->add_line_item( $product_id, $options, $quantity ); + $this->handle_response( $response, $cart, $post_id, $product_id, $variant_id ); + } catch ( ApiException $e ) { + $this->handle_exception( $e, $cart ); + } + } + + /** + * Sanitizes a product option based on its configuration type. + * + * @param mixed $value The value of the option submitted by the user. + * @param array $config The configuration of the option (type, id, etc.). + * + * @return mixed The sanitized option value. + */ + private function sanitize_option( $value, $config ) { + switch ( $config[ 'type' ] ) { + case 'date': + return strtotime( $value ); + case 'multi_line_text': + return sanitize_textarea_field( $value ); + case 'numbers_only_text': + return filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION|FILTER_FLAG_ALLOW_THOUSAND ); + case 'text': + return sanitize_text_field( $value ); + default: // checkboxes, selects, and radios + return (int) $value; + } + } + + /** + * Handles the response from the API after attempting to add a product to the cart. + * + * @param \BigCommerce\Api\v3\Model\Cart|null $response The response from the API. + * @param Cart $cart The cart instance. + * @param int $post_id The ID of the product post. + * @param int $product_id The ID of the product in BigCommerce. + * @param int $variant_id The variant ID for the product. + * + * @return void + */ + protected function handle_response( $response, Cart $cart, $post_id, $product_id, $variant_id ) { + $cart_url = $cart->get_cart_url(); + /** + * Triggered when a form is successfully processed. + * + * @param string $message The message that will display to the user. + * @param array $submission The data submitted to the form. + * @param string $url The URL to redirect the user to. + * @param array $data Additional data to store with the message. + */ + do_action( 'bigcommerce/form/success', __( '1 item added to Cart', 'bigcommerce' ), $_POST, $cart_url, [ + 'key' => 'add_to_cart', + 'cart_id' => $cart->get_cart_id(), + 'post_id' => $post_id, + 'product_id' => $product_id, + 'variant_id' => $variant_id, + ] ); + wp_safe_redirect( esc_url_raw( $cart_url ), 303 ); + exit(); + } + + /** + * Handles exceptions thrown during the cart API process. + * + * @param ApiException $e The exception thrown during the API request. + * @param Cart $cart The cart instance. + * + * @return void + */ + protected function handle_exception( ApiException $e, $cart ) { + if ( strpos( (string) $e->getCode(), '4' ) === 0 ) { + $body = $e->getResponseBody(); + if ( $body && ! empty( $body->title ) ) { + $message = sprintf( '[%d] %s', $e->getCode(), $body->title ); + } else { + $message = $e->getMessage(); + } + $error = new \WP_Error( 'api_error', sprintf( + __( 'There was an error adding this product to your cart. Error message: "%s"', 'bigcommerce' ), + $message + ), [ 'exception' => [ 'message' => $e->getMessage(), 'code' => $e->getCode() ] ] ); + } else { + $error = new \WP_Error( 'api_error', __( 'There was an error adding this product to your cart. It might be out of stock or unavailable.', 'bigcommerce' ), [ + 'exception' => [ + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ], + ] ); + } + /** + * Fires when there is an API error while adding an item to the cart. + * + * @param \WP_Error $error The error object + * @param array $submission The submitted form data + * @param string $redirect The URL to redirect to after handling submission + * @param array $data Additional data about the submission + */ + do_action('bigcommerce/form/error', $error, $_POST, $cart->get_cart_url()); + } + + /** + * Validates the request to ensure the product exists and is published. + * + * @param int $post_id The ID of the product post. + * @param array $submission The form submission data. + * + * @return bool True if the request is valid, false otherwise. + */ + protected function validate_request( $post_id, $submission ) { + $post = get_post( $post_id ); + if ( empty( $post ) ) { + return false; + } + if ( Product::NAME !== $post->post_type ) { + return false; + } + if ( $post->post_status !== 'publish' ) { + return false; + } + + return true; + } + + /** + * Gets the product variant ID from the form submission. + * + * @param Product $product The product object. + * @param array $submission The form submission data. * - * @return int + * @return int The variant ID. */ - protected function get_variant_id( Product $product, $submission ) { - if ( ! empty( $submission[ 'variant_id' ] ) ) { - return (int) $submission[ 'variant_id' ]; - } - - $data = $product->get_source_data(); - - foreach ( $data->variants as $variant ) { - foreach ( $variant->option_values as $option ) { - $key = 'option-' . $option->option_id; - if ( ! isset( $submission[ $key ] ) ) { - continue 2; - } - if ( $submission[ $key ] != $option->id ) { - continue 2; - } - } - - // all options matched, we have a winner - return $variant->id; - } - - // fall back to the first variant - if ( ! empty( $data->variants ) ) { - return reset( $data->variants )->id; - } - - return 0; - } + protected function get_variant_id( Product $product, $submission ) { + if ( ! empty( $submission[ 'variant_id' ] ) ) { + return (int) $submission[ 'variant_id' ]; + } + + $data = $product->get_source_data(); + + foreach ( $data->variants as $variant ) { + foreach ( $variant->option_values as $option ) { + $key = 'option-' . $option->option_id; + if ( ! isset( $submission[ $key ] ) ) { + continue 2; + } + if ( $submission[ $key ] != $option->id ) { + continue 2; + } + } + + // all options matched, we have a winner + return $variant->id; + } + + // fall back to the first variant + if ( ! empty( $data->variants ) ) { + return reset( $data->variants )->id; + } + + return 0; + } } diff --git a/src/BigCommerce/Cart/Buy_Now.php b/src/BigCommerce/Cart/Buy_Now.php index bd1e461f..3115337f 100644 --- a/src/BigCommerce/Cart/Buy_Now.php +++ b/src/BigCommerce/Cart/Buy_Now.php @@ -1,6 +1,5 @@ get_cart_url() ); } } diff --git a/src/BigCommerce/Cart/Cache_Control.php b/src/BigCommerce/Cart/Cache_Control.php index fe5a65b6..02b8ae1f 100644 --- a/src/BigCommerce/Cart/Cache_Control.php +++ b/src/BigCommerce/Cart/Cache_Control.php @@ -6,9 +6,18 @@ use BigCommerce\Shortcodes\Cart; +/** + * Class Cache_Control + * + * Handles caching logic based on the presence of specific shortcodes in the content of a singular page. + * If certain shortcodes are found, it disables caching for that page. + */ class Cache_Control { /** - * @param string[] $shortcodes + * Checks for specific shortcodes in the content of the queried object. + * If any shortcode is found, it triggers the 'bigcommerce/do_not_cache' action to prevent caching of the page. + * + * @param string[] $shortcodes An array of shortcodes to check for in the post content. * * @return void * @action template_redirect @@ -18,6 +27,10 @@ public function check_for_shortcodes( $shortcodes ) { $object = get_queried_object(); foreach ( $shortcodes as $shortcode ) { if ( strpos( $object->post_content, sprintf( '[%s', $shortcode ) ) ) { + /** + * Fires when a BigCommerce shortcode is detected in the post content. + * This action triggers cache prevention mechanisms to ensure dynamic cart content is always fresh. + */ do_action( 'bigcommerce/do_not_cache' ); break; } @@ -26,6 +39,9 @@ public function check_for_shortcodes( $shortcodes ) { } /** + * Disables caching for the page by sending the appropriate no-cache headers + * and defining constants to prevent caching mechanisms from caching the page. + * * @return void * @action bigcommerce/do_not_cache */ diff --git a/src/BigCommerce/Cart/Cart.php b/src/BigCommerce/Cart/Cart.php index 7aeaf013..8401d9a7 100644 --- a/src/BigCommerce/Cart/Cart.php +++ b/src/BigCommerce/Cart/Cart.php @@ -19,26 +19,36 @@ use BigCommerce\Util\Cart_Item_Iterator; /** - * Class Cart - * + * Handles cart operations such as adding line items, managing cookies, and interacting with the BigCommerce API. + * * @package BigCommerce\Cart */ class Cart { + /** @var string The name of the cookie storing the cart ID */ const CART_COOKIE = 'wp-bigcommerce_cart_id'; + /** @var string The name of the cookie storing the cart item count */ const COUNT_COOKIE = 'wp-bigcommerce_cart_item_count'; - /** - * @var CartApi - */ + + /** @var CartApi The BigCommerce Cart API instance */ private $api; + /** + * Cart constructor. + * + * Initializes the Cart class with the given CartApi instance. + * + * @param CartApi $api The BigCommerce Cart API instance. + */ public function __construct( CartApi $api ) { $this->api = $api; } /** - * Get the cart ID from the cookie + * Get the cart ID from the cookie. + * + * Retrieves the cart ID from the cookie and applies any relevant filters. * - * @return string + * @return string The cart ID. */ public function get_cart_id() { $cart_id = ''; @@ -48,25 +58,27 @@ public function get_cart_id() { } /** - * Filter the cart ID to use for the current request + * Filter the cart ID to use for the current request. * - * @param string $cart_id + * @param string $cart_id The current cart ID. */ return apply_filters( 'bigcommerce/cart/cart_id', $cart_id ); } /** - * Set the cookie that contains the cart ID + * Set the cookie that contains the cart ID. * - * @param string $cart_id + * Sets a cookie with the given cart ID, applying filters to determine the cookie's lifetime. + * + * @param string $cart_id The cart ID to set in the cookie. * * @return void */ public function set_cart_id( $cart_id ) { /** - * Filter how long the cart cookie should persist + * Filter how long the cart cookie should persist. * - * @param int $lifetime The cookie lifespan in seconds + * @param int $lifetime The cookie lifespan in seconds. */ $cookie_life = apply_filters( 'bigcommerce/cart/cookie_lifetime', 30 * DAY_IN_SECONDS ); $secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ); @@ -75,13 +87,18 @@ public function set_cart_id( $cart_id ) { } /** - * @param int $product_id The BigCommerce ID of the product - * @param array $options All options and modifiers for the line item - * @param int $quantity How many to add to the cart - * @param array $modifiers Deprecated in 1.7.0, all values should be passed in $options + * Add a line item to the cart. * - * @return \BigCommerce\Api\v3\Model\Cart - * @throws ApiException + * Adds a product to the cart with the specified options, quantity, and modifiers. + * The function handles both options and modifiers and sends the data to BigCommerce. + * + * @param int $product_id The BigCommerce ID of the product. + * @param array $options All options and modifiers for the line item. + * @param int $quantity How many to add to the cart. + * @param array $modifiers Deprecated in 1.7.0, all values should be passed in $options. + * + * @return \BigCommerce\Api\v3\Model\Cart The updated cart after adding the line item. + * @throws ApiException If an error occurs while interacting with the BigCommerce API. */ public function add_line_item( $product_id, $options = [], $quantity = 1, $modifiers = [] ) { $request_data = new CartRequestData(); @@ -125,10 +142,14 @@ public function add_line_item( $product_id, $options = [], $quantity = 1, $modif } /** - * @param $certificate + * Add a gift certificate to the cart. * - * @return \BigCommerce\Api\v3\Model\Cart - * @throws ApiException + * Adds a gift certificate to the cart, sending the data to BigCommerce for processing. + * + * @param $certificate The gift certificate data to be added to the cart. + * + * @return \BigCommerce\Api\v3\Model\Cart The updated cart after adding the gift certificate. + * @throws ApiException If an error occurs while interacting with the BigCommerce API. */ public function add_gift_certificate( $certificate ) { $request_data = new CartRequestData(); @@ -156,7 +177,7 @@ private function add_request_to_cart( CartRequestData $request ) { // Add to the existing cart if ( $cart_id ) { - /* @throws ApiException if the request failes */ + /* @throws ApiException if the request fails */ $cart_response = $this->api->cartsCartIdItemsPost( $cart_id, $request ); $cart = $cart_response->getData(); } else { // either there was no cart ID passed, or the cart no longer exists, so build a new cart @@ -193,6 +214,13 @@ private function add_request_to_cart( CartRequestData $request ) { ] )->getData(); } + /** + * Sanitize the cart ID by ensuring the cart still exists + * + * @param string $cart_id The cart ID to sanitize + * + * @return string The sanitized cart ID or an empty string if not valid + */ public function sanitize_cart_id( $cart_id ) { if ( $cart_id ) { try { @@ -224,6 +252,11 @@ private function set_item_count_cookie( \BigCommerce\Api\v3\Model\Cart $cart ) { $_COOKIE[ self::COUNT_COOKIE ] = $count; } + /** + * Get the URL to the cart page + * + * @return string The URL to the cart page + */ public function get_cart_url() { $cart_page_id = get_option( Settings\Sections\Cart::OPTION_CART_PAGE_ID, 0 ); if ( empty( $cart_page_id ) ) { @@ -242,6 +275,8 @@ public function get_cart_url() { } /** + * Get the checkout URL for the given cart ID + * * @param string $cart_id The ID of the user's cart. Defaults to the ID found in the cart cookie * * @return string The URL for checking out with the given cart @@ -268,6 +303,13 @@ public function get_checkout_url( $cart_id ) { return $checkout_url; } + /** + * Get the embedded checkout URL for the given cart ID + * + * @param string $cart_id The ID of the user's cart. Defaults to the ID found in the cart cookie + * + * @return string The URL for the embedded checkout with the given cart + */ public function get_embedded_checkout_url( $cart_id ) { $cart_id = $cart_id ?: $this->get_cart_id(); if ( empty( $cart_id ) ) { @@ -302,9 +344,22 @@ private function get_channel_id() { } private function get_currency() { + /** + * Filters the currency code. + * + * This filter allows modification of the currency code being used. It returns + * the current currency code based on the configured currency. + * + * @return string The currency code. + */ return apply_filters( 'bigcommerce/currency/code', 'USD' ); } + /** + * Delete the cart by its ID + * + * @return void + */ public function delete_cart() { $cart_id = $this->get_cart_id(); if ( empty( $cart_id ) ) { diff --git a/src/BigCommerce/Cart/Cart_Mapper.php b/src/BigCommerce/Cart/Cart_Mapper.php index 75564dac..ab830a06 100644 --- a/src/BigCommerce/Cart/Cart_Mapper.php +++ b/src/BigCommerce/Cart/Cart_Mapper.php @@ -22,29 +22,34 @@ /** - * Class Cart_Mapper - * * Maps a cart from the API to a standard format usable by the - * REST API and other templates + * REST API and other templates. */ class Cart_Mapper { - /** - * @var BigCommerce_Cart - */ - private $cart; - - /** - * @var \WP_Term - */ - private $channel; - - public function __construct( BigCommerce_Cart $cart ) { - $this->cart = $cart; - } - - /** - * @return array - */ + /** + * @var BigCommerce_Cart + */ + private $cart; + + /** + * @var \WP_Term + */ + private $channel; + + /** + * Cart_Mapper constructor. + * + * @param BigCommerce_Cart $cart The cart to map. + */ + public function __construct( BigCommerce_Cart $cart ) { + $this->cart = $cart; + } + + /** + * Maps the cart data into a format for API and template usage. + * + * @return array Mapped cart data. + */ public function map() { $this->identify_channel(); $cart = [ @@ -87,7 +92,7 @@ public function map() { /** * If tax is not already included in item prices - * then we need to deduct the calulated tax from the subtotal + * then we need to deduct the calculated tax from the subtotal * as we are displaying the tax separately */ if ( $cart[ 'tax_included' ] || $tax_amount < 0 ) { diff --git a/src/BigCommerce/Cart/Cart_Menu_Item.php b/src/BigCommerce/Cart/Cart_Menu_Item.php index 69706969..1854e3d2 100644 --- a/src/BigCommerce/Cart/Cart_Menu_Item.php +++ b/src/BigCommerce/Cart/Cart_Menu_Item.php @@ -7,16 +7,30 @@ use BigCommerce\Settings\Sections\Cart; /** - * Class Cart_Menu_Item + * The Cart_Menu_Item class is responsible for modifying WordPress navigation menu items + * to display cart-related information. It specifically adds a cart item count to the menu + * item representing the cart page and ensures the proper display of this count based on + * various conditions like checkout settings and the status of the mini-cart. + * + * This class listens for the `wp_setup_nav_menu_item` filter to inject the necessary + * HTML and CSS classes into the cart menu item and modifies the menu item title to + * include a dynamic cart item count. It also provides methods to determine whether + * the cart count should be shown and verifies if a menu item corresponds to the cart page. + * + * The Cart_Menu_Item class interacts with WordPress options and applies filters to + * conditionally enable or disable cart item count display. It also provides hooks + * for customizing cart-related functionality, making it adaptable to different configurations. * * @package BigCommerce\Cart */ class Cart_Menu_Item { /** - * @param object $menu_item + * Adds classes to the cart page menu item and updates the title with the item count. + * + * @param object $menu_item The menu item object to modify. * - * @return object + * @return object The modified menu item object. * @filter wp_setup_nav_menu_item */ public function add_classes_to_cart_page( $menu_item ) { diff --git a/src/BigCommerce/Cart/Cart_Recovery.php b/src/BigCommerce/Cart/Cart_Recovery.php index e3c9b948..bd7fbc0d 100644 --- a/src/BigCommerce/Cart/Cart_Recovery.php +++ b/src/BigCommerce/Cart/Cart_Recovery.php @@ -10,11 +10,20 @@ use BigCommerce\Settings\Sections\Cart as CartSettings; /** - * Class Cart_Recovery + * The Cart_Recovery class is responsible for handling the recovery of abandoned carts. + * It interacts with BigCommerce's API to retrieve and recover abandoned carts based on + * a unique token provided in the request. It also manages the redirection process and + * the setting of cookies for recovered carts, ensuring that the user is taken to the correct + * cart page and that the abandoned cart is appropriately handled. * * @package BigCommerce\Cart */ class Cart_Recovery { + /** + * The action hook name for cart recovery. + * + * @var string + */ const ACTION = 'recover-cart'; /** @@ -30,8 +39,10 @@ class Cart_Recovery { /** * Cart_Recovery constructor. * - * @param AbandonedCartApi $api - * @param CartApi $cart + * Initializes the Cart_Recovery class with the given AbandonedCartApi and CartApi instances. + * + * @param AbandonedCartApi $api An instance of the AbandonedCartApi to interact with the BigCommerce API for cart recovery. + * @param CartApi $cart An instance of the CartApi to interact with the BigCommerce API for cart-related actions. */ public function __construct( AbandonedCartApi $api , CartApi $cart) { $this->api = $api; @@ -39,8 +50,15 @@ public function __construct( AbandonedCartApi $api , CartApi $cart) { } /** + * Handles the incoming request to recover an abandoned cart. + * + * This function retrieves the token from the query parameters, validates it, + * and then attempts to recover the abandoned cart using the BigCommerce API. + * If the cart is recovered successfully, it sets a cookie with the abandoned + * cart's ID and redirects the user to the cart page. If there is an error, + * it handles the error and redirects to the appropriate page. * - * @return string + * @return string The URL of the cart page, either with the recovered cart or as a fallback. */ public function handle_request( ) { $token = filter_input( INPUT_GET, 't', FILTER_SANITIZE_STRING ); @@ -65,6 +83,13 @@ public function handle_request( ) { } else { $destination = get_post_type_archive_link( Product::NAME ); } + /** + * Fires when an error occurs during cart recovery. + * + * @param \WP_Error $error The WordPress error object containing the error details + * @param array $_POST The POST data from the request + * @param string $destination The URL where the user will be redirected after the error + */ do_action( 'bigcommerce/form/error', $error, $_POST, $destination ); } @@ -77,7 +102,12 @@ public function handle_request( ) { } /** - * @param int $cart_page_id + * Redirects the user to the cart page. + * + * This function redirects the user to the specified cart page using the cart page ID. + * It performs the redirection and stops the script execution. + * + * @param int $cart_page_id The ID of the cart page to redirect to. */ private function redirect_to_cart( $cart_page_id ){ wp_redirect( get_permalink ( $cart_page_id ) ); @@ -85,7 +115,12 @@ private function redirect_to_cart( $cart_page_id ){ } /** - * @param int $abandoned_cart + * Sets a cookie for the recovered abandoned cart. + * + * This function creates a Cart object and sets the cart ID of the recovered abandoned cart + * to associate the user's session with the cart they are recovering. + * + * @param int $abandoned_cart The ID of the abandoned cart to be recovered. */ private function set_abandoned_cart_cookie( $abandoned_cart ){ $cart = new \BigCommerce\Cart\Cart( $this->cart_api ); diff --git a/src/BigCommerce/Cart/Checkout.php b/src/BigCommerce/Cart/Checkout.php index e8a3e646..660ce9b9 100644 --- a/src/BigCommerce/Cart/Checkout.php +++ b/src/BigCommerce/Cart/Checkout.php @@ -9,28 +9,56 @@ use BigCommerce\Settings\Sections\Cart as Cart_Settings; /** - * Class Buy_Now - * - * Handles requests from the Buy Now button for products + * Handles requests during checkout from the Buy Now button for products. */ class Checkout { + /** + * The action endpoint for the checkout process. + * + * @var string + */ const ACTION = 'checkout'; + + /** + * The factory instance for creating BigCommerce API clients. + * + * @var Api_Factory + */ private $api_factory; + /** + * Constructor. + * + * @param Api_Factory $api_factory Factory for creating API clients. + */ public function __construct( Api_Factory $api_factory ) { $this->api_factory = $api_factory; } /** - * @param string $cart_id - * @param CartApi $cart_api + * Handle the request for redirecting to checkout. + * + * This method processes a checkout request based on the provided cart ID and redirects the user + * to the appropriate checkout page or URL. If the cart ID is missing or an error occurs, + * an error is displayed to the user. + * + * @param string $cart_id The ID of the cart to check out. + * @param CartApi $cart_api The BigCommerce Cart API client. * * @return void + * * @action bigcommerce/action_endpoint/ . self::ACTION */ public function handle_request( $cart_id, CartApi $cart_api ) { if ( empty( $cart_id ) ) { $error = new \WP_Error( 'checkout', __( 'Please add some items to your cart before checking out.', 'bigcommerce' ) ); + /** + * Fires when a form error occurs during checkout. + * + * @param \WP_Error $error The WordPress error object containing the error code and message + * @param array $submission The submitted form data ($_POST) + * @param string $redirect The URL to redirect to after error handling + */ do_action( 'bigcommerce/form/error', $error, $_POST, home_url( '/' ) ); return; @@ -57,6 +85,13 @@ public function handle_request( $cart_id, CartApi $cart_api ) { exit(); } catch ( \Exception $e ) { $error = new \WP_Error( 'api_error', __( "We're having some difficulty redirecting you to checkout. Please try again.", 'bigcommerce' ) ); + /** + * Fires when a form error occurs during checkout. + * + * @param \WP_Error $error The WordPress error object containing the error code and message + * @param array $submission The submitted form data ($_POST) + * @param string $redirect The URL to redirect to after error handling + */ do_action( 'bigcommerce/form/error', $error, $_POST, home_url( '/' ) ); return; diff --git a/src/BigCommerce/Cart/Item_Counter.php b/src/BigCommerce/Cart/Item_Counter.php index f1415bce..fc03b7e7 100644 --- a/src/BigCommerce/Cart/Item_Counter.php +++ b/src/BigCommerce/Cart/Item_Counter.php @@ -5,11 +5,21 @@ use BigCommerce\Util\Cart_Item_Iterator; /** - * Class Item_Counter - * - * Counts the number of items in a cart + * Provides functionality to count the number of items in a BigCommerce cart. + * This excludes child items, such as product variations or bundled items. */ class Item_Counter { + /** + * Count the total number of items in a BigCommerce cart. + * + * This method iterates through the items in the provided cart and calculates the total count. + * It excludes child items (e.g., variations or bundled items) from the total count. If the quantity + * of an item is available, it adds the quantity to the count; otherwise, it assumes a quantity of 1. + * + * @param \BigCommerce\Api\v3\Model\Cart $cart The cart object to count items for. + * + * @return int The total number of items in the cart. + */ public static function count_bigcommerce_cart( \BigCommerce\Api\v3\Model\Cart $cart ) { return array_reduce( iterator_to_array( Cart_Item_Iterator::factory( $cart ) ), diff --git a/src/BigCommerce/Cart/Mini_Cart.php b/src/BigCommerce/Cart/Mini_Cart.php index 712c1786..2fdb9708 100644 --- a/src/BigCommerce/Cart/Mini_Cart.php +++ b/src/BigCommerce/Cart/Mini_Cart.php @@ -5,12 +5,21 @@ use BigCommerce\Pages\Cart_Page; use BigCommerce\Pages\Checkout_Page; +/** + * Manages the configuration and display logic for the mini-cart widget in BigCommerce. + */ class Mini_Cart { /** - * @param array $config + * Adds mini-cart configuration to the global JavaScript configuration array. + * + * This method appends the `mini_cart` configuration to the provided configuration array. + * It determines whether the mini-cart widget is enabled and passes this value. + * + * @param array $config The existing JavaScript configuration array. + * + * @return array The modified configuration array with mini-cart settings. * - * @return array * @filter bigcommerce/js_config */ public function add_mini_cart_config( $config ) { diff --git a/src/BigCommerce/Checkout/Customer_Login.php b/src/BigCommerce/Checkout/Customer_Login.php index 112a6644..bcb80191 100644 --- a/src/BigCommerce/Checkout/Customer_Login.php +++ b/src/BigCommerce/Checkout/Customer_Login.php @@ -15,35 +15,42 @@ use BigCommerce\Taxonomies\Channel\Connections; /** - * Class Customer_Login - * - * Handle customer login logic on checkout + * Handles customer login logic during the checkout process. * * @package BigCommerce\Checkout */ class Customer_Login { /** - * @var Onboarding_Api + * @var Onboarding_Api API for merchant onboarding processes. */ private $onboarding; /** - * @var Store_Api + * @var Store_Api API for interacting with the store. */ private $store; + /** + * Constructor for the `Customer_Login` class. + * + * @param Onboarding_Api $onboarding API instance for onboarding. + * @param Store_Api $store API instance for store interactions. + */ public function __construct( Onboarding_Api $onboarding, Store_Api $store ) { $this->onboarding = $onboarding; $this->store = $store; } - /** - * Get new login token for the customer - * - * @param string $checkout_url + * Generate a new login token for the customer and update the checkout URL. + * + * Depending on whether the store is created through the onboarding process + * or uses custom API credentials, it generates a login token for the customer. + * + * @param string $checkout_url The original checkout URL. + * + * @return string The updated checkout URL with the login token appended. * - * @return string * @filter bigcommerce/checkout/url */ public function set_login_token_for_checkout( $checkout_url ) { diff --git a/src/BigCommerce/Checkout/Requirements_Notice.php b/src/BigCommerce/Checkout/Requirements_Notice.php index d3e89d9b..0d57ef22 100644 --- a/src/BigCommerce/Checkout/Requirements_Notice.php +++ b/src/BigCommerce/Checkout/Requirements_Notice.php @@ -9,29 +9,36 @@ use BigCommerce\Settings\Screens\Settings_Screen; /** - * Class Requirements_Notice - * * Shows a notice if the required configuration for checkout is not complete */ class Requirements_Notice { - const REFRESH = 'bigcommerce_checkout_requirements_refresh'; - - /** - * @var Setup_Status - */ - private $status; - - public function __construct( Setup_Status $status ) { - $this->status = $status; - } - - /** - * Checks the BigCommerce API to verify that checkout requirements - * have been met. - * - * @return void - * @action admin_notices - */ + /** + * Action for refreshing the checkout requirements status cache. + * @var string + */ + const REFRESH = 'bigcommerce_checkout_requirements_refresh'; + + /** + * @var Setup_Status Handles the setup status for the BigCommerce store. + */ + private $status; + + /** + * Constructor to initialize the setup status. + * + * @param Setup_Status $status Instance of Setup_Status to manage the store's setup status. + */ + public function __construct( Setup_Status $status ) { + $this->status = $status; + } + + /** + * Checks the BigCommerce API to verify that checkout requirements + * have been met. Displays admin notices if requirements are not satisfied. + * + * @return void + * @action admin_notices + */ public function check_requirements() { $status = $this->status->get_current_status(); $notices = []; @@ -101,12 +108,12 @@ private function get_settings_dashboard_url() { return admin_url( 'edit.php?post_type=' . Product::NAME . '&page=' . Settings_Screen::NAME ); } - /** - * Admin post handler to refresh the checkout requirements status cache - * - * @return void - * @action admin_post_ . self::REFRESH - */ + /** + * Admin post handler to refresh the checkout requirements status cache. + * + * @return void + * @action admin_post_ . self::REFRESH + */ public function refresh_status() { check_admin_referer( self::REFRESH ); @@ -141,27 +148,29 @@ private function refresh_url( $redirect = '' ) { return $url; } - /** - * Disable embedded checkout if SSL is not supported - * - * @param int|bool $option - * - * @return int|bool - * @filter pre_option_ . Cart::OPTION_EMBEDDED_CHECKOUT - */ - public function filter_embedded_checkout( $option ) { - if ( ! $this->can_enable_embedded_checkout() ) { - return 0; // not `false`, because WP would ignore it - } - - return $option; - } - - /** - * @return bool - * @filter bigcommerce/checkout/can_embed - */ - public function can_enable_embedded_checkout() { - return (bool) $this->status->is_ssl(); - } + /** + * Disables embedded checkout if SSL is not supported. + * + * @param int|bool $option Current option value. + * + * @return int|bool Modified option value. + * @filter pre_option_ . Cart::OPTION_EMBEDDED_CHECKOUT + */ + public function filter_embedded_checkout( $option ) { + if ( ! $this->can_enable_embedded_checkout() ) { + return 0; // not `false`, because WP would ignore it + } + + return $option; + } + + /** + * Determines if embedded checkout can be enabled. + * + * @return bool True if SSL is supported, false otherwise. + * @filter bigcommerce/checkout/can_embed + */ + public function can_enable_embedded_checkout() { + return (bool) $this->status->is_ssl(); + } } diff --git a/src/BigCommerce/Compatibility/Akismet/Akismet.php b/src/BigCommerce/Compatibility/Akismet/Akismet.php index 3084bd01..fce482b3 100644 --- a/src/BigCommerce/Compatibility/Akismet/Akismet.php +++ b/src/BigCommerce/Compatibility/Akismet/Akismet.php @@ -4,13 +4,32 @@ use BigCommerce\Compatibility\Spam_Checker; +/** + * This class implements the Spam_Checker interface and uses the Akismet API to determine if a submission is considered spam. + * It checks submissions against the Akismet service based on the provided details such as user IP, email, name, and referrer. + * + * The `is_spam` method makes an HTTP request to the Akismet API, and if the submission is flagged as spam, it updates the Akismet spam count. + * The Akismet API key must be set in WordPress options for the class to function. + * + * Usage: + * $akismet = new Akismet(); + * $result = $akismet->is_spam( $submission ); + * + * @package BigCommerce + * @subpackage Compatibility + */ class Akismet implements Spam_Checker { /** - * @param array $submission - * - * @return boolean - */ + * Checks whether a submission is flagged as spam by the Akismet service. + * + * This method sends the submission details to Akismet's API for spam checking. If the submission is flagged as spam, + * the spam count in WordPress options is updated. It returns `true` if the submission is spam, otherwise `false`. + * + * @param array $submission An associative array containing the submission data, including first name, last name, email, etc. + * + * @return bool Returns `true` if the submission is spam, otherwise `false`. + */ public function is_spam( array $submission ) { if ( ! function_exists( 'akismet_init' ) ) { return false; diff --git a/src/BigCommerce/Compatibility/Matomo/Matomo.php b/src/BigCommerce/Compatibility/Matomo/Matomo.php index f27851c6..9fb6070e 100644 --- a/src/BigCommerce/Compatibility/Matomo/Matomo.php +++ b/src/BigCommerce/Compatibility/Matomo/Matomo.php @@ -3,14 +3,29 @@ namespace BigCommerce\Compatibility\Matomo; +/** + * This class integrates BigCommerce with Matomo (formerly Piwik), a web analytics platform. It provides functionality for + * modifying the JavaScript configuration for tracking user interactions with custom variables in Matomo. + * The class specifically hooks into the `bigcommerce/js_config` filter to add custom variables to the JavaScript configuration. + * + * @package BigCommerce + * @subpackage Compatibility + */ class Matomo { /** - * @param array $config - * - * @return array - * @filter bigcommerce/js_config - */ + * Adds custom variables to the JavaScript configuration for Matomo tracking. + * + * This method hooks into the `bigcommerce/js_config` filter and modifies the configuration array to include Matomo's + * custom variables. By default, it includes a custom variable for the BigCommerce channel (BC_Channel), which can be extended + * for more custom tracking variables. + * + * @param array $config The existing JavaScript configuration array that can be modified. + * + * @return array The modified configuration array with the added Matomo custom variables. + * + * @filter bigcommerce/js_config + */ public function js_config( $config ) { $config['matomo'] = [ // Matomo supports 5 custom variables diff --git a/src/BigCommerce/Compatibility/Spam_Checker.php b/src/BigCommerce/Compatibility/Spam_Checker.php index 238f5b4d..17582805 100644 --- a/src/BigCommerce/Compatibility/Spam_Checker.php +++ b/src/BigCommerce/Compatibility/Spam_Checker.php @@ -2,12 +2,20 @@ namespace BigCommerce\Compatibility; +/** + * Defines the contract for a spam checker, which can be used to determine whether a given content is considered spam. + * + * @package BigCommerce + * @subpackage Compatibility + */ interface Spam_Checker { - /** - * @param array $content + /** + * Checks whether the given content is spam. * - * @return boolean + * @param array $content The content to check for spam, typically containing fields like author name, email, etc. + * + * @return boolean True if the content is considered spam, otherwise false. */ public function is_spam( array $content ); diff --git a/src/BigCommerce/Compatibility/Template_Compatibility.php b/src/BigCommerce/Compatibility/Template_Compatibility.php index 7544f028..1f29e41f 100644 --- a/src/BigCommerce/Compatibility/Template_Compatibility.php +++ b/src/BigCommerce/Compatibility/Template_Compatibility.php @@ -3,18 +3,25 @@ namespace BigCommerce\Compatibility; - +/** + * Provides compatibility functionality to override WooCommerce page templates. + * This class handles the removal of WooCommerce-specific templates from the page template hierarchy. + * + * @package BigCommerce + * @subpackage Compatibility + */ class Template_Compatibility { /** - * If a theme has a page template that assumes WooCommerce - * functions will be available (e.g., a page-cart.php), - * remove that template from the hierarchy. + * Overrides the page template for WooCommerce pages that assume WooCommerce functions will be available. + * + * If a theme has a page template (e.g., `page-cart.php`) that relies on WooCommerce functions, + * this method will remove that template from the hierarchy to prevent errors if WooCommerce is not present. * - * @param string $template - * @param string $type - * @param array $templates + * @param string $template The current template being used for the page. + * @param string $type The type of template being overridden. + * @param array $templates List of available templates in the hierarchy. * - * @return string + * @return string The modified template, or the original template if no changes were made. * @filter page_template */ public function override_page_template( $template, $type, $templates ) { diff --git a/src/BigCommerce/Compatibility/Themes/Flatsome/Flatsome.php b/src/BigCommerce/Compatibility/Themes/Flatsome/Flatsome.php index 662b8a39..74e70a69 100644 --- a/src/BigCommerce/Compatibility/Themes/Flatsome/Flatsome.php +++ b/src/BigCommerce/Compatibility/Themes/Flatsome/Flatsome.php @@ -6,17 +6,41 @@ use BigCommerce\Compatibility\Themes\Theme; use BigCommerce\Templates\Login_Form; +/** + * This class defines the compatibility layer for the Flatsome theme in the BigCommerce ecosystem. + * It specifies the supported version of the theme, maps template files to corresponding template classes, + * and loads additional compatibility functions. + * + * @package BigCommerce + * @subpackage Compatibility\Themes\Flatsome + */ class Flatsome extends Theme { - protected $supported_version = '3.10.1'; - - protected $templates = [ - 'myaccount/account-links.php' => Templates\Account_Links::class, - 'myaccount/form-login.php' => Login_Form::class, - ]; - - public function load_compat_functions() { - include_once( dirname( __FILE__ ) . '/functions.php' ); - } + /** + * The supported version of the Flatsome theme. + * + * @var string + */ + protected $supported_version = '3.10.1'; + + /** + * Template files mapped to their corresponding template classes. + * + * @var array + */ + protected $templates = [ + 'myaccount/account-links.php' => Templates\Account_Links::class, + 'myaccount/form-login.php' => Login_Form::class, + ]; + + /** + * Loads the compatibility functions for the Flatsome theme. + * + * This method includes the necessary functions for the Flatsome theme compatibility, + * which are stored in a separate file for better maintainability. + */ + public function load_compat_functions() { + include_once( dirname( __FILE__ ) . '/functions.php' ); + } } \ No newline at end of file diff --git a/src/BigCommerce/Compatibility/Themes/Flatsome/Templates/Account_Links.php b/src/BigCommerce/Compatibility/Themes/Flatsome/Templates/Account_Links.php index d9fc90d9..4177a7f6 100644 --- a/src/BigCommerce/Compatibility/Themes/Flatsome/Templates/Account_Links.php +++ b/src/BigCommerce/Compatibility/Themes/Flatsome/Templates/Account_Links.php @@ -9,46 +9,85 @@ use BigCommerce\Pages\Wishlist_Page; use BigCommerce\Settings\Sections\Wishlists as Wishlist_Settings; - +/** + * This class is responsible for generating the account links for the user's account page in the Flatsome theme. + * It provides links to the order history, addresses, and wish lists (if enabled), and manages the data + * passed to the template for rendering. + * + * @package BigCommerce + * @subpackage Compatibility\Themes\Flatsome\Templates + */ class Account_Links extends Controller { - const LINKS = 'links'; - - protected $template = 'compatibility/themes/flatsome/myaccount/account-links.php'; - + /** + * Constant to define the key for links in the data array. + */ + const LINKS = 'links'; - protected function parse_options( array $options ) { - $defaults = []; + /** + * The template file used to render the account links. + * + * @var string + */ + protected $template = 'compatibility/themes/flatsome/myaccount/account-links.php'; - return wp_parse_args( $options, $defaults ); - } + /** + * Merges the provided options with default values. + * + * This method takes an array of options and merges it with the default options + * before returning the final options array. + * + * @param array $options The options to merge with defaults. + * + * @return array The merged options. + */ + protected function parse_options( array $options ) { + $defaults = []; - public function get_data() { - $data = $this->options; - $data[ self::LINKS ] = $this->get_links(); - return $data; - } + return wp_parse_args( $options, $defaults ); + } - protected function get_links() { + /** + * Retrieves the data to be passed to the template. + * + * This method prepares the data array to include the account links and any other necessary options + * for the template rendering. + * + * @return array The data array, including the account links. + */ + public function get_data() { + $data = $this->options; + $data[ self::LINKS ] = $this->get_links(); + return $data; + } - $links = [ - [ - 'title' => __( 'Order History', 'bigcommerce'), - 'url' => get_permalink( get_option( Orders_Page::NAME, 0 ) ), - ], - [ - 'title' => __( 'Addresses', 'bigcommerce'), - 'url' => get_permalink( get_option( Address_Page::NAME, 0 ) ), - ], - ]; + /** + * Generates the links for the user's account page. + * + * This method creates an array of links, including order history, addresses, and wish lists (if enabled), + * and returns the array of links to be displayed in the template. + * + * @return array An array of links with titles and URLs. + */ + protected function get_links() { + $links = [ + [ + 'title' => __( 'Order History', 'bigcommerce'), + 'url' => get_permalink( get_option( Orders_Page::NAME, 0 ) ), + ], + [ + 'title' => __( 'Addresses', 'bigcommerce'), + 'url' => get_permalink( get_option( Address_Page::NAME, 0 ) ), + ], + ]; - if ( get_option( Wishlist_Settings::ENABLED ) ) { - $links[] = [ - 'title' => __( 'Wish Lists', 'bigcommerce'), - 'url' => get_permalink( get_option( Wishlist_Page::NAME, 0 ) ), - ]; - } + if ( get_option( Wishlist_Settings::ENABLED ) ) { + $links[] = [ + 'title' => __( 'Wish Lists', 'bigcommerce'), + 'url' => get_permalink( get_option( Wishlist_Page::NAME, 0 ) ), + ]; + } - return $links; - } + return $links; + } } \ No newline at end of file diff --git a/src/BigCommerce/Compatibility/Themes/Null_Theme.php b/src/BigCommerce/Compatibility/Themes/Null_Theme.php index 3f246391..762bbc41 100644 --- a/src/BigCommerce/Compatibility/Themes/Null_Theme.php +++ b/src/BigCommerce/Compatibility/Themes/Null_Theme.php @@ -3,7 +3,13 @@ namespace BigCommerce\Compatibility\Themes; - +/** + * A placeholder class for themes that do not require any compatibility layer. + * This class extends the base Theme class but does not add any additional functionality. + * + * @package BigCommerce + * @subpackage Compatibility\Themes + */ class Null_Theme extends Theme { } \ No newline at end of file diff --git a/src/BigCommerce/Compatibility/Themes/Theme.php b/src/BigCommerce/Compatibility/Themes/Theme.php index 271d2410..ad3d7ed6 100644 --- a/src/BigCommerce/Compatibility/Themes/Theme.php +++ b/src/BigCommerce/Compatibility/Themes/Theme.php @@ -3,17 +3,24 @@ namespace BigCommerce\Compatibility\Themes; - +/** + * Base class for themes, providing functionality for rendering templates and checking version compatibility. + * Specific theme implementations should extend this class and define templates and their supported versions. + * + * @package BigCommerce + * @subpackage Compatibility\Themes + */ abstract class Theme { protected $supported_version = '1.0.0'; protected $templates = []; /** - * Render theme template + * Render the specified theme template with options. + * + * @param string $template_name The name of the template to render. + * @param array $options The options to pass to the template controller. * - * @param string $template_name - * @param array $options * @return void */ public function render_template( $template_name, $options = [] ) { @@ -24,10 +31,24 @@ public function render_template( $template_name, $options = [] ) { } } + /** + * Load theme-specific compatibility functions. + * + * This method is intended to be overridden by child classes to load additional functions. + * + * @return void + */ public function load_compat_functions() { return; } + /** + * Check if the theme version is supported. + * + * @param string $version The version to check. + * + * @return bool True if the version is supported, false otherwise. + */ public function is_version_supported( $version ) { if ( version_compare( $version, $this->supported_version, '>=' ) ) { return true; diff --git a/src/BigCommerce/Compatibility/Themes/Theme_Factory.php b/src/BigCommerce/Compatibility/Themes/Theme_Factory.php index 15d971e4..29396527 100644 --- a/src/BigCommerce/Compatibility/Themes/Theme_Factory.php +++ b/src/BigCommerce/Compatibility/Themes/Theme_Factory.php @@ -5,6 +5,14 @@ use BigCommerce\Compatibility\Themes\Flatsome\Flatsome; +/** + * Factory class for creating theme instances based on template name and version. + * It supports creating instances of themes such as Flatsome and provides a fallback to a Null_Theme + * when the template is unsupported or the version is not compatible. + * + * @package BigCommerce + * @subpackage Compatibility\Themes + */ class Theme_Factory { /** @@ -17,7 +25,12 @@ class Theme_Factory { ]; /** - * @return BigCommerce\Compatibility\Themes\Theme + * Creates an instance of the appropriate theme based on the template and version. + * + * @param string $template The theme template name. + * @param string $version The theme version. + * + * @return BigCommerce\Compatibility\Themes\Theme The theme instance, or a Null_Theme if unsupported. */ public function make( $template, $version = '1.0.0' ) { if ( isset( $this->supported[ $template ] ) ) { diff --git a/src/BigCommerce/Compatibility/WooCommerce/Cart.php b/src/BigCommerce/Compatibility/WooCommerce/Cart.php index d0fa6914..c688d8c9 100644 --- a/src/BigCommerce/Compatibility/WooCommerce/Cart.php +++ b/src/BigCommerce/Compatibility/WooCommerce/Cart.php @@ -7,19 +7,45 @@ use BigCommerce\Api\v3\Api\CartApi; use BigCommerce\Cart\Cart_Mapper; +/** + * This class handles the interaction between the WooCommerce cart and BigCommerce's cart API. + * It retrieves cart information, including the cart subtotal, and maps it to a WooCommerce-compatible format. + * + * @package BigCommerce + * @subpackage Compatibility\WooCommerce + */ class Cart { + /** + * The count of items in the cart. + * + * @var int + */ public $cart_contents_count = 0; - /** @var CartApi */ + /** + * The instance of BigCommerce CartApi for interacting with the BigCommerce cart. + * + * @var CartApi + */ private $bc_cart_api; + /** + * Cart constructor. + * + * @param CartApi $bc_cart_api The BigCommerce CartApi instance used to interact with the BigCommerce cart. + */ public function __construct( CartApi $bc_cart_api ) { $this->bc_cart_api = $bc_cart_api; $this->cart_contents_count = filter_input( INPUT_COOKIE, BC_Cart::COUNT_COOKIE, FILTER_SANITIZE_NUMBER_INT ) ?: 0; } + /** + * Get the subtotal for the current cart. + * + * @return string|int The formatted subtotal of the cart or 0 if the cart amount is unavailable. + */ public function get_cart_subtotal() { $bc_cart = $this->get_bc_cart(); diff --git a/src/BigCommerce/Compatibility/WooCommerce/Facade.php b/src/BigCommerce/Compatibility/WooCommerce/Facade.php index 05b8bb07..1ca523b7 100644 --- a/src/BigCommerce/Compatibility/WooCommerce/Facade.php +++ b/src/BigCommerce/Compatibility/WooCommerce/Facade.php @@ -2,15 +2,28 @@ namespace BigCommerce\Compatibility\WooCommerce; +/** + * This class acts as a facade for the WooCommerce cart, providing a simplified interface for interacting with the BigCommerce cart. + * + * @package BigCommerce + * @subpackage Compatibility\WooCommerce + */ class Facade { /** - * @var BigCommerce\Compatibility\WooCommerce\Cart + * The instance of the BigCommerce WooCommerce Cart class. + * + * @var Cart */ public $cart; + /** + * Facade constructor. + * + * @param Cart $cart The Cart instance used to interact with the BigCommerce cart. + */ public function __construct( Cart $cart ) { $this->cart = $cart; } - + } \ No newline at end of file diff --git a/src/BigCommerce/Compatibility/woocommerce-functions.php b/src/BigCommerce/Compatibility/woocommerce-functions.php index 7c6be50c..d6f91fd8 100644 --- a/src/BigCommerce/Compatibility/woocommerce-functions.php +++ b/src/BigCommerce/Compatibility/woocommerce-functions.php @@ -14,6 +14,11 @@ use BigCommerce\Settings\Sections\Cart as Cart_Settings; if ( ! function_exists( 'wc' ) ) { + /** + * Retrieves the WooCommerce facade instance from the container. + * + * @return Compatibility The WooCommerce facade instance. + */ function wc() { $container = bigcommerce()->container(); return $container[ Compatibility::WC_FACADE ]; @@ -21,6 +26,13 @@ function wc() { } if ( ! function_exists( 'wc_get_template_part' ) ) { + /** + * Retrieves a template part for WooCommerce. + * + * @param string $slug The template slug. + * @param string $name The template part name (optional). + * @return string The rendered template part. + */ function wc_get_template_part( $slug, $name = '' ) { $template = "{$slug}.php"; if ( $name ) { @@ -31,6 +43,15 @@ function wc_get_template_part( $slug, $name = '' ) { } if ( ! function_exists( 'wc_get_template' ) ) { + /** + * Retrieves and renders a WooCommerce template. + * + * @param string $template_name The template file name. + * @param array $args Arguments to pass to the template. + * @param string $template_path The path to the template (optional). + * @param string $default_path The default path (optional). + * @return void + */ function wc_get_template( $template_name, $args = [], $template_path = '', $default_path = '' ) { $container = bigcommerce()->container(); $container[ Compatibility::THEME ]->render_template( $template_name, $args ); @@ -38,42 +59,84 @@ function wc_get_template( $template_name, $args = [], $template_path = '', $defa } if ( ! function_exists( 'wc_get_template_html' ) ) { + /** + * Retrieves the HTML content for a WooCommerce template. + * + * @param string $template_name The template file name. + * @param array $args Arguments to pass to the template. + * @param string $template_path The path to the template (optional). + * @param string $default_path The default path (optional). + * @return string An empty string. + */ function wc_get_template_html( $template_name, $args = [], $template_path = '', $default_path = '' ) { return ''; } } if ( ! function_exists( 'wc_locate_template' ) ) { + /** + * Locates a WooCommerce template. + * + * @param string $template_name The template file name. + * @param string $template_path The path to the template (optional). + * @param string $default_path The default path (optional). + * @return string An empty string. + */ function wc_locate_template( $template_name, $template_path = '', $default_path = '' ) { return ''; } } if ( ! function_exists( 'woocommerce_mini_cart' ) ) { + /** + * Displays the mini cart for WooCommerce. + * + * @return void + */ function woocommerce_mini_cart() { printf( '
    %s
    ', esc_html( __( 'Loading', 'bigcommerce' ) ) ); } } if ( ! function_exists( 'wc_get_cart_url' ) ) { + /** + * Retrieves the URL of the cart page. + * + * @return string The cart page URL. + */ function wc_get_cart_url() { return get_permalink( get_option( Cart_Page::NAME, 0 ) ); } } if ( ! function_exists( 'wc_get_checkout_url' ) ) { + /** + * Retrieves the URL of the checkout page. + * + * @return string The checkout page URL. + */ function wc_get_checkout_url() { return get_permalink( get_option( Checkout_Page::NAME, 0 ) ); } } if ( ! function_exists( 'is_cart' ) ) { + /** + * Checks if the current page is the cart page. + * + * @return bool True if the current page is the cart page, false otherwise. + */ function is_cart() { return is_page( get_option( Cart_Page::NAME, 0 ) ); } } if ( ! function_exists( 'is_checkout' ) ) { + /** + * Checks if the current page is the checkout page. + * + * @return bool True if the current page is the checkout page, false otherwise. + */ function is_checkout() { if ( ! (bool) get_option( Cart_Settings::OPTION_EMBEDDED_CHECKOUT, false ) ) { return false; @@ -83,61 +146,111 @@ function is_checkout() { } if ( ! function_exists( 'is_account_page' ) ) { + /** + * Checks if the current page is the account page. + * + * @return bool True if the current page is the account page, false otherwise. + */ function is_account_page() { return is_page( get_option( Account_Page::NAME, 0 ) ); } } if ( ! function_exists( 'is_product' ) ) { + /** + * Checks if the current page is a product page. + * + * @return bool True if the current page is a product page, false otherwise. + */ function is_product() { return is_singular( Product::NAME ); } } if ( ! function_exists( 'is_shop' ) ) { + /** + * Checks if the current page is the shop page. + * + * @return bool True if the current page is the shop page, false otherwise. + */ function is_shop() { return is_archive( Product::NAME ); } } if ( ! function_exists( 'is_product_category' ) ) { + /** + * Checks if the current page is a product category page. + * + * @return bool True if the current page is a product category page, false otherwise. + */ function is_product_category() { return is_tax( Product_Category::NAME ); } } if ( ! function_exists( 'is_product_tag' ) ) { + /** + * Checks if the current page is a product tag page. + * + * @return bool False, as the function always returns false. + */ function is_product_tag() { return false; } } if ( ! function_exists( 'is_product_taxonomy' ) ) { + /** + * Checks if the current page is a product taxonomy page. + * + * @return bool True if the current page is a product taxonomy page, false otherwise. + */ function is_product_taxonomy() { return is_tax( Product_Category::NAME ); } } if ( ! function_exists( 'wc_get_image_size' ) ) { + /** + * Retrieves the WooCommerce image size. + * + * @return string An empty string. + */ function wc_get_image_size() { return ''; } } if ( ! function_exists( 'wc_print_notices' ) ) { + /** + * Prints WooCommerce notices. + * + * @return string An empty string. + */ function wc_print_notices() { return ''; } } if ( ! function_exists( 'woocommerce_reset_loop' ) ) { + /** + * Resets the WooCommerce loop. + * + * @return string An empty string. + */ function woocommerce_reset_loop() { return ''; } } if ( ! function_exists( 'wc_get_page_id' ) ) { + /** + * Retrieves the ID of a WooCommerce page. + * + * @return int The ID of the WooCommerce page, or -1 if not found. + */ function wc_get_page_id() { - return ''; + return -1; } -} \ No newline at end of file +} diff --git a/src/BigCommerce/Container/Accounts.php b/src/BigCommerce/Container/Accounts.php index 7c6bb1c9..acc13fbd 100644 --- a/src/BigCommerce/Container/Accounts.php +++ b/src/BigCommerce/Container/Accounts.php @@ -23,58 +23,199 @@ /** * Class Accounts * + * Handles the registration and initialization of various account-related services + * such as login, registration, countries, wishlists, profile settings, and customer groups. + * * @package BigCommerce\Container */ class Accounts extends Provider { - const LOGIN = 'accounts.login'; - const REGISTER = 'accounts.register'; - const COUNTRIES = 'accounts.countries'; - const COUNTRIES_PATH = 'accounts.countries.path'; - const DELETE_ADDRESS = 'accounts.delete_address'; - const NAV_MENU = 'accounts.nav_menu'; - const SUB_NAV = 'accounts.sub_nav'; - const USER_PROFILE = 'accounts.user_profile'; - const GROUP_PROXY = 'accounts.groups.proxy'; - const PASSWORD_RESET = 'accounts.password_reset'; + /** + * The constant for the login service. + * Represents the key for the accounts login service in the container. + * + * @var string + */ + const LOGIN = 'accounts.login'; + + /** + * The constant for the register service. + * Represents the key for the accounts registration service in the container. + * + * @var string + */ + const REGISTER = 'accounts.register'; + + /** + * The constant for the countries service. + * Represents the key for the accounts countries service in the container. + * + * @var string + */ + const COUNTRIES = 'accounts.countries'; + + /** + * The constant for the countries data file path. + * Represents the key for the path to the countries data file in the container. + * + * @var string + */ + const COUNTRIES_PATH = 'accounts.countries.path'; + + /** + * The constant for the delete address service. + * Represents the key for the accounts delete address service in the container. + * + * @var string + */ + const DELETE_ADDRESS = 'accounts.delete_address'; + + /** + * The constant for the navigation menu service. + * Represents the key for the accounts navigation menu service in the container. + * + * @var string + */ + const NAV_MENU = 'accounts.nav_menu'; + + /** + * The constant for the sub-navigation service. + * Represents the key for the accounts sub-navigation service in the container. + * + * @var string + */ + const SUB_NAV = 'accounts.sub_nav'; + + /** + * The constant for the user profile settings service. + * Represents the key for the accounts user profile settings service in the container. + * + * @var string + */ + const USER_PROFILE = 'accounts.user_profile'; + + /** + * The constant for the customer group proxy service. + * Represents the key for the accounts customer group proxy service in the container. + * + * @var string + */ + const GROUP_PROXY = 'accounts.groups.proxy'; + + /** + * The constant for the password reset service. + * Represents the key for the accounts password reset service in the container. + * + * @var string + */ + const PASSWORD_RESET = 'accounts.password_reset'; + + /** + * The constant for the channel settings service. + * Represents the key for the accounts channel settings service in the container. + * + * @var string + */ const CHANNEL_SETTINGS = 'accounts.channel_settings'; - const PUBLIC_WISHLIST = 'accounts.wishlist.public'; - const WISHLIST_ROUTER = 'accounts.wishlist.router'; - const WISHLIST_CREATE = 'accounts.wishlist.create'; - const WISHLIST_EDIT = 'accounts.wishlist.edit'; - const WISHLIST_DELETE = 'accounts.wishlist.delete'; - const WISHLIST_ADD = 'accounts.wishlist.add_item'; - const WISHLIST_REMOVE = 'accounts.wishlist.remove_item'; + /** + * The constant for the public wishlist service. + * Represents the key for the public wishlist service in the container. + * + * @var string + */ + const PUBLIC_WISHLIST = 'accounts.wishlist.public'; + + /** + * The constant for the wishlist router service. + * Represents the key for the wishlist router service in the container. + * + * @var string + */ + const WISHLIST_ROUTER = 'accounts.wishlist.router'; + + /** + * The constant for the wishlist creation service. + * Represents the key for the wishlist creation service in the container. + * + * @var string + */ + const WISHLIST_CREATE = 'accounts.wishlist.create'; + + /** + * The constant for the wishlist edit service. + * Represents the key for the wishlist edit service in the container. + * + * @var string + */ + const WISHLIST_EDIT = 'accounts.wishlist.edit'; + + /** + * The constant for the wishlist delete service. + * Represents the key for the wishlist delete service in the container. + * + * @var string + */ + const WISHLIST_DELETE = 'accounts.wishlist.delete'; + + /** + * The constant for the wishlist add item service. + * Represents the key for the wishlist add item service in the container. + * + * @var string + */ + const WISHLIST_ADD = 'accounts.wishlist.add_item'; + + /** + * The constant for the wishlist remove item service. + * Represents the key for the wishlist remove item service in the container. + * + * @var string + */ + const WISHLIST_REMOVE = 'accounts.wishlist.remove_item'; + + /** + * The constant for the wishlist add item view service. + * Represents the key for the wishlist add item view service in the container. + * + * @var string + */ const WISHLIST_ADD_ITEM_VIEW = 'accounts.wishlist.add_item_view'; - public function register( Container $container ) { - $this->login( $container ); - $this->countries( $container ); - $this->profile( $container ); - $this->addresses( $container ); - $this->customer_groups( $container ); - $this->wishlists( $container ); - $this->passwords( $container ); - $this->channel_settings( $container ); - } + /** + * Registers various services into the container + * + * @param Container $container The dependency injection container + */ + public function register( Container $container ) { + $this->login( $container ); + $this->countries( $container ); + $this->profile( $container ); + $this->addresses( $container ); + $this->customer_groups( $container ); + $this->wishlists( $container ); + $this->passwords( $container ); + $this->channel_settings( $container ); + } /** - * Handle login logic methods + * Registers and handles login-related actions. * - * @param Container $container + * @param Container $container The dependency injection container */ - private function login( Container $container ) { - $container[ self::LOGIN ] = function ( Container $container ) { - return new Login( $container[ Api::FACTORY ] ); - }; + private function login( Container $container ) { + /** Registering login service */ + $container[ self::LOGIN ] = function ( Container $container ) { + return new Login( $container[ Api::FACTORY ] ); + }; - $container[ self::REGISTER ] = function ( Container $container ) { - return new Register( $container[ Api::FACTORY ], new Connections() ); - }; + /** Registering register service */ + $container[ self::REGISTER ] = function ( Container $container ) { + return new Register( $container[ Api::FACTORY ], new Connections() ); + }; - add_action( 'wp_login', $this->create_callback( 'connect_customer_id', function ( $username, $user ) use ( $container ) { - $container[ self::LOGIN ]->connect_customer_id( $username, $user ); - } ), 10, 2 ); + add_action( 'wp_login', $this->create_callback( 'connect_customer_id', function ( $username, $user ) use ( $container ) { + $container[ self::LOGIN ]->connect_customer_id( $username, $user ); + } ), 10, 2 ); add_filter( 'login_url', $this->create_callback( 'login_url', function ( $url, $redirect, $reauth ) use ( $container ) { return $container[ self::LOGIN ]->login_url( $url, $redirect, $reauth ); @@ -124,113 +265,136 @@ private function login( Container $container ) { add_action( 'user_register', $this->create_callback( 'create_customer_from_admin', function ( $user_id, $userdata ) use ( $container ) { $container[ self::REGISTER ]->maybe_create_new_customer( $user_id, $userdata ); } ), 10, 2 ); + } /** - * Register countries container and handle requests for it + * Registers and handles country-related services and requests. * - * @param Container $container + * @param Container $container The dependency injection container */ - private function countries( Container $container ) { - $container[ self::COUNTRIES ] = function ( Container $container ) { - return new Countries( $container[ self::COUNTRIES_PATH ] ); - }; - - $container[ self::COUNTRIES_PATH ] = function ( Container $container ) { - $file = plugin_dir_path( $container['plugin_file'] ) . 'assets/data/countries.json'; + private function countries( Container $container ) { + /** Registering countries service */ + $container[ self::COUNTRIES ] = function ( Container $container ) { + return new Countries( $container[ self::COUNTRIES_PATH ] ); + }; + + /** Registering countries path */ + $container[ self::COUNTRIES_PATH ] = function ( Container $container ) { + $file = plugin_dir_path( $container['plugin_file'] ) . 'assets/data/countries.json'; + + /** + * Filters the path of the countries data file. + * + * @param string $file Countries data json file path + */ + return apply_filters( 'bigcommerce/countries/data_file', $file ); + }; + + add_filter( 'bigcommerce/countries/data', $this->create_callback( 'countries', function ( $data ) use ( $container ) { + return $container[ self::COUNTRIES ]->get_countries(); + } ), 5, 1 ); - /** - * Filters countries data file. - * - * @param string $file Countries data json file path. - */ - return apply_filters( 'bigcommerce/countries/data_file', $file ); - }; - - add_filter( 'bigcommerce/countries/data', $this->create_callback( 'countries', function ( $data ) use ( $container ) { - return $container[ self::COUNTRIES ]->get_countries(); - } ), 5, 1 ); $countries_js_config = $this->create_callback( 'countries_js_config', function ( $config ) use ( $container ) { return $container[ self::COUNTRIES ]->js_config( $config ); } ); + add_filter( 'bigcommerce/js_config', $countries_js_config, 10, 1 ); + add_filter( 'bigcommerce/admin/js_config', $countries_js_config, 10, 1 ); - } + } /** - * Handle profile container requests + * Registers profile-related services and actions. * - * @param Container $container + * @param Container $container The dependency injection container */ - private function profile( Container $container ) { - $container[ self::NAV_MENU ] = function ( Container $container ) { - return new Nav_Menu(); - }; - - add_filter( 'wp_setup_nav_menu_item', $this->create_callback( 'loginregister_menu_item', function ( $item ) use ( $container ) { - return $container[ self::NAV_MENU ]->filter_account_menu_items( $item ); - } ), 10, 1 ); - - $container[ self::SUB_NAV ] = function ( Container $container ) { - return new Sub_Nav(); - }; - add_filter( 'the_content', $this->create_callback( 'account_subnav', function ( $content ) use ( $container ) { - return $container[ self::SUB_NAV ]->add_subnav_above_content( $content ); - } ), 10, 1 ); - - $container[ self::USER_PROFILE ] = function ( Container $container ) { - return new User_Profile_Settings(); - }; - $render_profile_settings = $this->create_callback( 'render_profile_settings', function ( $user ) use ( $container ) { - $container[ self::USER_PROFILE ]->render_profile_settings( $user ); - } ); - $save_profile_settings = $this->create_callback( 'save_profile_settings', function ( $user_id ) use ( $container ) { - $container[ self::USER_PROFILE ]->save_profile_settings( $user_id ); - } ); - add_action( 'show_user_profile', $render_profile_settings, 10, 1 ); - add_action( 'edit_user_profile', $render_profile_settings, 10, 1 ); - add_action( 'personal_options_update', $save_profile_settings, 10, 1 ); - add_action( 'edit_user_profile_update', $save_profile_settings, 10, 1 ); - } + private function profile( Container $container ) { + /** Registering navigation menu service */ + $container[ self::NAV_MENU ] = function ( Container $container ) { + return new Nav_Menu(); + }; + + add_filter( 'wp_setup_nav_menu_item', $this->create_callback( 'loginregister_menu_item', function ( $item ) use ( $container ) { + return $container[ self::NAV_MENU ]->filter_account_menu_items( $item ); + } ), 10, 1 ); + + /** Registering sub-navigation service */ + $container[ self::SUB_NAV ] = function ( Container $container ) { + return new Sub_Nav(); + }; + + add_filter( 'the_content', $this->create_callback( 'account_subnav', function ( $content ) use ( $container ) { + return $container[ self::SUB_NAV ]->add_subnav_above_content( $content ); + } ), 10, 1 ); + + /** Registering user profile settings service */ + $container[ self::USER_PROFILE ] = function ( Container $container ) { + return new User_Profile_Settings(); + }; + + /** Action to render and save profile settings */ + $render_profile_settings = $this->create_callback( 'render_profile_settings', function ( $user ) use ( $container ) { + $container[ self::USER_PROFILE ]->render_profile_settings( $user ); + } ); + $save_profile_settings = $this->create_callback( 'save_profile_settings', function ( $user_id ) use ( $container ) { + $container[ self::USER_PROFILE ]->save_profile_settings( $user_id ); + } ); + + add_action( 'show_user_profile', $render_profile_settings, 10, 1 ); + add_action( 'edit_user_profile', $render_profile_settings, 10, 1 ); + add_action( 'personal_options_update', $save_profile_settings, 10, 1 ); + add_action( 'edit_user_profile_update', $save_profile_settings, 10, 1 ); + } /** - * @param Container $container + * Registers and handles address-related services and actions. + * + * @param Container $container The dependency injection container */ - private function addresses( Container $container ) { - $container[ self::DELETE_ADDRESS ] = function ( Container $container ) { - return new Delete_Address_Handler(); - }; - add_action( 'parse_request', $this->create_callback( 'handle_delete_address', function () use ( $container ) { - $container[ self::DELETE_ADDRESS ]->handle_request( $_POST ); - } ), 10, 0 ); - } + private function addresses( Container $container ) { + /** Registering delete address handler */ + $container[ self::DELETE_ADDRESS ] = function ( Container $container ) { + return new Delete_Address_Handler(); + }; - /** - * @param Container $container - */ - private function customer_groups( Container $container ) { - $container[ self::GROUP_PROXY ] = function ( Container $container ) { - return new Customer_Group_Proxy(); - }; - add_filter( 'bigcommerce/customer/group_info', $this->create_callback( 'set_customer_group_info', function ( $info, $group_id ) use ( $container ) { - return $container[ self::GROUP_PROXY ]->filter_group_info( $info, $group_id ); - } ), 10, 2 ); - } + add_action( 'parse_request', $this->create_callback( 'handle_delete_address', function () use ( $container ) { + $container[ self::DELETE_ADDRESS ]->handle_request( $_POST ); + } ), 10, 0 ); + } /** - * Handle wishlists container logic + * Registers customer group-related services and actions. * - * @param Container $container + * @param Container $container The dependency injection container */ - private function wishlists( Container $container ) { - $container[ self::PUBLIC_WISHLIST ] = function ( Container $container ) { - return new Wishlist_Request_Parser( $container[ Api::FACTORY ]->wishlists() ); - }; + private function customer_groups( Container $container ) { + /** Registering customer group proxy service */ + $container[ self::GROUP_PROXY ] = function ( Container $container ) { + return new Customer_Group_Proxy(); + }; - add_action( 'parse_request', $this->create_callback( 'public_wishlist_request', function ( \WP $wp ) use ( $container ) { - $container[ self::PUBLIC_WISHLIST ]->setup_wishlist_request( $wp ); - } ), 10, 1 ); + add_filter( 'bigcommerce/customer/group_info', $this->create_callback( 'set_customer_group_info', function ( $info, $group_id ) use ( $container ) { + return $container[ self::GROUP_PROXY ]->filter_group_info( $info, $group_id ); + } ), 10, 2 ); + } + /** + * Registers and handles wishlist-related services and actions. + * + * @param Container $container The dependency injection container + */ + private function wishlists( Container $container ) { + /** Registering public wishlist parser */ + $container[ self::PUBLIC_WISHLIST ] = function ( Container $container ) { + return new Wishlist_Request_Parser( $container[ Api::FACTORY ]->wishlists() ); + }; + + add_action( 'parse_request', $this->create_callback( 'public_wishlist_request', function ( \WP $wp ) use ( $container ) { + $container[ self::PUBLIC_WISHLIST ]->setup_wishlist_request( $wp ); + } ), 10, 1 ); + + /** Initialize the wishlist request router */ $container[ self::WISHLIST_ROUTER ] = function ( Container $container ) { return new Wishlist_Actions\Request_Router(); }; @@ -238,89 +402,102 @@ private function wishlists( Container $container ) { add_action( 'bigcommerce/action_endpoint/' . Wishlist_Actions\Request_Router::ACTION, $this->create_callback( 'handle_wishlist_action', function ( $args ) use ( $container ) { $container[ self::WISHLIST_ROUTER ]->handle_request( $args ); } ), 10, 1 ); - + + /** Initialize the create wishlist action handler */ $container[ self::WISHLIST_CREATE ] = function ( Container $container ) { return new Wishlist_Actions\Create_Wishlist( $container[ Api::FACTORY ]->wishlists() ); }; - + add_action( 'bigcommerce/wishlist_endpoint/' . Wishlist_Actions\Create_Wishlist::ACTION, $this->create_callback( 'create_wishlist', function ( $args ) use ( $container ) { $container[ self::WISHLIST_CREATE ]->handle_request( $args ); } ), 10, 1 ); - + + /** Initialize the edit wishlist action handler */ $container[ self::WISHLIST_EDIT ] = function ( Container $container ) { return new Wishlist_Actions\Edit_Wishlist( $container[ Api::FACTORY ]->wishlists() ); }; - + add_action( 'bigcommerce/wishlist_endpoint/' . Wishlist_Actions\Edit_Wishlist::ACTION, $this->create_callback( 'edit_wishlist', function ( $args ) use ( $container ) { $container[ self::WISHLIST_EDIT ]->handle_request( $args ); } ), 10, 1 ); - + + /** Initialize the delete wishlist action handler */ $container[ self::WISHLIST_DELETE ] = function ( Container $container ) { return new Wishlist_Actions\Delete_Wishlist( $container[ Api::FACTORY ]->wishlists() ); }; - + add_action( 'bigcommerce/wishlist_endpoint/' . Wishlist_Actions\Delete_Wishlist::ACTION, $this->create_callback( 'delete_wishlist', function ( $args ) use ( $container ) { $container[ self::WISHLIST_DELETE ]->handle_request( $args ); } ), 10, 1 ); - + + /** Initialize the add item to wishlist action handler */ $container[ self::WISHLIST_ADD ] = function ( Container $container ) { return new Wishlist_Actions\Add_Item( $container[ Api::FACTORY ]->wishlists() ); }; - + add_action( 'bigcommerce/wishlist_endpoint/' . Wishlist_Actions\Add_Item::ACTION, $this->create_callback( 'add_wishlist_item', function ( $args ) use ( $container ) { $container[ self::WISHLIST_ADD ]->handle_request( $args ); } ), 10, 1 ); - + + /** Initialize the remove item from wishlist action handler */ $container[ self::WISHLIST_REMOVE ] = function ( Container $container ) { return new Wishlist_Actions\Remove_Item( $container[ Api::FACTORY ]->wishlists() ); }; - + add_action( 'bigcommerce/wishlist_endpoint/' . Wishlist_Actions\Remove_Item::ACTION, $this->create_callback( 'remove_wishlist_item', function ( $args ) use ( $container ) { $container[ self::WISHLIST_REMOVE ]->handle_request( $args ); } ), 10, 1 ); - + + /** Initialize the add item view to product single page */ $container[ self::WISHLIST_ADD_ITEM_VIEW ] = function ( Container $container ) { return new Add_Item_View( $container[ Api::FACTORY ]->wishlists() ); }; - + + /** Add item view to product single page template */ $add_item_view_to_product_single = $this->create_callback( 'add_item_view_to_product_single', function ( $data, $template, $options ) use ( $container ) { return $container[ self::WISHLIST_ADD_ITEM_VIEW ]->filter_product_single_template( $data, $template, $options ); } ); add_action( 'bigcommerce/template=components/products/product-single.php/data', $add_item_view_to_product_single, 10, 3 ); // Decided not to show on the shortcode single //add_action( 'bigcommerce/template=components/products/product-shortcode-single.php/data', $add_item_view_to_product_single, 10, 3 ); - } - - /** - * Handle passwords container and hooks - * @param Container $container - */ - private function passwords( Container $container ) { - $container[ self::PASSWORD_RESET ] = function ( Container $container ) { - return new Password_Reset( $container[ Api::FACTORY ]->customer() ); - }; - - add_action( 'after_password_reset', $this->create_callback( 'sync_reset_password', function ( $user, $password ) use ( $container ) { - $container[ self::PASSWORD_RESET ]->sync_reset_password_with_bigcommerce( $user, $password ); - } ), 10, 2 ); - - add_action( 'profile_update', $this->create_callback( 'sync_changed_password', function ( $user, $old_user_data ) use ( $container ) { - $container[ self::PASSWORD_RESET ]->sync_password_change_with_bigcommerce( $user, $old_user_data ); - } ), 10, 2 ); - } - - private function channel_settings( Container $container ) { - $container[ self::CHANNEL_SETTINGS ] = function ( Container $container ) { - return new Channel_Settings( new Connections(), $container[ Api::FACTORY ]->customers() ); - }; - - add_action( 'bigcommerce/sync_global_logins', $this->create_callback( 'sync_global_logins', function () use ( $container ) { - $container[ self::CHANNEL_SETTINGS ]->sync_global_logins(); - } ) ); - - add_action( 'bigcommerce/channel/promote', $this->create_callback( 'schedule_global_logins_sync', function () use ( $container ) { - $container[ self::CHANNEL_SETTINGS ]->schedule_sync(); - } ) ); - } - -} + } + + /** + * Handle passwords container and hooks + * @param Container $container + */ + private function passwords( Container $container ) { + /** Initialize password reset action handler */ + $container[ self::PASSWORD_RESET ] = function ( Container $container ) { + return new Password_Reset( $container[ Api::FACTORY ]->customer() ); + }; + + add_action( 'after_password_reset', $this->create_callback( 'sync_reset_password', function ( $user, $password ) use ( $container ) { + $container[ self::PASSWORD_RESET ]->sync_reset_password_with_bigcommerce( $user, $password ); + } ), 10, 2 ); + + add_action( 'profile_update', $this->create_callback( 'sync_changed_password', function ( $user, $old_user_data ) use ( $container ) { + $container[ self::PASSWORD_RESET ]->sync_password_change_with_bigcommerce( $user, $old_user_data ); + } ), 10, 2 ); + } + + /** + * Handle channel settings container and hooks + * @param Container $container + */ + private function channel_settings( Container $container ) { + /** Initialize channel settings action handler */ + $container[ self::CHANNEL_SETTINGS ] = function ( Container $container ) { + return new Channel_Settings( new Connections(), $container[ Api::FACTORY ]->customers() ); + }; + + add_action( 'bigcommerce/sync_global_logins', $this->create_callback( 'sync_global_logins', function () use ( $container ) { + $container[ self::CHANNEL_SETTINGS ]->sync_global_logins(); + } ) ); + + add_action( 'bigcommerce/channel/promote', $this->create_callback( 'schedule_global_logins_sync', function () use ( $container ) { + $container[ self::CHANNEL_SETTINGS ]->schedule_sync(); + } ) ); + } + + } diff --git a/src/BigCommerce/Container/Amp.php b/src/BigCommerce/Container/Amp.php index 97a702ec..e82b0d64 100644 --- a/src/BigCommerce/Container/Amp.php +++ b/src/BigCommerce/Container/Amp.php @@ -1,9 +1,4 @@ providers( $container ); $this->events( $container ); @@ -96,7 +137,7 @@ private function events( Container $container ) { add_filter( 'bigcommerce/template=components/products/product-title.php/options', $this->create_callback( 'view_product_title', function( $options, $template ) use ( $container ) { return $container[ self::VIEW_PRODUCT ]->add_tracking_attributes_to_permalink( $options, $template ); }), 10, 3 ); - + add_filter( \BigCommerce\Settings\Sections\Analytics::TRACK_BY_HOOK, $this->create_callback( 'change_track_by_options', function( $track_data ) use ( $container ) { return $container[ self::VIEW_PRODUCT ]->change_track_data( $track_data ); }), 10, 1 ); diff --git a/src/BigCommerce/Container/Api.php b/src/BigCommerce/Container/Api.php index 1779c063..462e1c7a 100644 --- a/src/BigCommerce/Container/Api.php +++ b/src/BigCommerce/Container/Api.php @@ -16,25 +16,102 @@ use Pimple\Container; /** - * Class API + * Manages the registration and configuration of the BigCommerce API client and related services. + * Registers various services such as API client, cache handler, and configuration. * * @package BigCommerce\Container */ class Api extends Provider { - const API_VALID = 'api.configuration.valid'; + /** + * Constant representing the valid API configuration state. + * + * @var string + */ + const API_VALID = 'api.configuration.valid'; + + /** + * Constant representing the API configuration renewal service. + * + * @var string + */ const API_CONFIG_RENEWAL = 'api.configuration.config'; - const CONFIG_COMPLETE = 'api.configuration.complete'; + /** + * Constant representing the completion state of the API configuration. + * + * @var string + */ + const CONFIG_COMPLETE = 'api.configuration.complete'; + + /** + * Constant representing the cache handler service. + * + * @var string + */ const CACHE_HANDLER = 'api.cache_handler'; - const CLIENT = 'api.client'; - const CONFIG = 'api.configuration'; - const CLIENT_ID = 'api.client_id'; + + /** + * Constant representing the API client service. + * + * @var string + */ + const CLIENT = 'api.client'; + + /** + * Constant representing the API configuration service. + * + * @var string + */ + const CONFIG = 'api.configuration'; + + /** + * Constant representing the API client ID service. + * + * @var string + */ + const CLIENT_ID = 'api.client_id'; + + /** + * Constant representing the API client secret service. + * + * @var string + */ const CLIENT_SECRET = 'api.client_secret'; - const ACCESS_TOKEN = 'api.access_token'; - const HOST = 'api.host'; - const FACTORY = 'api.factory'; - const TIMEOUT = 'api.timeout'; - const HEADERS = 'api.headers'; + + /** + * Constant representing the API access token service. + * + * @var string + */ + const ACCESS_TOKEN = 'api.access_token'; + + /** + * Constant representing the API host service. + * + * @var string + */ + const HOST = 'api.host'; + + /** + * Constant representing the API factory service. + * + * @var string + */ + const FACTORY = 'api.factory'; + + /** + * Constant representing the API timeout configuration. + * + * @var string + */ + const TIMEOUT = 'api.timeout'; + + /** + * Constant representing the API request headers service. + * + * @var string + */ + const HEADERS = 'api.headers'; /** * Register api client container diff --git a/src/BigCommerce/Container/Assets.php b/src/BigCommerce/Container/Assets.php index 22b04d63..6e2765a3 100644 --- a/src/BigCommerce/Container/Assets.php +++ b/src/BigCommerce/Container/Assets.php @@ -1,105 +1,226 @@ admin( $container ); - $this->frontend( $container ); - } - - public function admin( Container $container ) { - $container[ self::ADMIN_SCRIPTS ] = function ( Container $container ) { - return new Admin\Scripts( $container[ self::PATH ], $container[ self::VERSION ], $container[ self::ADMIN_CONFIG ], $container[ self::ADMIN_LOCALIZATIONN ] ); - }; - - $container[ self::ADMIN_STYLES ] = function ( Container $container ) { - return new Admin\Styles( $container[ self::PATH ], $container[ self::VERSION ] ); - }; - - $container[ self::ADMIN_CONFIG ] = function( Container $container ) { - return new Admin\JS_Config( $container[ self::PATH ] ); - }; - - $container[ self::ADMIN_LOCALIZATIONN ] = function( Container $container ) { - return new Admin\JS_Localization(); - }; - - add_action( 'admin_enqueue_scripts', $this->create_callback( 'admin_admin_enqueue_scripts', function () use ( $container ) { - $container[ self::ADMIN_SCRIPTS ]->enqueue_scripts(); - $container[ self::ADMIN_STYLES ]->enqueue_styles(); - } ), 9, 0 ); - - add_action( 'admin_enqueue_scripts', $this->create_callback( 'admin_remove_google_sitekit_script_on_bc_admin_pages', function ( $hook ) { - if ( strpos( get_current_screen()->id, 'bigcommerce') !== false ) { - wp_dequeue_script( 'googlesitekit-base' ); - } - } ), 999 ); - } - - public function frontend( Container $container ) { - $container[ self::FRONTEND_SCRIPTS ] = function ( Container $container ) { - return new Theme\Scripts( $container[ self::PATH ], $container[ self::VERSION ], $container[ self::FRONTEND_CONFIG ], $container[ self::FRONTEND_LOCALIZATION ] ); - }; - - $container[ self::FRONTEND_STYLES ] = function ( Container $container ) { - return new Theme\Styles( $container[ self::PATH ], $container[ self::VERSION ] ); - }; - - $container[ self::FRONTEND_CONFIG ] = function ( Container $container ) { - return new Theme\JS_Config( $container[ self::PATH ], new Connections() ); - }; - - $container[ self::FRONTEND_LOCALIZATION ] = function( Container $container ) { - return new Theme\JS_Localization(); - }; - - $container[ self::IMAGE_SIZES ] = function ( Container $container ) { - return new Theme\Image_Sizes(); - }; - - add_action( 'after_setup_theme', $this->create_callback( 'frontend_after_setup_theme', function () use ( $container ) { - $container[ self::IMAGE_SIZES ]->register_sizes(); - } ), 10, 0 ); - - add_action( 'wp_enqueue_scripts', $this->create_callback( 'frontend_wp_enqueue_scripts', function () use ( $container ) { - $container[ self::FRONTEND_SCRIPTS ]->enqueue_scripts(); - $container[ self::FRONTEND_STYLES ]->enqueue_styles(); - } ), 10, 0 ); - } + + /** + * Identifier for frontend image sizes service. + * + * @var string + */ + const IMAGE_SIZES = 'assets.frontend.imagesizes'; + + /** + * Registers assets in the dependency container. + * + * @param Container $container Dependency injection container. + */ + public function register( Container $container ) { + $container[ self::PATH ] = function ( Container $container ) { + return plugins_url( 'assets', $container['plugin_file'] ); + }; + + $container[ self::VERSION ] = function ( Container $container ) { + $version = Plugin::VERSION; + if ( file_exists( dirname( $container['plugin_file'] ) . '/build-timestamp.php' ) ) { + include_once( dirname( $container['plugin_file'] ) . '/build-timestamp.php' ); + } + if ( defined( 'BIGCOMMERCE_ASSETS_BUILD_TIMESTAMP' ) ) { + $version .= '-' . BIGCOMMERCE_ASSETS_BUILD_TIMESTAMP; + } + + return $version; + }; + + $this->admin( $container ); + $this->frontend( $container ); + } + + /** + * Registers admin assets and related actions. + * + * @param Container $container Dependency injection container. + * + * @action admin_enqueue_scripts Enqueues admin scripts and styles. + * @action admin_enqueue_scripts Removes conflicting Google Site Kit scripts on BigCommerce admin pages. + */ + public function admin( Container $container ) { + $container[ self::ADMIN_SCRIPTS ] = function ( Container $container ) { + return new Admin\Scripts( + $container[ self::PATH ], + $container[ self::VERSION ], + $container[ self::ADMIN_CONFIG ], + $container[ self::ADMIN_LOCALIZATIONN ] + ); + }; + + $container[ self::ADMIN_STYLES ] = function ( Container $container ) { + return new Admin\Styles( $container[ self::PATH ], $container[ self::VERSION ] ); + }; + + $container[ self::ADMIN_CONFIG ] = function ( Container $container ) { + return new Admin\JS_Config( $container[ self::PATH ] ); + }; + + $container[ self::ADMIN_LOCALIZATIONN ] = function ( Container $container ) { + return new Admin\JS_Localization(); + }; + + add_action( + 'admin_enqueue_scripts', + $this->create_callback( 'admin_admin_enqueue_scripts', function () use ( $container ) { + $container[ self::ADMIN_SCRIPTS ]->enqueue_scripts(); + $container[ self::ADMIN_STYLES ]->enqueue_styles(); + } ), + 9, + 0 + ); + + add_action( + 'admin_enqueue_scripts', + $this->create_callback( 'admin_remove_google_sitekit_script_on_bc_admin_pages', function ( $hook ) { + if ( strpos( get_current_screen()->id, 'bigcommerce' ) !== false ) { + wp_dequeue_script( 'googlesitekit-base' ); + } + } ), + 999 + ); + } + + /** + * Registers frontend assets and related actions. + * + * @param Container $container Dependency injection container. + * + * @action after_setup_theme Registers custom image sizes for the theme. + * @action wp_enqueue_scripts Enqueues frontend scripts and styles. + */ + public function frontend( Container $container ) { + $container[ self::FRONTEND_SCRIPTS ] = function ( Container $container ) { + return new Theme\Scripts( + $container[ self::PATH ], + $container[ self::VERSION ], + $container[ self::FRONTEND_CONFIG ], + $container[ self::FRONTEND_LOCALIZATION ] + ); + }; + + $container[ self::FRONTEND_STYLES ] = function ( Container $container ) { + return new Theme\Styles( $container[ self::PATH ], $container[ self::VERSION ] ); + }; + + $container[ self::FRONTEND_CONFIG ] = function ( Container $container ) { + return new Theme\JS_Config( $container[ self::PATH ], new Connections() ); + }; + + $container[ self::FRONTEND_LOCALIZATION ] = function ( Container $container ) { + return new Theme\JS_Localization(); + }; + + $container[ self::IMAGE_SIZES ] = function ( Container $container ) { + return new Theme\Image_Sizes(); + }; + + add_action( + 'after_setup_theme', + $this->create_callback( 'frontend_after_setup_theme', function () use ( $container ) { + $container[ self::IMAGE_SIZES ]->register_sizes(); + } ), + 10, + 0 + ); + + add_action( + 'wp_enqueue_scripts', + $this->create_callback( 'frontend_wp_enqueue_scripts', function () use ( $container ) { + $container[ self::FRONTEND_SCRIPTS ]->enqueue_scripts(); + $container[ self::FRONTEND_STYLES ]->enqueue_styles(); + } ), + 10, + 0 + ); + } } diff --git a/src/BigCommerce/Container/Banners.php b/src/BigCommerce/Container/Banners.php index 3778dd08..905acb0a 100644 --- a/src/BigCommerce/Container/Banners.php +++ b/src/BigCommerce/Container/Banners.php @@ -2,22 +2,38 @@ namespace BigCommerce\Container; - use BigCommerce\Banners\Banners as Banners_Manager; use Pimple\Container; - +/** + * This class is responsible for managing the banners service within the dependency injection container. + * It provides functionality to register the banners API factory and integrates banner-specific configurations + * into JavaScript settings via a filter hook. + * + * The `banners` service is registered, allowing the application to interact with the banners API and manage banner-related data. + * + * @package BigCommerce\Container + */ class Banners extends Provider { - const BANNERS = 'banners'; - - public function register( Container $container ) { - $container[ self::BANNERS ] = function ( Container $container ) { - return new Banners_Manager( $container[ Api::FACTORY ]->banners() ); - }; - - add_filter( 'bigcommerce/js_config', $this->create_callback( 'banners_js_config', function ( $config ) use ( $container ) { - return $container[ self::BANNERS ]->js_config( $config ); - } ), 10, 1 ); - } - + const BANNERS = 'banners'; + + /** + * Registers the banners service and related configuration within the container. + * + * The `banners` service is instantiated with the banners API factory, + * allowing the application to manage banners. A filter is also added + * to integrate banner-specific configurations into JavaScript settings. + * + * @param Container $container The dependency injection container used to manage services. + * @return void + */ + public function register( Container $container ) { + $container[ self::BANNERS ] = function ( Container $container ) { + return new Banners_Manager( $container[ Api::FACTORY ]->banners() ); + }; + + add_filter( 'bigcommerce/js_config', $this->create_callback( 'banners_js_config', function ( $config ) use ( $container ) { + return $container[ self::BANNERS ]->js_config( $config ); + } ), 10, 1 ); + } } diff --git a/src/BigCommerce/Container/Cart.php b/src/BigCommerce/Container/Cart.php index bf437bc0..33bdbba5 100644 --- a/src/BigCommerce/Container/Cart.php +++ b/src/BigCommerce/Container/Cart.php @@ -13,17 +13,134 @@ use BigCommerce\Cart\Mini_Cart; use Pimple\Container; +/** + * Cart service provider for managing cart-related functionality. + * + * The `Cart` class registers various cart-related services in the container, such as: + * - Menu item for the cart + * - Mini cart functionality + * - Cache control for cart and checkout pages + * - Buy Now functionality + * - Add to Cart and Cart Recovery services + * - Checkout service + * + * The class also sets up necessary action and filter hooks to integrate these services + * into the WordPress environment, ensuring that cart operations are handled effectively. + * + * @package BigCommerce\Container + */ class Cart extends Provider { - const CART_INDICATOR = 'cart.page_indicator'; - const CART_CREATOR = 'cart.page_creator'; - const MENU_ITEM = 'cart.menu_item'; - const MINI_CART = 'cart.mini_cart'; - const CACHE_CONTROL = 'cart.cache_control'; - const BUY_NOW = 'cart.buy_now'; - const ADD_TO_CART = 'cart.add_to_cart'; + + /** + * The identifier for the cart page indicator service. + * + * This constant is used to reference the service responsible for managing the cart + * page indicator functionality, helping to indicate the current state of the cart + * on the frontend. + * + * @var string + */ + const CART_INDICATOR = 'cart.page_indicator'; + + /** + * The identifier for the cart page creator service. + * + * This constant is used to reference the service that handles the creation and + * setup of the cart page, ensuring that the cart page content is properly generated + * and displayed to the user. + * + * @var string + */ + const CART_CREATOR = 'cart.page_creator'; + + /** + * The identifier for the cart menu item service. + * + * This constant is used to reference the service that manages the cart menu item, + * ensuring that the cart is properly represented in the navigation menu and allowing + * the user to interact with it. + * + * @var string + */ + const MENU_ITEM = 'cart.menu_item'; + + /** + * The identifier for the mini cart service. + * + * This constant is used to reference the service responsible for handling the + * mini cart, which typically displays a summary of the user's cart in a compact + * view, often in a header or sidebar. + * + * @var string + */ + const MINI_CART = 'cart.mini_cart'; + + /** + * The identifier for the cache control service for cart and checkout pages. + * + * This constant is used to reference the service that manages caching for cart + * and checkout pages, ensuring proper cache invalidation and preventing issues + * with stale data on these pages. + * + * @var string + */ + const CACHE_CONTROL = 'cart.cache_control'; + + /** + * The identifier for the Buy Now service. + * + * This constant is used to reference the service responsible for handling the + * Buy Now functionality, which allows users to quickly add products to their + * cart and proceed to checkout without navigating through multiple pages. + * + * @var string + */ + const BUY_NOW = 'cart.buy_now'; + + /** + * The identifier for the Add to Cart service. + * + * This constant is used to reference the service that handles the action of + * adding items to the cart, ensuring that products are properly added and the + * cart is updated accordingly. + * + * @var string + */ + const ADD_TO_CART = 'cart.add_to_cart'; + + /** + * The identifier for the Cart Recovery service. + * + * This constant is used to reference the service responsible for handling + * cart recovery, allowing users to retrieve abandoned carts and continue their + * shopping experience without losing previously added items. + * + * @var string + */ const RECOVER_FROM_CART = 'cart.recover_from_cart'; - const CHECKOUT = 'cart.checkout'; + /** + * The identifier for the Checkout service. + * + * This constant is used to reference the service that manages the checkout + * process, including handling the cart's transition to the checkout page and + * managing the user's order details. + * + * @var string + */ + const CHECKOUT = 'cart.checkout'; + + + /** + * Registers the cart-related services and hooks within the container. + * + * This method registers various cart-related services such as the menu item, mini cart, cache control, + * buy now functionality, add-to-cart functionality, and checkout services within the container. It also sets up + * action and filter hooks to manage cart behavior throughout the application. + * + * @param Container $container The dependency injection container used to manage services. + * @return void + */ public function register( Container $container ) { $this->menu_item( $container ); $this->mini_cart( $container ); @@ -55,6 +172,7 @@ private function cache_control( Container $container ) { \BigCommerce\Shortcodes\Checkout::NAME, ] ); } ), 10, 0 ); + add_action( 'bigcommerce/do_not_cache', $this->create_callback( 'do_not_cache', function () use ( $container ) { $container[ self::CACHE_CONTROL ]->do_not_cache(); } ), 10, 0 ); @@ -92,6 +210,7 @@ private function mini_cart( Container $container ) { $container[ self::MINI_CART ] = function ( Container $container ) { return new Mini_Cart(); }; + add_filter( 'bigcommerce/js_config', $this->create_callback( 'mini_cart_js_config', function ( $config ) use ( $container ) { return $container[ self::MINI_CART ]->add_mini_cart_config( $config ); } ), 10, 1 ); diff --git a/src/BigCommerce/Container/Checkout.php b/src/BigCommerce/Container/Checkout.php index 48035b83..e39296e8 100644 --- a/src/BigCommerce/Container/Checkout.php +++ b/src/BigCommerce/Container/Checkout.php @@ -9,10 +9,41 @@ use BigCommerce\Settings\Sections\Channels; use Pimple\Container; +/** + * Handles the registration of checkout-related services and actions. + * + * This class is responsible for registering the services related to the checkout + * process, such as displaying checkout requirements notices and handling customer + * login functionality during the checkout flow. + */ class Checkout extends Provider { - const REQUIREMENTS_NOTICE = 'checkout.requirements_notice'; - const LOGIN = 'checkout.customer_login'; + /** + * The identifier for the checkout requirements notice service. + * + * This constant is used to reference the service that handles displaying + * the requirements notice to the user if the checkout process requires + * additional setup or configurations. + */ + const REQUIREMENTS_NOTICE = 'checkout.requirements_notice'; + + /** + * The identifier for the customer login service during checkout. + * + * This constant is used to reference the service responsible for handling + * customer login functionality during the checkout process, including + * generating a login token for the customer. + */ + const LOGIN = 'checkout.customer_login'; + + /** + * Registers checkout-related services in the container. + * + * This method is used to register the checkout services, including the + * requirements notice and customer login services, in the container. + * + * @param Container $container The container to register the services in. + */ public function register( Container $container ) { $this->requirements( $container ); $this->customer_login( $container ); @@ -28,6 +59,7 @@ private function requirements( Container $container ) { $container[ self::REQUIREMENTS_NOTICE ]->check_requirements(); } } ), 10, 0 ); + add_action( 'admin_post_' . Requirements_Notice::REFRESH, $this->create_callback( 'refresh_checkout_requirements', function () use ( $container ) { $container[ self::REQUIREMENTS_NOTICE ]->refresh_status(); } ), 10, 0 ); @@ -49,7 +81,7 @@ private function customer_login( Container $container ) { add_filter( 'bigcommerce/checkout/url', $this->create_callback( 'checkout_url', function ( $url ) use ( $container ) { return $container[ self::LOGIN ]->set_login_token_for_checkout( $url ); } ), 10, 1 ); - + } } diff --git a/src/BigCommerce/Container/Cli.php b/src/BigCommerce/Container/Cli.php index b755f5c4..82b3c90b 100644 --- a/src/BigCommerce/Container/Cli.php +++ b/src/BigCommerce/Container/Cli.php @@ -1,9 +1,7 @@ create_callback( 'init', function () use ( $container ) { - if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { - return; - } - - $container[ self::IMPORT_PRODUCTS ]->register(); - $container[ self::UPDATE_COUNTRIES ]->register(); - $container[ self::DOCS_BUILD ]->register(); - $container[ self::DOCS_IMPORT ]->register(); - $container[ self::DEV_RESET ]->register(); - $container[ self::RESOURCE_BUILD ]->register(); - } ), 0, 0 ); - } + /** + * Identifier for the CLI Import Products service. + * + * @var string + */ + const IMPORT_PRODUCTS = 'cli.import_products'; + + /** + * Identifier for the CLI Update Countries service. + * + * @var string + */ + const UPDATE_COUNTRIES = 'cli.update_countries'; + + /** + * Identifier for the CLI Build Documentation service. + * + * @var string + */ + const DOCS_BUILD = 'cli.documentation.build'; + + /** + * Identifier for the CLI Import Documentation service. + * + * @var string + */ + const DOCS_IMPORT = 'cli.documentation.import'; + + /** + * Identifier for the CLI Reset Plugin service. + * + * @var string + */ + const DEV_RESET = 'cli.dev.reset'; + + /** + * Identifier for the CLI Build Resources service. + * + * @var string + */ + const RESOURCE_BUILD = 'cli.resources.build'; + + /** + * Registers CLI services into the Pimple container. + * + * @param Container $container The dependency injection container. + * @return void + */ + public function register( Container $container ) { + $container[ self::IMPORT_PRODUCTS ] = function ( Container $container ) { + return new Import_Products(); + }; + + $container[ self::UPDATE_COUNTRIES ] = function ( Container $container ) { + return new Update_Country_Cache( $container[ Accounts::COUNTRIES_PATH ] ); + }; + + $container[ self::DOCS_BUILD ] = function ( Container $container ) { + return new Build_Docs( dirname( $container[ 'plugin_file' ] ) ); + }; + + $container[ self::DOCS_IMPORT ] = function ( Container $container ) { + return new Import_Docs( dirname( $container[ 'plugin_file' ] ) ); + }; + + $container[ self::DEV_RESET ] = function ( Container $container ) { + return new Reset_Plugin(); + }; + + $container[ self::RESOURCE_BUILD ] = function ( Container $container ) { + return new Build_Resources( dirname( $container[ 'plugin_file' ] ) ); + }; + + add_action( 'init', $this->create_callback( 'init', function () use ( $container ) { + if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { + return; + } + + $container[ self::IMPORT_PRODUCTS ]->register(); + $container[ self::UPDATE_COUNTRIES ]->register(); + $container[ self::DOCS_BUILD ]->register(); + $container[ self::DOCS_IMPORT ]->register(); + $container[ self::DEV_RESET ]->register(); + $container[ self::RESOURCE_BUILD ]->register(); + } ), 0, 0 ); + } } \ No newline at end of file diff --git a/src/BigCommerce/Container/Compatibility.php b/src/BigCommerce/Container/Compatibility.php index b329c93a..e605eabb 100644 --- a/src/BigCommerce/Container/Compatibility.php +++ b/src/BigCommerce/Container/Compatibility.php @@ -14,13 +14,54 @@ use BigCommerce\Container\Api; use Pimple\Container; +/** + * Provides integration with various third-party services and themes, including WooCommerce, Matomo, and Akismet. + * It handles the registration of necessary services, theme compatibility, and custom functionality for BigCommerce. + * + * @package BigCommerce\Container + */ class Compatibility extends Provider { - const TEMPLATES = 'theme_compat.templates'; - const THEME = 'theme_compat.theme'; - const WC_FACADE = 'woo_compat.wc_facade'; - const MATOMO = 'compatibility.matomo'; - const SPAM_CHECKER = 'compatibility.spam_checker'; + /** + * Template compatibility service. + * + * @var string + */ + const TEMPLATES = 'theme_compat.templates'; + + /** + * Theme compatibility service. + * + * @var string + */ + const THEME = 'theme_compat.theme'; + + /** + * WooCommerce facade service. + * + * @var string + */ + const WC_FACADE = 'woo_compat.wc_facade'; + + /** + * Matomo tracking service. + * + * @var string + */ + const MATOMO = 'compatibility.matomo'; + + /** + * Akismet spam checker service. + * + * @var string + */ + const SPAM_CHECKER = 'compatibility.spam_checker'; + + /** + * Registers the necessary services and actions for compatibility with external plugins and themes. + * + * @param Container $container The container to register services with. + */ public function register( Container $container ) { $container[ self::TEMPLATES ] = function ( Container $container ) { return new Template_Compatibility(); @@ -67,7 +108,7 @@ public function register( Container $container ) { remove_filter( 'the_content', 'flatsome_contentfix' ); } } ) ); - + add_action( 'init', $this->create_callback( 'woo_compat_theme_flatsome_replace_wc_related_shortcodes', function () { if ( get_option( 'template' ) !== 'flatsome') { return; @@ -92,7 +133,7 @@ public function register( Container $container ) { include_once( dirname( $container[ 'plugin_file' ] ) . '/src/BigCommerce/Compatibility/wordpress-5-dot-1.php' ); } } ), 10, 0 ); - + add_action( 'pre_option_woocommerce_myaccount_page_id', $this->create_callback( 'woo_compat_filter_myaccount_page_id', function () { if ( is_user_logged_in() ) { return get_option( Account_Page::NAME, 0 ); diff --git a/src/BigCommerce/Container/Currency.php b/src/BigCommerce/Container/Currency.php index df423576..a6cf61bf 100644 --- a/src/BigCommerce/Container/Currency.php +++ b/src/BigCommerce/Container/Currency.php @@ -6,12 +6,52 @@ use BigCommerce\Currency\Formatter_Factory; use Pimple\Container; +/** + * Currency container provider class. + * + * This class provides the necessary bindings for currency functionality, including + * currency code, currency formatter, and related services. It handles the registration + * of currency-related services and hooks for filtering currency values in BigCommerce. + */ class Currency extends Provider { - const CURRENCY = 'currency'; - const FORMATTER = 'currency.formatter'; - const FACTORY = 'currency.formatter.factory'; - const CURRENCY_CODE = 'currency.code'; + + /** + * Constant for the currency service identifier. + * + * @var string + */ + const CURRENCY = 'currency'; + /** + * Constant for the currency formatter service identifier. + * + * @var string + */ + const FORMATTER = 'currency.formatter'; + + /** + * Constant for the currency formatter factory service identifier. + * + * @var string + */ + const FACTORY = 'currency.formatter.factory'; + + /** + * Constant for the currency code service identifier. + * + * @var string + */ + const CURRENCY_CODE = 'currency.code'; + + /** + * Registers the services and hooks related to currency functionality. + * + * This method binds the currency manager, formatter, and formatter factory to the + * container. It also sets up various filters for modifying currency values and currency + * codes based on the configured currency for the store. + * + * @param Container $container The container instance to register services with. + */ public function register( Container $container ) { $container[ self::CURRENCY ] = function ( Container $container ) { return new Currency_Manager(); diff --git a/src/BigCommerce/Container/Editor.php b/src/BigCommerce/Container/Editor.php index 77af4f7d..8b5b1c67 100644 --- a/src/BigCommerce/Container/Editor.php +++ b/src/BigCommerce/Container/Editor.php @@ -12,17 +12,57 @@ use BigCommerce\Settings\Sections\Wishlists as Wishlist_Settings; /** - * Class Editor + * Loads behavior relevant to the admin post editor, including rendering custom buttons, + * templates, and Gutenberg blocks within the WordPress admin interface. It also handles + * the integration of the Gutenberg editor with BigCommerce blocks and assets. * - * Load behavior relevant to the admin post editor + * @package BigCommerce\Container */ class Editor extends Provider { - const SHORTCODE_BUTTON = 'admin.shortcode_button'; - const UI_DIALOG = 'admin.ui_dialog'; - const GUTENBERG_BLOCKS = 'gutenberg.blocks'; - const GUTENBERG_MIGRATE = 'gutenberg.migrate'; - const STYLES = 'gutenberg.styles'; - + /** + * Constant for the shortcode button identifier. + * + * @var string + */ + const SHORTCODE_BUTTON = 'admin.shortcode_button'; + + /** + * Constant for the UI dialog identifier. + * + * @var string + */ + const UI_DIALOG = 'admin.ui_dialog'; + + /** + * Constant for the Gutenberg blocks identifier. + * + * @var string + */ + const GUTENBERG_BLOCKS = 'gutenberg.blocks'; + + /** + * Constant for the Gutenberg migration identifier. + * + * @var string + */ + const GUTENBERG_MIGRATE = 'gutenberg.migrate'; + + /** + * Constant for the styles identifier. + * + * @var string + */ + const STYLES = 'gutenberg.styles'; + + /** + * Registers the necessary components for the editor, including buttons, dialog templates, + * and Gutenberg blocks. + * + * This function initializes and sets up the custom behavior for the WordPress admin post + * editor, integrating custom buttons and templates for a more enhanced editing experience. + * + * @param Container $container The dependency injection container. + */ public function register( Container $container ) { $this->render_button( $container ); $this->render_dialog_template( $container ); @@ -49,6 +89,7 @@ private function render_dialog_template( Container $container ) { $render_callback = $this->create_callback( 'render_editor_dialog_template', function () use ( $container ) { echo $container[ self::UI_DIALOG ]->render_dialog_once(); } ); + add_action( 'enqueue_block_editor_assets', $this->create_callback( 'block_editor_enqueue_dialog_template', function() use ( $container, $render_callback ) { $current_screen = get_current_screen(); @@ -58,10 +99,11 @@ private function render_dialog_template( Container $container ) { if ( did_action( 'admin_enqueue_scripts' ) ) { // if the Gutenberg plugin is enabled, the action will already be called $render_callback(); - } else { // if using the Block Editor in WP core, no HTML has been rendered, so delay the output + } else { add_action( 'admin_enqueue_scripts', $render_callback, 10, 0 ); } }), 10, 0 ); + add_action( 'admin_print_footer_scripts', $render_callback, 10, 0 ); // if the block editor is disabled, print scripts in the footer add_filter( 'bigcommerce/admin/js_config', $this->create_callback( 'editor_dialog_js_config', function ( $config ) use ( $container ) { diff --git a/src/BigCommerce/Container/Forms.php b/src/BigCommerce/Container/Forms.php index 2f703d57..21a2616e 100644 --- a/src/BigCommerce/Container/Forms.php +++ b/src/BigCommerce/Container/Forms.php @@ -17,19 +17,97 @@ use BigCommerce\Forms\Switch_Currency_Handler; use Pimple\Container; +/** + * Forms class handles various form actions within BigCommerce, such as registration, address updates, product reviews, and more. + * It registers form handlers and provides functionality to process form actions, handle errors, success messages, redirects, and messaging. + * This class is part of the container and utilizes dependency injection to manage the various handlers for each action. + * + * @package BigCommerce\Container + */ class Forms extends Provider { + /** + * Constant for deleting an address form action. + * + * @var string + */ const DELETE_ADDRESS = 'forms.delete_address'; + + /** + * Constant for the user registration form action. + * + * @var string + */ const REGISTER = 'forms.register'; + + /** + * Constant for the product review form action. + * + * @var string + */ const REVIEW = 'forms.review'; - const UPDATE_ADDRESS = 'forms.udpate_address'; + + /** + * Constant for updating an address form action. + * + * @var string + */ + const UPDATE_ADDRESS = 'forms.update_address'; + + /** + * Constant for updating a user's profile form action. + * + * @var string + */ const UPDATE_PROFILE = 'forms.update_profile'; + + /** + * Constant for purchasing a gift certificate form action. + * + * @var string + */ const GIFT_CERTIFICATE = 'forms.purchase_gift_certificate'; + + /** + * Constant for form errors. + * + * @var string + */ const ERRORS = 'forms.errors'; + + /** + * Constant for form success messages. + * + * @var string + */ const SUCCESS = 'forms.success'; + + /** + * Constant for form redirects. + * + * @var string + */ const REDIRECTS = 'forms.redirects'; + + /** + * Constant for form messaging. + * + * @var string + */ const MESSAGING = 'forms.messaging'; + + /** + * Constant for switching currency in a form. + * + * @var string + */ const SWITCH_CURRENCY = 'forms.switch_currency'; + /** + * Registers all the form actions and handlers into the container. + * This method sets up actions for handling form submissions, errors, success, redirects, and messaging. + * + * @param Container $container The dependency injection container. + */ public function register( Container $container ) { $this->actions( $container ); @@ -41,12 +119,14 @@ public function register( Container $container ) { } private function actions( Container $container ) { - /** - * Handle all form submissions with a bc-action argument - */ add_action( 'parse_request', $this->create_callback( 'handle_form_action', function () use ( $container ) { $action = filter_var_array( $_REQUEST, [ 'bc-action' => FILTER_SANITIZE_STRING ] ); if ( $action['bc-action'] ) { + /** + * Fires when a BigCommerce form action is submitted. + * + * @param array $submission The sanitized form submission data (typically from $_REQUEST) + */ do_action( 'bigcommerce/form/action=' . $action['bc-action'], stripslashes_deep( $_REQUEST ) ); } } ), 10, 0 ); @@ -54,6 +134,7 @@ private function actions( Container $container ) { $container[ self::DELETE_ADDRESS ] = function ( Container $container ) { return new Delete_Address_Handler(); }; + add_action( 'bigcommerce/form/action=' . Delete_Address_Handler::ACTION, $this->create_callback( 'delete_address', function ( $submission ) use ( $container ) { $container[ self::DELETE_ADDRESS ]->handle_request( $submission ); } ), 10, 1 ); @@ -61,6 +142,7 @@ private function actions( Container $container ) { $container[ self::UPDATE_ADDRESS ] = function ( Container $container ) { return new Update_Address_Handler(); }; + add_action( 'bigcommerce/form/action=' . Update_Address_Handler::ACTION, $this->create_callback( 'update_address', function ( $submission ) use ( $container ) { $container[ self::UPDATE_ADDRESS ]->handle_request( $submission ); } ), 10, 1 ); @@ -68,6 +150,7 @@ private function actions( Container $container ) { $container[ self::UPDATE_PROFILE ] = function ( Container $container ) { return new Update_Profile_Handler(); }; + add_action( 'bigcommerce/form/action=' . Update_Profile_Handler::ACTION, $this->create_callback( 'update_profile', function ( $submission ) use ( $container ) { $container[ self::UPDATE_PROFILE ]->handle_request( $submission ); } ), 10, 1 ); @@ -75,6 +158,7 @@ private function actions( Container $container ) { $container[ self::REGISTER ] = function ( Container $container ) { return new Registration_Handler( $container[ Compatibility::SPAM_CHECKER ], $container[ Accounts::LOGIN] ); }; + add_action( 'bigcommerce/form/action=' . Registration_Handler::ACTION, $this->create_callback( 'register', function ( $submission ) use ( $container ) { return $container[ self::REGISTER ]->handle_request( $submission ); } ), 10, 1 ); @@ -82,6 +166,7 @@ private function actions( Container $container ) { $container[ self::GIFT_CERTIFICATE ] = function ( Container $container ) { return new Purchase_Gift_Certificate_Handler( $container[ Api::FACTORY ]->cart() ); }; + add_action( 'bigcommerce/form/action=' . Purchase_Gift_Certificate_Handler::ACTION, $this->create_callback( 'purchase_gift_certificate', function ( $submission ) use ( $container ) { return $container[ self::GIFT_CERTIFICATE ]->handle_request( $submission ); } ), 10, 1 ); @@ -89,12 +174,15 @@ private function actions( Container $container ) { $container[ self::REVIEW ] = function ( Container $container ) { return new Product_Review_Handler( $container[ Api::FACTORY ]->catalog() ); }; + add_action( 'bigcommerce/form/action=' . Product_Review_Handler::ACTION, $this->create_callback( 'product_review', function ( $submission ) use ( $container ) { $container[ self::REVIEW ]->handle_request( $submission ); } ), 10, 1 ); + add_filter( 'bigcommerce/forms/show_messages', $this->create_callback( 'review_form_messages', function ( $show, $post_id ) use ( $container ) { return $container[ self::REVIEW ]->remove_form_messages_from_post_content( $show, $post_id ); } ), 10, 2 ); + add_filter( 'bigcommerce/product/reviews/show_form', $this->create_callback( 'toggle_review_form', function ( $enabled, $post_id ) use ( $container ) { return $container[ self::REVIEW ]->toggle_reviews_form_availability( $enabled, $post_id ); } ), 10, 2 ); @@ -102,6 +190,7 @@ private function actions( Container $container ) { $container[ self::SWITCH_CURRENCY ] = function ( Container $container ) { return new Switch_Currency_Handler( $container[ Currency::CURRENCY ], $container[ Api::FACTORY ]->cart() ); }; + add_action( 'bigcommerce/form/action=' . Switch_Currency_Handler::ACTION, $this->create_callback( 'switch_currency', function ( $submission ) use ( $container ) { return $container[ self::SWITCH_CURRENCY ]->handle_request( $submission ); } ), 10, 1 ); @@ -111,9 +200,11 @@ private function errors( Container $container ) { $container[ self::ERRORS ] = function ( Container $container ) { return new Error_Handler(); }; + add_action( 'bigcommerce/form/error', $this->create_callback( 'error', function ( \WP_Error $error, $submission, $redirect = '' ) use ( $container ) { $container[ self::ERRORS ]->form_error( $error, $submission, $redirect ); } ), 10, 3 ); + add_filter( 'bigcommerce/form/state/errors', $this->create_callback( 'error_data', function ( $data ) use ( $container ) { return $container[ self::ERRORS ]->get_errors( $data ); } ), 10, 1 ); @@ -133,6 +224,7 @@ private function redirects( Container $container ) { $container[ self::REDIRECTS ] = function ( Container $container ) { return new Form_Redirect(); }; + add_action( 'bigcommerce/form/redirect', $this->create_callback( 'redirect', function ( $url ) use ( $container ) { $container[ self::REDIRECTS ]->redirect( $url ); } ), 10, 1 ); diff --git a/src/BigCommerce/Container/Gift_Certificates.php b/src/BigCommerce/Container/Gift_Certificates.php index 92a638d6..90736161 100644 --- a/src/BigCommerce/Container/Gift_Certificates.php +++ b/src/BigCommerce/Container/Gift_Certificates.php @@ -7,13 +7,49 @@ use BigCommerce\Gift_Certificates\Sub_Nav; use Pimple\Container; +/** + * This class provides functionality for registering and handling the gift certificates sub-navigation + * in the BigCommerce environment. It extends the Provider class and implements a registration method + * to add a sub-navigation to the content. + * + * @package BigCommerce\Container + */ class Gift_Certificates extends Provider { - const SUB_NAV = 'gift_certificates.sub_nav'; + /** + * The key used for accessing the gift certificates sub-navigation service in the container. + * + * This constant defines the service key for the gift certificates sub-navigation, allowing it to be + * accessed through the container. + * + * @var string + */ + const SUB_NAV = 'gift_certificates.sub_nav'; + + /** + * Registers the gift certificates sub-navigation service and hooks the sub-navigation to the content. + * + * This method registers the `SUB_NAV` service in the container and defines a callback that inserts + * the gift certificates sub-navigation above the content. The callback is hooked into the `the_content` + * filter to ensure the sub-navigation is added to the content when it is being rendered. + * + * @param Container $container The Pimple container instance used for managing dependencies. + */ public function register( Container $container ) { $container[ self::SUB_NAV ] = function ( Container $container ) { return new Sub_Nav(); }; + + /** + * Adds the gift certificates sub-navigation above the content. + * + * This callback function is hooked into the `the_content` filter to insert the gift + * certificates sub-navigation at the beginning of the content. + * + * @param string $content The post content. + * + * @return string Modified content with the gift certificates sub-navigation added above. + */ add_filter( 'the_content', $this->create_callback( 'gift_certificates_subnav', function ( $content ) use ( $container ) { return $container[ self::SUB_NAV ]->add_subnav_above_content( $content ); } ), 10, 1 ); diff --git a/src/BigCommerce/Container/GraphQL.php b/src/BigCommerce/Container/GraphQL.php index 48ccaf91..2fc81649 100644 --- a/src/BigCommerce/Container/GraphQL.php +++ b/src/BigCommerce/Container/GraphQL.php @@ -9,30 +9,91 @@ use BigCommerce\GraphQL\Terms_Query; use Pimple\Container; +/** + * This class provides functionality for registering GraphQL-related services, such as various + * query objects and a GraphQL requestor processor, in the BigCommerce container. The `register` + * method configures these services to be accessed globally through the container. + * + * @package BigCommerce\Container + */ class GraphQL extends Provider { - const GRAPHQL_REQUESTOR = 'bigcommerce.graphql_requestor'; - const QUERY = 'bigcommerce.graphql_query'; - const PRODUCT_QUERY = 'bigcommerce.graphql_query_products'; - const REVIEWS_QUERY = 'bigcommerce.graphql_query_reviews'; - const TERMS_QUERY = 'bigcommerce.graphql_query_terms'; - const CUSTOMER_QUERY = 'bigcommerce.graphql_query_customer'; - - /** - * @inheritDoc - */ - public function register(Container $container) { - $container[ self::QUERY ] = function ( Container $container ) { - return [ - self::PRODUCT_QUERY => new Product_Query(), - self::TERMS_QUERY => new Terms_Query(), - self::REVIEWS_QUERY => new Reviews_Query(), - self::CUSTOMER_QUERY => new Customer_Query(), - ]; - }; - - $container[ self::GRAPHQL_REQUESTOR ] = function ( Container $container ) { - return new GraphQL_Processor( $container[ Api::CONFIG ], $container[ self::QUERY ] ); - }; - } + /** + * The service key for accessing the GraphQL requestor processor. + * + * This constant defines the key used to access the `GraphQL_Processor` service from the container. + * + * @var string + */ + const GRAPHQL_REQUESTOR = 'bigcommerce.graphql_requestor'; + + /** + * The service key for accessing the main GraphQL query collection. + * + * This constant defines the key used to access the collection of GraphQL queries (product, reviews, etc.) + * from the container. + * + * @var string + */ + const QUERY = 'bigcommerce.graphql_query'; + + /** + * The service key for accessing the product-related GraphQL query. + * + * This constant is used to access the query specifically related to products in the GraphQL system. + * + * @var string + */ + const PRODUCT_QUERY = 'bigcommerce.graphql_query_products'; + + /** + * The service key for accessing the reviews-related GraphQL query. + * + * This constant is used to access the query related to product reviews in the GraphQL system. + * + * @var string + */ + const REVIEWS_QUERY = 'bigcommerce.graphql_query_reviews'; + + /** + * The service key for accessing the terms-related GraphQL query. + * + * This constant is used to access the query related to terms and conditions in the GraphQL system. + * + * @var string + */ + const TERMS_QUERY = 'bigcommerce.graphql_query_terms'; + + /** + * The service key for accessing the customer-related GraphQL query. + * + * This constant is used to access the query related to customer information in the GraphQL system. + * + * @var string + */ + const CUSTOMER_QUERY = 'bigcommerce.graphql_query_customer'; + + /** + * Registers the GraphQL-related services in the container. + * + * This method registers the GraphQL queries (products, reviews, terms, customer) and the `GraphQL_Processor` + * service that will be used to execute GraphQL requests. These services are registered with specific keys + * that can be accessed via the container. + * + * @param Container $container The Pimple container instance used for managing dependencies. + */ + public function register(Container $container) { + $container[ self::QUERY ] = function (Container $container) { + return [ + self::PRODUCT_QUERY => new Product_Query(), + self::TERMS_QUERY => new Terms_Query(), + self::REVIEWS_QUERY => new Reviews_Query(), + self::CUSTOMER_QUERY => new Customer_Query(), + ]; + }; + + $container[ self::GRAPHQL_REQUESTOR ] = function (Container $container) { + return new GraphQL_Processor( $container[ Api::CONFIG ], $container[ self::QUERY ] ); + }; + } } diff --git a/src/BigCommerce/Container/Image.php b/src/BigCommerce/Container/Image.php index f767dc3e..baa7c4e5 100644 --- a/src/BigCommerce/Container/Image.php +++ b/src/BigCommerce/Container/Image.php @@ -5,10 +5,25 @@ use BigCommerce\Import\Image_Importer; use Pimple\Container; +/** + * This class provides functionality for registering image-related services and hooks related to + * image import and CDN management within the BigCommerce container. It includes hooks that + * determine if image import is allowed and modify image HTML to load images from a CDN if applicable. + * + * @package BigCommerce\Container + */ class Image extends Provider { + /** + * Registers image import and CDN-related filters. + * + * This method registers two filters: + * - A filter that checks if image import is allowed. + * - A filter that modifies image HTML to load images from CDN if a valid BigCommerce ID is found. + * + * @param Container $container The Pimple container instance used for managing dependencies. + */ public function register( Container $container ) { - add_filter( 'bigcommerce/import/product/import_images', $this->create_callback( 'images_import_full_disabled', function ( ) { return Image_Importer::is_image_import_allowed(); } ), 10, 0 ); diff --git a/src/BigCommerce/Container/Import.php b/src/BigCommerce/Container/Import.php index 4236843d..ed06b56a 100644 --- a/src/BigCommerce/Container/Import.php +++ b/src/BigCommerce/Container/Import.php @@ -17,46 +17,218 @@ use BigCommerce\Taxonomies\Channel\Connections; use Pimple\Container; +/** +* This class handles the import process for BigCommerce data. It includes functionality +* to manage cron jobs, process various import tasks, handle batch sizes, and trigger +* different import-related actions. +*/ class Import extends Provider { - const CRON_MONITOR = 'import.cron.monitor'; - const CRON_RUNNER = 'import.cron.runner'; - const PARALLEL_RUNNER = 'import.async.runner'; - const LOCK_MONITOR = 'import.lock.monitor'; - const TIMEOUT = 'timeout'; - - const CUSTOMER_DEFAULT_GROUP = 'import.customer_default_group'; - const MSF_STOREFRONT_PROCESSOR = 'import.msf_storefront_processor'; - - const TASK_MANAGER = 'import.task_manager'; - const TASK_LIST = 'import.task_list'; - const CACHE_CLEANUP = 'import.cache_cleanup'; - const CHANNEL_LIST = 'import.channel_list'; - - const BATCH_SIZE = 'import.batch_size'; - const LARGE_BATCH_SIZE = 'import.large_batch_size'; - const POST_TASK_MANAGER = 'import.postponed_task_manager'; - - const START = 'import.start'; - const LISTINGS = 'import.listings'; - const CHANNEL = 'import.channel'; - const PURGE_CATEGORIES = 'import.purge.categories'; - const PURGE_BRANDS = 'import.purge.brands'; - const CATEGORIES = 'import.categories'; - const BRANDS = 'import.brands'; - const RESIZE = 'import.resize'; - const PRODUCTS = 'import.products'; - const MARK = 'import.mark_deleted'; - const QUEUE = 'import.queue'; - const STORE = 'import.store'; - const CURRENCIES = 'import.currencies'; - const CLEANUP = 'import.cleanup'; - const PRODUCT_CLEANUP = 'import.product_cleanup'; - const IMPORT_STATUS = 'import.import_status'; - const ERROR = 'import.error'; - const IMPORT_TYPE = 'import.type'; - - const HEADLESS_PROCESSOR = 'headless.processor'; - + + /** + * The service identifier for the cron monitor used to check scheduled crons. + * @var string + */ + const CRON_MONITOR = 'import.cron.monitor'; + + /** + * The service identifier for the cron runner responsible for processing cron jobs. + * @var string + */ + const CRON_RUNNER = 'import.cron.runner'; + + /** + * The service identifier for the parallel runner responsible for asynchronous job execution. + * @var string + */ + const PARALLEL_RUNNER = 'import.async.runner'; + + /** + * The service identifier for monitoring locks during the import process. + * @var string + */ + const LOCK_MONITOR = 'import.lock.monitor'; + + /** + * The service identifier for the timeout setting used to control the import process timeout. + * @var string + */ + const TIMEOUT = 'timeout'; + + /** + * The default customer group for the import process. + * @var string + */ + const CUSTOMER_DEFAULT_GROUP = 'import.customer_default_group'; + + /** + * The service identifier for the storefront processor used in the import process. + * @var string + */ + const MSF_STOREFRONT_PROCESSOR = 'import.msf_storefront_processor'; + + /** + * The service identifier for the task manager handling postponed tasks. + * @var string + */ + const TASK_MANAGER = 'import.task_manager'; + + /** + * The service identifier for the list of tasks to be processed during the import. + * @var string + */ + const TASK_LIST = 'import.task_list'; + + /** + * The service identifier for the cache cleanup process during import. + * @var string + */ + const CACHE_CLEANUP = 'import.cache_cleanup'; + + /** + * The service identifier for managing channels during the import process. + * @var string + */ + const CHANNEL_LIST = 'import.channel_list'; + + /** + * The service identifier for the batch size setting for the import process. + * @var string + */ + const BATCH_SIZE = 'import.batch_size'; + + /** + * The service identifier for a larger batch size setting for the import process. + * @var string + */ + const LARGE_BATCH_SIZE = 'import.large_batch_size'; + + /** + * The service identifier for managing postponed tasks after the import process. + * @var string + */ + const POST_TASK_MANAGER = 'import.postponed_task_manager'; + + /** + * The service identifier for starting the import process. + * @var string + */ + const START = 'import.start'; + + /** + * The service identifier for importing product listings during the import process. + * @var string + */ + const LISTINGS = 'import.listings'; + + /** + * The service identifier for the channel configuration used in the import process. + * @var string + */ + const CHANNEL = 'import.channel'; + + /** + * The service identifier for purging categories during the import process. + * @var string + */ + const PURGE_CATEGORIES = 'import.purge.categories'; + + /** + * The service identifier for purging brands during the import process. + * @var string + */ + const PURGE_BRANDS = 'import.purge.brands'; + + /** + * The service identifier for importing categories during the import process. + * @var string + */ + const CATEGORIES = 'import.categories'; + + /** + * The service identifier for importing brands during the import process. + * @var string + */ + const BRANDS = 'import.brands'; + + /** + * The service identifier for resizing images during the import process. + * @var string + */ + const RESIZE = 'import.resize'; + + /** + * The service identifier for importing products during the import process. + * @var string + */ + const PRODUCTS = 'import.products'; + + /** + * The service identifier for marking deleted products during the import process. + * @var string + */ + const MARK = 'import.mark_deleted'; + + /** + * The service identifier for managing the import queue. + * @var string + */ + const QUEUE = 'import.queue'; + + /** + * The service identifier for managing the store configuration during the import process. + * @var string + */ + const STORE = 'import.store'; + + /** + * The service identifier for handling currency settings during the import process. + * @var string + */ + const CURRENCIES = 'import.currencies'; + + /** + * The service identifier for the cleanup process during the import. + * @var string + */ + const CLEANUP = 'import.cleanup'; + + /** + * The service identifier for cleaning up product-related data during the import process. + * @var string + */ + const PRODUCT_CLEANUP = 'import.product_cleanup'; + + /** + * The service identifier for tracking the import status. + * @var string + */ + const IMPORT_STATUS = 'import.import_status'; + + /** + * The service identifier for handling import errors. + * @var string + */ + const ERROR = 'import.error'; + + /** + * The service identifier for specifying the type of import process. + * @var string + */ + const IMPORT_TYPE = 'import.type'; + + /** + * The service identifier for the headless processor used during import. + * @var string + */ + const HEADLESS_PROCESSOR = 'headless.processor'; + + /** + * Registers the import-related services and actions within the container. + * + * @param Container $container The container instance for dependency injection. + * + * @return void + */ public function register( Container $container ) { $this->cron( $container ); $this->process( $container ); @@ -138,7 +310,7 @@ private function cron( Container $container ) { } $container[ self::PARALLEL_RUNNER ]->run(); } ), 10, 0 ); - + add_action( Processors\Cleanup::CLEAN_USERS_TRANSIENT, $this->create_callback( 'clean_users_group_transient', function () use ( $container ) { $container[ self::CLEANUP ]->clean_customer_group_transients(); } ), 10, 0 ); @@ -267,6 +439,7 @@ private function process( Container $container ) { // Run pre import cleanup process. Set abort = false, pre_import = true $container[ self::CLEANUP ]->run( false, true ); } ); + add_action( 'bigcommerce/import/start', $start, 10, 0 ); $container[ self::TASK_LIST ] = function ( Container $container ) { @@ -376,6 +549,7 @@ private function process( Container $container ) { $error = $this->create_callback( 'process_error', function () use ( $container ) { $container[ self::ERROR ]->run(); } ); + add_action( 'bigcommerce/import/error', $error, 10, 0 ); @@ -388,6 +562,7 @@ private function process( Container $container ) { } ); add_action( 'bigcommerce/import/before', $flush_option_caches, 0, 0 ); + add_action( 'bigcommerce/import/after', $flush_option_caches, 0, 0 ); $container[ self::IMPORT_TYPE ] = function ( Container $container ) { diff --git a/src/BigCommerce/Container/Log.php b/src/BigCommerce/Container/Log.php index dcfcfdd4..d25752fe 100644 --- a/src/BigCommerce/Container/Log.php +++ b/src/BigCommerce/Container/Log.php @@ -8,15 +8,51 @@ use Pimple\Container; use BigCommerce\Logging\Error_Log as Logger; +/** + * This class is responsible for setting up logging functionality in the BigCommerce container. + * It registers services for logging, defines constants for log paths, and handles log-related actions + * during the BigCommerce import process, such as logging errors and diagnostics. + * + * @package BigCommerce\Container + */ class Log extends Provider { + /** + * Constant for the logger service. + * + * This constant defines the key used to retrieve the logger instance from the container. + * + * @var string + */ const LOGGER = 'logger.log'; + + /** + * Constant for the log file path. + * + * This constant defines the key used to retrieve the log file path from the container. + * + * @var string + */ const LOG_PATH = 'logger.log_path'; + + /** + * Constant for the log folder path. + * + * This constant defines the key used to retrieve the log folder path from the container. + * + * @var string + */ const LOG_FOLDER_PATH = 'logger.log_folder_path'; - /** - * @param Container $container - */ + /** + * Registers logging-related services and actions in the container. + * + * This method sets up the necessary services for logging, such as the log file path, + * log folder path, and logger instance. It also registers various actions and filters + * for logging during the BigCommerce import process. + * + * @param Container $container The container instance used to register the services. + */ public function register( Container $container ) { $container[ self::LOG_PATH ] = function ( Container $container ) { $log_path = bigcommerce_get_env( 'BIGCOMMERCE_DEBUG_LOG' ); @@ -53,7 +89,7 @@ public function register( Container $container ) { add_action( 'bigcommerce/import/start', $this->create_callback( 'truncate_log', function () use ( $container ) { $container[ self::LOGGER ]->truncate_log(); } ), 9, 0 ); - + add_action( 'bigcommerce/import/product/error', $this->create_callback( 'log_product_import_error', function ( $product_id, CatalogApi $catalog_api, \Exception $exception ) use ( $container ) { $container[ self::LOGGER ]->log_product_import_error( $product_id, $catalog_api, $exception ); } ), 10, 3 ); @@ -65,9 +101,10 @@ public function register( Container $container ) { $log = $this->create_callback( 'log', function ( $level = Error_Log::INFO, $message = '', $context = [], $path = '' ) use ( $container ) { $container[ self::LOGGER ]->log( $level, $message, $context, $path ); } ); + add_action( 'bigcommerce/log', $log, 10, 4 ); - add_action( 'bigcommerce/import/log', $log, 10, 3 ); + add_action( 'bigcommerce/import/log', $log, 10, 3 ); add_action( 'bigcommerce/import/error', $this->create_callback( 'log_import_error', function ( $message, $context = [] ) use ( $container ) { $container[ self::LOGGER ]->log( Error_Log::ERROR, $message, $context ); diff --git a/src/BigCommerce/Container/Merchant.php b/src/BigCommerce/Container/Merchant.php index 86b4a503..a5e04f62 100644 --- a/src/BigCommerce/Container/Merchant.php +++ b/src/BigCommerce/Container/Merchant.php @@ -12,18 +12,79 @@ use BigCommerce\Settings\Screens\Pending_Account_Screen; use Pimple\Container; +/** + * Handles merchant-related onboarding and account management for BigCommerce integration. + * + * Provides functionality for creating and connecting merchant accounts, checking account + * statuses, and setting up the onboarding API. + * + * @package BigCommerce\Container + */ class Merchant extends Provider { + /** + * The URL for the middleman used in onboarding processes. + * + * @var string + */ const MIDDLEMAN_URL = 'merchant.middleman.url'; + + /** + * The key for accessing the Onboarding API service in the container. + * + * @var string + */ const ONBOARDING_API = 'merchant.onboarding.api'; + + /** + * The key for accessing the Create Account service in the container. + * + * @var string + */ const CREATE_ACCOUNT = 'merchant.onboarding.create_account'; + + /** + * The key for accessing the Connect Account service in the container. + * + * @var string + */ const CONNECT_ACCOUNT = 'merchant.onboarding.connect_account'; + + /** + * The key for accessing the Account Status service in the container. + * + * @var string + */ const ACCOUNT_STATUS = 'merchant.onboarding.account_status'; + + /** + * The key for accessing the Setup Status service in the container. + * + * @var string + */ const SETUP_STATUS = 'merchant.onboarding.setup_status'; + /** + * Registers services into the dependency container. + * + * Sets up account onboarding services including account creation, connection, + * status checks, and setup status. + * + * @param Container $container The dependency injection container. + * @return void + */ public function register( Container $container ) { $this->account_onboarding( $container ); } + /** + * Sets up account onboarding services in the container. + * + * Initializes and registers services for onboarding, including the middleman URL, + * onboarding API, account creation, account connection, and account status. + * + * @param Container $container The dependency injection container. + * @return void + */ private function account_onboarding( Container $container ) { $container[ self::MIDDLEMAN_URL ] = function ( Container $container ) { /** @@ -44,6 +105,12 @@ private function account_onboarding( Container $container ) { $this->setup_status( $container ); } + /** + * Registers the Create Account service and hooks into the account creation process. + * + * @param Container $container The dependency injection container. + * @return void + */ private function create_account( Container $container ) { $container[ self::CREATE_ACCOUNT ] = function ( Container $container ) { return new Create_Account( $container[ self::ONBOARDING_API ] ); @@ -54,6 +121,12 @@ private function create_account( Container $container ) { } ), 10, 2 ); } + /** + * Registers the Connect Account service and hooks into the account connection process. + * + * @param Container $container The dependency injection container. + * @return void + */ private function connect_account( Container $container ) { $container[ self::CONNECT_ACCOUNT ] = function ( Container $container ) { return new Connect_Account( $container[ self::ONBOARDING_API ] ); @@ -68,6 +141,12 @@ private function connect_account( Container $container ) { } ), 10, 0 ); } + /** + * Registers the Account Status service and hooks into status rendering and checks. + * + * @param Container $container The dependency injection container. + * @return void + */ private function account_status( Container $container ) { $container[ self::ACCOUNT_STATUS ] = function ( Container $container ) { return new Account_Status( $container[ self::ONBOARDING_API ] ); @@ -76,14 +155,22 @@ private function account_status( Container $container ) { add_action( 'bigcommerce/settings/after_content/page=' . Pending_Account_Screen::NAME, $this->create_callback( 'account_status_placeholder', function () use ( $container ) { $container[ self::ACCOUNT_STATUS ]->render_status_placeholder(); } ), 10, 0 ); + add_action( 'wp_ajax_' . Account_Status::STATUS_AJAX, $this->create_callback( 'ajax_account_status', function () use ( $container ) { $container[ self::ACCOUNT_STATUS ]->handle_account_status_request(); } ), 10, 0 ); + add_action( 'bigcommerce/pending_account/check_status', $this->create_callback( 'pending_check_status', function ( $errors ) use ( $container ) { $container[ self::ACCOUNT_STATUS ]->handle_refresh_status_request( $errors ); } ), 10, 1 ); } + /** + * Registers the Setup Status service in the container. + * + * @param Container $container The dependency injection container. + * @return void + */ private function setup_status( Container $container ) { $container[ self::SETUP_STATUS ] = function ( Container $container ) { return new Setup_Status( $container[ Api::FACTORY ] ); diff --git a/src/BigCommerce/Container/Nav_Menu.php b/src/BigCommerce/Container/Nav_Menu.php index d992c955..12325827 100644 --- a/src/BigCommerce/Container/Nav_Menu.php +++ b/src/BigCommerce/Container/Nav_Menu.php @@ -8,17 +8,49 @@ use BigCommerce\Nav_Menu\Nav_Items_Meta_Box; use Pimple\Container; +/** + * Provides dependencies and behaviors for navigation menus. + */ class Nav_Menu extends Provider { + /** + * Navigation items dependency identifier. + * + * @var string + */ const ITEMS = 'navigation.items'; + + /** + * Navigation metabox dependency identifier. + * + * @var string + */ const METABOX = 'navigation.metabox'; + + /** + * Navigation customizer dependency identifier. + * + * @var string + */ const CUSTOMIZER = 'navigation.customizer'; + /** + * Registers dependencies with the container. + * + * @param Container $container The dependency injection container. + * @return void + */ public function register( Container $container ) { $this->menu_items( $container ); $this->metabox( $container ); $this->customizer( $container ); } + /** + * Registers dynamic menu items dependency and hooks. + * + * @param Container $container The dependency injection container. + * @return void + */ private function menu_items( Container $container ) { $container[ self::ITEMS ] = function ( Container $container ) { return new Dynamic_Menu_Items(); @@ -33,6 +65,12 @@ private function menu_items( Container $container ) { } ), 20, 3 ); } + /** + * Registers navigation metabox dependency and hooks. + * + * @param Container $container The dependency injection container. + * @return void + */ private function metabox( Container $container ) { $container[ self::METABOX ] = function ( Container $container ) { return new Nav_Items_Meta_Box(); @@ -47,10 +85,17 @@ private function metabox( Container $container ) { } ), 0, 0 ); } + /** + * Registers navigation customizer dependency and hooks. + * + * @param Container $container The dependency injection container. + * @return void + */ private function customizer( Container $container ) { $container[ self::CUSTOMIZER ] = function ( Container $container ) { return new Nav_Items_Customizer(); }; + add_filter( 'customize_nav_menu_available_item_types', $this->create_callback( 'register_customizer_item_type', function ( $types ) use ( $container ) { return $container[ self::CUSTOMIZER ]->register_item_type( $types ); } ), 10, 1 ); diff --git a/src/BigCommerce/Container/Pages.php b/src/BigCommerce/Container/Pages.php index 52730f16..99e8a6dd 100644 --- a/src/BigCommerce/Container/Pages.php +++ b/src/BigCommerce/Container/Pages.php @@ -1,9 +1,7 @@ create_callback( 'create_pages', function () use ( $container ) { - foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { - /** @var Required_Page $page */ - $page->ensure_page_exists(); - } - } ), 10, 0 ); - - $clear_options = $this->create_callback( 'clear_options', function ( $post_id ) use ( $container ) { - foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { - /** @var Required_Page $page */ - $page->clear_option_on_delete( $post_id ); - } - } ); - add_action( 'trashed_post', $clear_options, 10, 1 ); - add_action( 'deleted_post', $clear_options, 10, 1 ); - - add_action( 'display_post_states', $this->create_callback( 'post_states', function ( $post_states, $post ) use ( $container ) { - - foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { - /** @var Required_Page $page */ - $post_states = $page->add_post_state( $post_states, $post ); - } - - return $post_states; - } ), 10, 2 ); - - add_action( 'bigcommerce/settings/accounts/after_page_field/page=' . Registration_Page::NAME, $this->create_callback( 'enable_registration_notice', function () use ( $container ) { - $container[ self::REGISTRATION_PAGE ]->enable_registration_notice(); - } ), 10, 0 ); - - add_action( 'the_content', $this->create_callback( 'page_content', function ( $content ) use ( $container ) { - if ( is_page() && in_the_loop() && is_main_query() ) { - foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { - /** @var Required_Page $page */ - $content = $page->filter_content( get_the_ID(), $content ); - } - } - return $content; - } ), 5, 1 ); - } + /** + * Identifier for required pages collection. + * + * @var string + */ + const REQUIRED_PAGES = 'pages.required_pages'; + + /** + * Identifier for the cart page. + * + * @var string + */ + const CART_PAGE = 'pages.cart'; + + /** + * Identifier for the checkout page. + * + * @var string + */ + const CHECKOUT_PAGE = 'pages.checkout'; + + /** + * Identifier for the checkout complete page. + * + * @var string + */ + const CHECKOUT_COMPLETE_PAGE = 'pages.checkout.complete'; + + /** + * Identifier for the login page. + * + * @var string + */ + const LOGIN_PAGE = 'pages.login'; + + /** + * Identifier for the registration page. + * + * @var string + */ + const REGISTRATION_PAGE = 'pages.register'; + + /** + * Identifier for the account page. + * + * @var string + */ + const ACCOUNT_PAGE = 'pages.account'; + + /** + * Identifier for the address page. + * + * @var string + */ + const ADDRESS_PAGE = 'pages.address'; + + /** + * Identifier for the orders page. + * + * @var string + */ + const ORDERS_PAGE = 'pages.orders'; + + /** + * Identifier for purchasing gift certificates. + * + * @var string + */ + const GIFT_PURCHACE = 'pages.gift_certificate.purchase'; + + /** + * Identifier for checking gift certificate balance. + * + * @var string + */ + const GIFT_BALANCE = 'pages.gift_certificate.balance'; + + /** + * Identifier for the shipping and returns page. + * + * @var string + */ + const SHIPPING_PAGE = 'pages.shipping_returns'; + + /** + * Identifier for the user's wishlist page. + * + * @var string + */ + const WISHLIST_USER = 'pages.wishlist.user'; + + /** + * Identifier for the public wishlist page. + * + * @var string + */ + const WISHLIST_PUBLIC = 'pages.wishlist.public'; + + /** + * Registers page-related services into the Pimple container. + * + * @param Container $container The dependency injection container. + * @return void + */ + public function register( Container $container ) { + $container[ self::REQUIRED_PAGES ] = function ( Container $container ) { + $pages = [ + $container[ self::LOGIN_PAGE ], + $container[ self::ACCOUNT_PAGE ], + $container[ self::ADDRESS_PAGE ], + $container[ self::ORDERS_PAGE ], + $container[ self::SHIPPING_PAGE ], + $container[ self::CHECKOUT_COMPLETE_PAGE ], + ]; + + if ( ( (bool) get_option( Cart_Settings::OPTION_ENABLE_CART, true ) ) === true ) { + $pages[] = $container[ self::CART_PAGE ]; + } + if ( ( (bool) get_option( Cart_Settings::OPTION_EMBEDDED_CHECKOUT, true ) ) === true ) { + $pages[] = $container[ self::CHECKOUT_PAGE ]; + } + if ( ( (bool) get_option( Gift_Certificate_Settings::OPTION_ENABLE, true ) ) === true ) { + $pages[] = $container[ self::GIFT_PURCHACE ]; + $pages[] = $container[ self::GIFT_BALANCE ]; + } + if ( get_option( 'users_can_register' ) ) { + $pages[] = $container[ self::REGISTRATION_PAGE ]; + } + if ( get_option( Wishlist_Settings::ENABLED ) ) { + $pages[] = $container[ self::WISHLIST_USER ]; + } + + return $pages; + }; + + // Define individual page services with corresponding classes + $container[ self::CART_PAGE ] = function ( Container $container ) { + return new Cart_Page(); + }; + + $container[ self::CHECKOUT_PAGE ] = function ( Container $container ) { + return new Checkout_Page(); + }; + + $container[ self::CHECKOUT_COMPLETE_PAGE ] = function ( Container $container ) { + return new Checkout_Complete_Page(); + }; + + $container[ self::LOGIN_PAGE ] = function ( Container $container ) { + return new Login_Page(); + }; + + $container[ self::REGISTRATION_PAGE ] = function ( Container $container ) { + return new Registration_Page(); + }; + + $container[ self::ACCOUNT_PAGE ] = function ( Container $container ) { + return new Account_Page(); + }; + + $container[ self::ADDRESS_PAGE ] = function ( Container $container ) { + return new Address_Page(); + }; + + $container[ self::ORDERS_PAGE ] = function ( Container $container ) { + return new Orders_Page(); + }; + + $container[ self::GIFT_PURCHACE ] = function ( Container $container ) { + return new Gift_Certificate_Page(); + }; + + $container[ self::GIFT_BALANCE ] = function ( Container $container ) { + return new Check_Balance_Page(); + }; + + $container[ self::SHIPPING_PAGE ] = function ( Container $container ) { + return new Shipping_Returns_Page(); + }; + + $container[ self::WISHLIST_USER ] = function ( Container $container ) { + return new Wishlist_Page(); + }; + + add_action( 'admin_init', $this->create_callback( 'create_pages', function () use ( $container ) { + foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { + /** @var Required_Page $page */ + $page->ensure_page_exists(); + } + } ), 10, 0 ); + + $clear_options = $this->create_callback( 'clear_options', function ( $post_id ) use ( $container ) { + foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { + /** @var Required_Page $page */ + $page->clear_option_on_delete( $post_id ); + } + } ); + + add_action( 'trashed_post', $clear_options, 10, 1 ); + + add_action( 'deleted_post', $clear_options, 10, 1 ); + + add_action( 'display_post_states', $this->create_callback( 'post_states', function ( $post_states, $post ) use ( $container ) { + foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { + /** @var Required_Page $page */ + $post_states = $page->add_post_state( $post_states, $post ); + } + return $post_states; + } ), 10, 2 ); + + add_action( 'bigcommerce/settings/accounts/after_page_field/page=' . Registration_Page::NAME, $this->create_callback( 'enable_registration_notice', function () use ( $container ) { + $container[ self::REGISTRATION_PAGE ]->enable_registration_notice(); + } ), 10, 0 ); + + add_action( 'the_content', $this->create_callback( 'page_content', function ( $content ) use ( $container ) { + if ( is_page() && in_the_loop() && is_main_query() ) { + foreach ( $container[ self::REQUIRED_PAGES ] as $page ) { + /** @var Required_Page $page */ + $content = $page->filter_content( get_the_ID(), $content ); + } + } + return $content; + } ), 5, 1 ); + } } diff --git a/src/BigCommerce/Container/Post_Meta.php b/src/BigCommerce/Container/Post_Meta.php index 0cf9ba2d..6015fe36 100644 --- a/src/BigCommerce/Container/Post_Meta.php +++ b/src/BigCommerce/Container/Post_Meta.php @@ -4,8 +4,20 @@ use Pimple\Container; +/** + * This class provides methods to handle post metadata related tasks in the container. It extends the Provider class + * and registers dependencies related to post metadata processing within the container. + */ class Post_Meta extends Provider { + /** + * Registers the necessary post metadata services in the container. + * + * This function is responsible for adding any services or dependencies related to post metadata handling to the container. + * It is called during the registration phase of the container setup. + * + * @param Container $container The container instance used to register the services. + */ public function register( Container $container ) { $this->import( $container ); } diff --git a/src/BigCommerce/Container/Post_Types.php b/src/BigCommerce/Container/Post_Types.php index 412a3c33..46edef2e 100644 --- a/src/BigCommerce/Container/Post_Types.php +++ b/src/BigCommerce/Container/Post_Types.php @@ -1,6 +1,5 @@ product( $container ); - $this->queue( $container ); - $this->sync_log( $container ); - - add_action( 'init', $this->create_callback( 'register', function () use ( $container ) { - $container[ self::PRODUCT_CONFIG ]->register(); - $container[ self::QUEUE_CONFIG ]->register(); - $container[ self::SYNC_LOG_CONFIG ]->register(); - $container[ self::WPGRAPHQL_PRODUCTS ]->register(); - } ), 1, 0 ); - } - - private function product( Container $container ) { - - $container[ self::PRODUCT_ADMIN_LIST ] = function ( Container $container ) { - return new Product\Admin_List(); - }; - - $container[ self::PRODUCT_CONFIG ] = function ( Container $container ) { - return new Product\Config( Product\Product::NAME ); - }; - - $container[ self::PRODUCT_QUERY ] = function ( Container $container ) { - return new Product\Query( $container[ Api::FACTORY ]->catalog(), $container[ Taxonomies::PRODUCT_CATEGORY_QUERY_FILTER ] ); - }; - - $container[ self::PRODUCT_ADMIN ] = function ( Container $container ) { - return new Product\Admin_UI(); - }; - - $container[ self::WPGRAPHQL_CONFIG ] = function ( Container $container ) { - return new Product\WPGraph_Config(); - }; - - $container[ self::WPGRAPHQL_PRODUCTS ] = function ( Container $container ) { - return new Product\WPGraph_Product( $container[ self::WPGRAPHQL_CONFIG ] ); - }; - - $container[ self::PRODUCT_UNSUPPORTED ] = function ( Container $container ) { - return new Product\Unsupported_Products(); - }; - - $container[ self::PRODUCT_DELETION ] = function ( Container $container ) { - return new Product\Deletion(); - }; + /** + * @var string Post type for product. + */ + const PRODUCT = 'post_type.product'; + /** + * @var string Configuration for product post type. + */ + const PRODUCT_CONFIG = 'post_type.product.config'; + /** + * @var string Query handling for product post type. + */ + const PRODUCT_QUERY = 'post_type.product.query'; + /** + * @var string Admin UI for product post type. + */ + const PRODUCT_ADMIN = 'post_type.product.admin'; + /** + * @var string Unsupported product handler. + */ + const PRODUCT_UNSUPPORTED = 'post_type.product.unsupported'; + /** + * @var string Product deletion handler. + */ + const PRODUCT_DELETION = 'post_type.product.deletion'; + /** + * @var string Store links handler for products. + */ + const STORE_LINKS = 'post_type.product.store_links'; + /** + * @var string Channel indicator handler for products. + */ + const CHANNEL_INDICATOR = 'post_type.product.channel_indicator'; + /** + * @var string Channel synchronization handler for products. + */ + const CHANNEL_SYNC = 'post_type.product.channel_sync'; + /** + * @var string Admin list handler for products. + */ + const PRODUCT_ADMIN_LIST = 'post_type.product.admin_list'; + /** + * @var string Unique slug generator for products. + */ + const PRODUCT_UNIQUE_SLUG = 'post_type.product.unique_slug'; + /** + * @var string Listing reset handler for products. + */ + const LISTING_RESET = 'post_type.product.listing_reset'; + /** + * @var string Single product resynchronization handler. + */ + const PRODUCT_RESYNC = 'post_type.product.resync_single'; + /** + * @var string SEO handler for products. + */ + const PRODUCT_SEO = 'post_type.product.seo'; + + /** + * @var string Cart indicator handler. + */ + const CART_INDICATOR = 'post_type.page.cart_indicator'; + /** + * @var string Cart creation handler. + */ + const CART_CREATOR = 'post_type.page.cart_creator'; + + /** + * @var string Queue task handler. + */ + const QUEUE = 'post_type.queue_task'; + /** + * @var string Queue task configuration. + */ + const QUEUE_CONFIG = 'post_type.queue_task.config'; + + /** + * @var string Synchronization log handler. + */ + const SYNC_LOG = 'post_type.sync_log'; + /** + * @var string Configuration for synchronization logs. + */ + const SYNC_LOG_CONFIG = 'post_type.sync_log.config'; + + /** + * @var string GraphQL products configuration. + */ + const WPGRAPHQL_PRODUCTS = 'bigcommerce.wpgrapql_products'; + /** + * @var string GraphQL configuration. + */ + const WPGRAPHQL_CONFIG = 'bigcommerce.wpgrapql_config'; + + /** + * Registers all post types and hooks them into the container. + * + * @param Container $container The Pimple container. + * @return void + */ + public function register(Container $container) { + $this->product($container); + $this->queue($container); + $this->sync_log($container); + + add_action('init', $this->create_callback('register', function () use ($container) { + $container[self::PRODUCT_CONFIG]->register(); + $container[self::QUEUE_CONFIG]->register(); + $container[self::SYNC_LOG_CONFIG]->register(); + $container[self::WPGRAPHQL_PRODUCTS]->register(); + }), 1, 0); + } + + /** + * Configures product-related dependencies in the container. + * + * @param Container $container The Pimple container. + * @return void + */ + private function product(Container $container) { + $container[self::PRODUCT_ADMIN_LIST] = function (Container $container) { + return new Product\Admin_List(); + }; + + $container[self::PRODUCT_CONFIG] = function (Container $container) { + return new Product\Config(Product\Product::NAME); + }; + + $container[self::PRODUCT_QUERY] = function (Container $container) { + return new Product\Query($container[Api::FACTORY]->catalog(), $container[Taxonomies::PRODUCT_CATEGORY_QUERY_FILTER]); + }; + + $container[self::PRODUCT_ADMIN] = function (Container $container) { + return new Product\Admin_UI(); + }; + + $container[self::WPGRAPHQL_CONFIG] = function (Container $container) { + return new Product\WPGraph_Config(); + }; + + $container[self::WPGRAPHQL_PRODUCTS] = function (Container $container) { + return new Product\WPGraph_Product($container[self::WPGRAPHQL_CONFIG]); + }; + + $container[self::PRODUCT_UNSUPPORTED] = function (Container $container) { + return new Product\Unsupported_Products(); + }; + + $container[self::PRODUCT_DELETION] = function (Container $container) { + return new Product\Deletion(); + }; add_action( 'pre_get_posts', $this->create_callback( 'product_pre_get_posts', function ( \WP_Query $query ) use ( $container ) { $container[ self::PRODUCT_QUERY ]->filter_queries( $query ); @@ -123,7 +209,7 @@ private function product( Container $container ) { nocache_headers(); return ''; - } ), 10, 1); + } ), 10, 1 ); /** * Only load the post admin hooks when on the post admin page to avoid interfering where we're not welcome @@ -146,6 +232,7 @@ private function product( Container $container ) { $loaded = true; } } ); + add_action( 'load-post.php', $load_post_admin_hooks, 10, 0 ); add_action( 'wp_ajax_inline-save', $load_post_admin_hooks, 0, 0 ); add_action( 'load-edit.php', $load_post_admin_hooks, 10, 0 ); @@ -162,12 +249,11 @@ private function product( Container $container ) { if ( ! empty( $redirect ) ) { wp_safe_redirect( $redirect ); - return; } return $preempt; - } ), 10, 1); + } ), 10, 1 ); add_filter( 'views_edit-' . Product\Product::NAME, $this->create_callback( 'list_table_import_status', function ( $views ) use ( $container ) { return $container[ self::PRODUCT_ADMIN ]->list_table_import_status( $views ); @@ -180,6 +266,7 @@ private function product( Container $container ) { add_filter( 'views_edit-' . Product\Product::NAME, $this->create_callback( 'list_table_manage_link', function ( $views ) use ( $container ) { return $container[ self::PRODUCT_ADMIN ]->list_table_manage_link( $views ); } ), 2, 1 ); + add_action( 'admin_notices', $this->create_callback( 'list_table_admin_notices', function () use ( $container ) { $container[ self::PRODUCT_ADMIN ]->list_table_admin_notices(); } ), 10, 0 ); @@ -187,19 +274,19 @@ private function product( Container $container ) { add_filter( 'map_meta_cap', $this->create_callback( 'unsupported_meta_caps', function ( $caps, $cap, $user_id, $args ) use ( $container ) { return $container[ self::PRODUCT_UNSUPPORTED ]->disallow_publication( $caps, $cap, $user_id, $args ); } ), 10, 4 ); + add_filter( 'display_post_states', $this->create_callback( 'unsupported_post_state', function ( $post_states, $post ) use ( $container ) { return $container[ self::PRODUCT_UNSUPPORTED ]->show_unsupported_status( $post_states, $post ); } ), 10, 4 ); + add_filter( 'wp_insert_post_data', $this->create_callback( 'prevent_publication', function ( $data, $postarr ) use ( $container ) { return $container[ self::PRODUCT_UNSUPPORTED ]->prevent_publication( $data, $postarr ); } ), 10, 2 ); - add_action( 'before_delete_post', $this->create_callback( 'delete_product', function ( $post_id ) use ( $container ) { $container[ self::PRODUCT_DELETION ]->delete_product_data( $post_id ); } ), 10, 1 ); - // do not push updates back upstream when running an import add_action( 'bigcommerce/import/before', function () { add_filter( 'bigcommerce/channel/listing/should_update', '__return_false', 10, 0 ); add_filter( 'bigcommerce/channel/listing/should_delete', '__return_false', 10, 0 ); @@ -210,7 +297,6 @@ private function product( Container $container ) { remove_filter( 'bigcommerce/channel/listing/should_delete', '__return_false', 10 ); }, 10, 0 ); - // Admin extra columns list add_filter( 'manage_bigcommerce_product_posts_columns', $this->create_callback( 'add_bigcommerce_product_id_column', function ( $columns ) use ( $container ) { return $container[ self::PRODUCT_ADMIN_LIST ]->add_product_list_columns( $columns ); } ), 5, 1 ); @@ -233,146 +319,218 @@ private function product( Container $container ) { $this->product_seo( $container ); } - private function queue( Container $container ) { - $container[ self::QUEUE_CONFIG ] = function ( Container $container ) { - return new Queue_Task\Config( Queue_Task\Queue_Task::NAME ); - }; - } + /** + * Queues the configuration for the Queue_Task. + * + * @param Container $container The service container. + * + * @return void + */ + private function queue( Container $container ) { + $container[ self::QUEUE_CONFIG ] = function ( Container $container ) { + return new Queue_Task\Config( Queue_Task\Queue_Task::NAME ); + }; + } - private function sync_log( Container $container ) { - $container[ self::SYNC_LOG_CONFIG ] = function ( Container $container ) { - return new Sync_Log\Config( Sync_Log\Sync_Log::NAME ); - }; + /** + * Sets up the synchronization logging. + * + * @param Container $container The service container. + * + * @return void + */ + private function sync_log( Container $container ) { + $container[ self::SYNC_LOG_CONFIG ] = function ( Container $container ) { + return new Sync_Log\Config( Sync_Log\Sync_Log::NAME ); + }; - $container[ self::SYNC_LOG ] = function ( Container $container ) { - return new Sync_Log\Sync_Log; - }; + $container[ self::SYNC_LOG ] = function ( Container $container ) { + return new Sync_Log\Sync_Log; + }; - add_action( 'bigcommerce/import/start', $this->create_callback( 'sync_log_create_sync', function ( $error ) use ( $container ) { - $container[ self::SYNC_LOG ]->create_sync(); - } ) ); + add_action( 'bigcommerce/import/start', $this->create_callback( 'sync_log_create_sync', function ( $error ) use ( $container ) { + $container[ self::SYNC_LOG ]->create_sync(); + } ) ); - add_action( 'bigcommerce/import/error', $this->create_callback( 'sync_log_log_error', function ( $error ) use ( $container ) { - $container[ self::SYNC_LOG ]->log_error( $error ); - } ) ); + add_action( 'bigcommerce/import/error', $this->create_callback( 'sync_log_log_error', function ( $error ) use ( $container ) { + $container[ self::SYNC_LOG ]->log_error( $error ); + } ) ); - add_action( 'bigcommerce/import/logs/rotate', $this->create_callback( 'sync_log_complete_sync', function ( $log ) use ( $container ) { - $container[ self::SYNC_LOG ]->complete_sync( $log ); - } ) ); + add_action( 'bigcommerce/import/logs/rotate', $this->create_callback( 'sync_log_complete_sync', function ( $log ) use ( $container ) { + $container[ self::SYNC_LOG ]->complete_sync( $log ); + } ) ); - add_filter( 'bigcommerce/diagnostics', $this->create_callback( 'sync_log_diagnostics', function ( $data ) use ( $container ) { - return $container[ self::SYNC_LOG ]->diagnostic_data( $data ); - } ), 10, 1 ); - } + add_filter( 'bigcommerce/diagnostics', $this->create_callback( 'sync_log_diagnostics', function ( $data ) use ( $container ) { + return $container[ self::SYNC_LOG ]->diagnostic_data( $data ); + } ), 10, 1 ); + } - private function product_store_links( Container $container ) { - $container[ self::STORE_LINKS ] = function ( Container $container ) { - return new Product\Store_Links( $container[ Api::FACTORY ] ); - }; - add_filter( 'post_row_actions', $this->create_callback( 'post_row_link', function ( $actions, $post ) use ( $container ) { - return $container[ self::STORE_LINKS ]->add_row_action( $actions, $post ); - } ), 10, 2 ); - add_filter( 'post_submitbox_misc_actions', $this->create_callback( 'submitbox_store_link', function ( $post ) use ( $container ) { - $container[ self::STORE_LINKS ]->add_submitbox_link( $post ); - } ), 10, 1 ); - add_filter( 'bigcommerce/gutenberg/js_config', $this->create_callback( 'gutenberg_store_link', function ( $data ) use ( $container ) { - return $container[ self::STORE_LINKS ]->add_link_to_gutenberg_config( $data ); - } ), 10, 1 ); - add_action( 'admin_bar_menu', $this->create_callback( 'admin_bar_edit_link', function ( $wp_admin_bar ) use ( $container ) { - $container[ self::STORE_LINKS ]->modify_edit_product_links_admin_bar( $wp_admin_bar ); - } ), 81, 1 ); - } + /** + * Adds product store links to various admin actions. + * + * @param Container $container The service container. + * + * @return void + */ + private function product_store_links( Container $container ) { + $container[ self::STORE_LINKS ] = function ( Container $container ) { + return new Product\Store_Links( $container[ Api::FACTORY ] ); + }; - private function product_listing_reset( Container $container ) { - $container[ self::LISTING_RESET ] = function ( Container $container ) { - return new Product\Reset_Listing(); - }; - add_filter( 'post_row_actions', $this->create_callback( 'post_row_reset', function ( $actions, $post ) use ( $container ) { - return $container[ self::LISTING_RESET ]->add_row_action( $actions, $post ); - } ), 10, 2 ); - add_action( 'admin_post_' . Product\Reset_Listing::ACTION, $this->create_callback( 'handle_reset_listing', function () use ( $container ) { - $container[ self::LISTING_RESET ]->handle_request(); - } ), 10, 0 ); - } + add_filter( 'post_row_actions', $this->create_callback( 'post_row_link', function ( $actions, $post ) use ( $container ) { + return $container[ self::STORE_LINKS ]->add_row_action( $actions, $post ); + } ), 10, 2 ); - private function product_resync( Container $container ) { - $container[ self::PRODUCT_RESYNC ] = function ( Container $container ) { - return new Product\Single_Product_Sync(); - }; - add_filter( 'post_row_actions', $this->create_callback( 'post_row_resync', function ( $actions, $post ) use ( $container ) { - return $container[ self::PRODUCT_RESYNC ]->add_row_action( $actions, $post ); - } ), 10, 2 ); - add_action( 'admin_post_' . Product\Single_Product_Sync::ACTION, $this->create_callback( 'handle_resync_product', function () use ( $container ) { - $container[ self::PRODUCT_RESYNC ]->handle_request(); - } ), 10, 0 ); - } + add_filter( 'post_submitbox_misc_actions', $this->create_callback( 'submitbox_store_link', function ( $post ) use ( $container ) { + $container[ self::STORE_LINKS ]->add_submitbox_link( $post ); + } ), 10, 1 ); - private function product_channel_indicator( Container $container ) { - $container[ self::CHANNEL_INDICATOR ] = function ( Container $container ) { - return new Product\Channel_Indicator(); - }; - add_action( 'post_submitbox_misc_actions', $this->create_callback( 'submitbox_channel_indicator', function ( $post ) use ( $container ) { - if ( Channel::multichannel_enabled() ) { - $container[ self::CHANNEL_INDICATOR ]->add_submitbox_message( $post ); - } - } ), 10, 1 ); - add_filter( 'bigcommerce/gutenberg/js_config', $this->create_callback( 'gutenberg_channel_indicator', function ( $data ) use ( $container ) { - if ( Channel::multichannel_enabled() ) { - return $container[ self::CHANNEL_INDICATOR ]->add_message_to_gutenberg_config( $data ); - } + add_filter( 'bigcommerce/gutenberg/js_config', $this->create_callback( 'gutenberg_store_link', function ( $data ) use ( $container ) { + return $container[ self::STORE_LINKS ]->add_link_to_gutenberg_config( $data ); + } ), 10, 1 ); - return $data; - } ), 10, 1 ); - } + add_action( 'admin_bar_menu', $this->create_callback( 'admin_bar_edit_link', function ( $wp_admin_bar ) use ( $container ) { + $container[ self::STORE_LINKS ]->modify_edit_product_links_admin_bar( $wp_admin_bar ); + } ), 81, 1 ); + } - private function channel_sync( Container $container ) { - $container[ self::CHANNEL_SYNC ] = function ( Container $container ) { - return new Product\Channel_Sync( $container[ Api::FACTORY ]->channels() ); - }; + /** + * Resets product listings based on specific actions. + * + * @param Container $container The service container. + * + * @return void + */ + private function product_listing_reset( Container $container ) { + $container[ self::LISTING_RESET ] = function ( Container $container ) { + return new Product\Reset_Listing(); + }; - add_action( 'save_post', $this->create_callback( 'sync_to_channel', function ( $post_id, $post ) use ( $container ) { - $container[ self::CHANNEL_SYNC ]->post_updated( $post_id, $post ); - } ), 10, 2 ); - add_action( 'before_delete_post', $this->create_callback( 'delete_from_channel', function ( $post_id ) use ( $container ) { - $container[ self::CHANNEL_SYNC ]->post_deleted( $post_id ); - } ), 5, 1 ); - } + add_filter( 'post_row_actions', $this->create_callback( 'post_row_reset', function ( $actions, $post ) use ( $container ) { + return $container[ self::LISTING_RESET ]->add_row_action( $actions, $post ); + } ), 10, 2 ); - /** - * @param Container $container - * - * @return void - */ - private function product_slugs( Container $container ) { - $container[ self::PRODUCT_UNIQUE_SLUG ] = function ( Container $container ) { - return new Product\Unique_Slug_Filter(); - }; - - add_filter( 'wp_unique_post_slug', $this->create_callback( 'unique_slug_per_channel', function ( $slug, $post_id, $post_status, $post_type, $post_parent, $original_slug ) use ( $container ) { - if ( Channel::multichannel_enabled() ) { - return $container[ self::PRODUCT_UNIQUE_SLUG ]->get_unique_slug( $slug, $post_id, $post_status, $post_type, $post_parent, $original_slug ); - } + add_action( 'admin_post_' . Product\Reset_Listing::ACTION, $this->create_callback( 'handle_reset_listing', function () use ( $container ) { + $container[ self::LISTING_RESET ]->handle_request(); + } ), 10, 0 ); + } - return $slug; - } ), 10, 6 ); - } + /** + * Resyncs a single product based on user action. + * + * @param Container $container The service container. + * + * @return void + */ + private function product_resync( Container $container ) { + $container[ self::PRODUCT_RESYNC ] = function ( Container $container ) { + return new Product\Single_Product_Sync(); + }; - private function product_seo( Container $container ) { - $container[ self::PRODUCT_SEO ] = function ( Container $container ) { - return new Product\Seo(); - }; - add_filter( 'wp_title_parts', $this->create_callback( 'product_wp_title', function ( $title_parts ) use ( $container ) { - return $container[ self::PRODUCT_SEO ]->filter_wp_title( $title_parts ); - } ), 10, 1 ); - add_filter( 'document_title_parts', $this->create_callback( 'product_document_title', function ( $title_parts ) use ( $container ) { - return $container[ self::PRODUCT_SEO ]->filter_document_title( $title_parts ); - } ), 10, 1 ); - add_filter( 'wp_head', $this->create_callback( 'product_page_meta_description', function () use ( $container ) { - if ( get_option( Product_Single::META_DESC_DISABLE, 'yes' ) !== 'yes' ) { - return null; - } + add_filter( 'post_row_actions', $this->create_callback( 'post_row_resync', function ( $actions, $post ) use ( $container ) { + return $container[ self::PRODUCT_RESYNC ]->add_row_action( $actions, $post ); + } ), 10, 2 ); - return $container[ self::PRODUCT_SEO ]->print_meta_description(); - } ), 0, 0 ); - } + add_action( 'admin_post_' . Product\Single_Product_Sync::ACTION, $this->create_callback( 'handle_resync_product', function () use ( $container ) { + $container[ self::PRODUCT_RESYNC ]->handle_request(); + } ), 10, 0 ); + } + + /** + * Adds a channel indicator for products when enabled. + * + * @param Container $container The service container. + * + * @return void + */ + private function product_channel_indicator( Container $container ) { + $container[ self::CHANNEL_INDICATOR ] = function ( Container $container ) { + return new Product\Channel_Indicator(); + }; + + add_action( 'post_submitbox_misc_actions', $this->create_callback( 'submitbox_channel_indicator', function ( $post ) use ( $container ) { + if ( Channel::multichannel_enabled() ) { + $container[ self::CHANNEL_INDICATOR ]->add_submitbox_message( $post ); + } + } ), 10, 1 ); + + add_filter( 'bigcommerce/gutenberg/js_config', $this->create_callback( 'gutenberg_channel_indicator', function ( $data ) use ( $container ) { + if ( Channel::multichannel_enabled() ) { + return $container[ self::CHANNEL_INDICATOR ]->add_message_to_gutenberg_config( $data ); + } + + return $data; + } ), 10, 1 ); + } + + /** + * Synchronizes product data with external channels. + * + * @param Container $container The service container. + * + * @return void + */ + private function channel_sync( Container $container ) { + $container[ self::CHANNEL_SYNC ] = function ( Container $container ) { + return new Product\Channel_Sync( $container[ Api::FACTORY ]->channels() ); + }; + + add_action( 'save_post', $this->create_callback( 'sync_to_channel', function ( $post_id, $post ) use ( $container ) { + $container[ self::CHANNEL_SYNC ]->post_updated( $post_id, $post ); + } ), 10, 2 ); + + add_action( 'before_delete_post', $this->create_callback( 'delete_from_channel', function ( $post_id ) use ( $container ) { + $container[ self::CHANNEL_SYNC ]->post_deleted( $post_id ); + } ), 5, 1 ); + } + + /** + * Adds unique slugs for products based on the channel context. + * + * @param Container $container The service container. + * + * @return void + */ + private function product_slugs( Container $container ) { + $container[ self::PRODUCT_UNIQUE_SLUG ] = function ( Container $container ) { + return new Product\Unique_Slug_Filter(); + }; + + add_filter( 'wp_unique_post_slug', $this->create_callback( 'unique_slug_per_channel', function ( $slug, $post_id, $post_status, $post_type, $post_parent, $original_slug ) use ( $container ) { + if ( Channel::multichannel_enabled() ) { + return $container[ self::PRODUCT_UNIQUE_SLUG ]->get_unique_slug( $slug, $post_id, $post_status, $post_type, $post_parent, $original_slug ); + } + + return $slug; + } ), 10, 6 ); + } + + /** + * Handles product SEO settings. + * + * @param Container $container The service container. + * + * @return void + */ + private function product_seo( Container $container ) { + $container[ self::PRODUCT_SEO ] = function ( Container $container ) { + return new Product\Seo(); + }; + + add_filter( 'wp_title_parts', $this->create_callback( 'product_wp_title', function ( $title_parts ) use ( $container ) { + return $container[ self::PRODUCT_SEO ]->filter_wp_title( $title_parts ); + } ), 10, 1 ); + + add_filter( 'document_title_parts', $this->create_callback( 'product_document_title', function ( $title_parts ) use ( $container ) { + return $container[ self::PRODUCT_SEO ]->filter_document_title( $title_parts ); + } ), 10, 1 ); + + add_filter( 'wp_head', $this->create_callback( 'product_page_meta_description', function () use ( $container ) { + if ( get_option( Product_Single::META_DESC_DISABLE, 'yes' ) !== 'yes' ) { + return null; + } + + return $container[ self::PRODUCT_SEO ]->print_meta_description(); + } ), 0, 0 ); + } } diff --git a/src/BigCommerce/Container/Provider.php b/src/BigCommerce/Container/Provider.php index 82e9f4d8..b4f930c8 100644 --- a/src/BigCommerce/Container/Provider.php +++ b/src/BigCommerce/Container/Provider.php @@ -1,26 +1,52 @@ callbacks ) ) { - return $this->callbacks[ $property ]; - } - return null; - } + /** + * @var array $callbacks Holds a collection of registered callbacks identified by unique identifiers. + */ + protected $callbacks = []; + + /** + * Magic method to retrieve registered callbacks by their identifier. + * + * This method allows access to the registered callbacks using property syntax. If the requested property is found + * in the `$callbacks` array, it returns the corresponding callback; otherwise, it returns `null`. + * + * @param string $property The identifier of the callback to retrieve. + * + * @return callable|null The registered callback, or `null` if not found. + */ + public function __get( $property ) { + if ( array_key_exists( $property, $this->callbacks ) ) { + return $this->callbacks[ $property ]; + } + return null; + } - protected function create_callback( $identifier, callable $callback ) { - if ( array_key_exists( $identifier, $this->callbacks ) ) { - throw new \InvalidArgumentException( sprintf( __( 'Invalid identifier: %s has already been set.', 'bigcommerce' ), $identifier ) ); - } - $this->callbacks[ $identifier ] = $callback; - return $callback; - } + /** + * Creates and registers a callback for a specific identifier. + * + * This method ensures that a callback is not already registered under the same identifier. If the identifier is + * already in use, an exception is thrown. Otherwise, it adds the callback to the `$callbacks` array. + * + * @param string $identifier The unique identifier for the callback. + * @param callable $callback The callback function to register. + * + * @throws \InvalidArgumentException If the identifier is already in use. + * + * @return callable The registered callback. + */ + protected function create_callback( $identifier, callable $callback ) { + if ( array_key_exists( $identifier, $this->callbacks ) ) { + throw new \InvalidArgumentException( sprintf( __( 'Invalid identifier: %s has already been set.', 'bigcommerce' ), $identifier ) ); + } + $this->callbacks[ $identifier ] = $callback; + return $callback; + } } \ No newline at end of file diff --git a/src/BigCommerce/Container/Proxy.php b/src/BigCommerce/Container/Proxy.php index 66e95814..a04342e1 100644 --- a/src/BigCommerce/Container/Proxy.php +++ b/src/BigCommerce/Container/Proxy.php @@ -2,7 +2,7 @@ /** * This container provider adds a WordPress proxy layer on top of the BigCommerce API. * - * @package BigCommere + * @package BigCommerce */ namespace BigCommerce\Container; @@ -13,46 +13,86 @@ use Pimple\Container; /** - * Proxy provider class + * This class registers the proxy container that adds a Wordpress proxy layer on top of the BigCommerce API. + * Sets up necessary services such as REST controllers, caching, and AMP cart controllers. + * + * @package BigCommerce */ class Proxy extends Provider { - const ACCESS = 'proxy.access'; - const REST_CONTROLLER = 'proxy.rest_controller'; - const CACHE = 'proxy.cache'; - const PROXY_BASE = 'proxy.base'; - const AMP_CART_CONTROLLER = 'proxy.amp_cart_controller'; - const CACHE_PRIORITY = 10; - - /** - * The proxy base, set in the constructor. - * - * @var string - */ - private $proxy_base = ''; - - /** - * Registers the container. - * - * @param Container $container A container instance. - */ - public function register( Container $container ) { - $container[ self::PROXY_BASE ] = function( Container $container ) { + /** + * Constant for the proxy access service. + * + * @var string + */ + const ACCESS = 'proxy.access'; + + /** + * Constant for the REST controller service. + * + * @var string + */ + const REST_CONTROLLER = 'proxy.rest_controller'; + + /** + * Constant for the cache service. + * + * @var string + */ + const CACHE = 'proxy.cache'; + + /** + * Constant for the proxy base service. + * + * @var string + */ + const PROXY_BASE = 'proxy.base'; + + /** + * Constant for the AMP cart controller service. + * + * @var string + */ + const AMP_CART_CONTROLLER = 'proxy.amp_cart_controller'; + + /** + * Cache priority constant. + * + * @var int + */ + const CACHE_PRIORITY = 10; + + /** + * The proxy base URL, set in the constructor. + * + * @var string + */ + private $proxy_base = ''; + + /** + * Registers the container and initializes proxy-related services such as REST controller, cache, and AMP cart controller. + * + * @param Container $container A container instance. + * + * @return void + */ + public function register( Container $container ) { + $container[ self::PROXY_BASE ] = function( Container $container ) { /** * Filters the REST base use for proxy API requests. * * @param string Default 'bc/v3'. */ - return apply_filters( 'bigcommerce/rest/proxy_base', 'bc/v3' ); - }; + return apply_filters( 'bigcommerce/rest/proxy_base', 'bc/v3' ); + }; - $this->rest_controller( $container ); - $this->cache( $container ); - $this->amp_cart_controller( $container ); - } + $this->rest_controller( $container ); + $this->cache( $container ); + $this->amp_cart_controller( $container ); + } /** - * Sets up the endpoint contianer. + * Sets up the endpoint container. * * @param Container $container The Container instance. */ @@ -68,111 +108,113 @@ private function rest_controller( Container $container ) { ); }; - // Initialise the proxy. - add_action( - 'rest_api_init', - $this->create_callback( - 'start_proxy_controller', - function() use ( $container ) { - $container[ self::REST_CONTROLLER ]->register_routes(); - } - ) - ); - } - - /** - * Sets up the cache container. - * - * @param Container $container The Container instance. - */ - private function cache( Container $container ) { - $container[ self::CACHE ] = function ( Container $container ) { - return new Proxy_Cache( - [ - 'proxy_base' => $container[ self::PROXY_BASE ], - ] - ); - }; + add_action( + 'rest_api_init', + $this->create_callback( + 'start_proxy_controller', + function() use ( $container ) { + $container[ self::REST_CONTROLLER ]->register_routes(); + } + ) + ); + } + + /** + * Sets up the cache container for proxy requests. + * + * @param Container $container The Container instance. + * + * @return void + */ + private function cache( Container $container ) { + $container[ self::CACHE ] = function ( Container $container ) { + return new Proxy_Cache( + [ + 'proxy_base' => $container[ self::PROXY_BASE ], + ] + ); + }; /** * Filters whether to use the proxy cache. * - * @param bool Defaul true. + * @param bool Default true. */ - $use_cache = apply_filters( 'bigcommerce/proxy/use_cache', true ); - - if ( ! $use_cache ) { - return; - } - - add_filter( - 'bigcommerce/proxy/result_pre', - $this->create_callback( - 'before_fetch_result', - function( $result, $args ) use ( $container ) { - if ( $container[ Api::CONFIG_COMPLETE ] ) { - return $container[ self::CACHE ]->get_result( $result, $args ); - } - - return $result; - } - ), - self::CACHE_PRIORITY, - 7, - 2 - ); - - add_action( - 'bigcommerce/proxy/response_received', - $this->create_callback( - 'on_response_received', - function( $result, $args ) use ( $container ) { - if ( $container[ Api::CONFIG_COMPLETE ] ) { - $container[ self::CACHE ]->handle_result( $result, $args ); - } - } - ), - self::CACHE_PRIORITY, - 2 - ); - - add_action( - 'bigcommerce/webhooks/product_updated', - $this->create_callback( - 'on_product_updated', - function( $product_id ) use ( $container ) { - $container[ self::CACHE ]->bust_product_cache( $product_id['product_id'] ); - } - ) - ); - } - - /** - * Sets up the AMP cart controller container. - * - * @param Container $container The Container instance. - */ - private function amp_cart_controller( Container $container ) { - $container[ self::AMP_CART_CONTROLLER ] = function ( Container $container ) { - return new AMP_Cart_Controller( - [ - 'host' => $container[ Api::HOST ], - 'client_id' => $container[ Api::CLIENT_ID ], - 'access_token' => $container[ Api::ACCESS_TOKEN ], - 'proxy_base' => $container[ self::PROXY_BASE ], - ] - ); - }; - - // Initialise the proxy. - add_action( - 'rest_api_init', - $this->create_callback( - 'init_amp_cart_controller', - function() use ( $container ) { - $container[ self::AMP_CART_CONTROLLER ]->register_routes(); - } - ) - ); - } + $use_cache = apply_filters( 'bigcommerce/proxy/use_cache', true ); + + if ( ! $use_cache ) { + return; + } + + add_filter( + 'bigcommerce/proxy/result_pre', + $this->create_callback( + 'before_fetch_result', + function( $result, $args ) use ( $container ) { + if ( $container[ Api::CONFIG_COMPLETE ] ) { + return $container[ self::CACHE ]->get_result( $result, $args ); + } + + return $result; + } + ), + self::CACHE_PRIORITY, + 7, + 2 + ); + + add_action( + 'bigcommerce/proxy/response_received', + $this->create_callback( + 'on_response_received', + function( $result, $args ) use ( $container ) { + if ( $container[ Api::CONFIG_COMPLETE ] ) { + $container[ self::CACHE ]->handle_result( $result, $args ); + } + } + ), + self::CACHE_PRIORITY, + 2 + ); + + add_action( + 'bigcommerce/webhooks/product_updated', + $this->create_callback( + 'on_product_updated', + function( $product_id ) use ( $container ) { + $container[ self::CACHE ]->bust_product_cache( $product_id['product_id'] ); + } + ) + ); + } + + /** + * Sets up the AMP cart controller container for AMP-specific requests. + * + * @param Container $container The Container instance. + * + * @return void + */ + private function amp_cart_controller( Container $container ) { + $container[ self::AMP_CART_CONTROLLER ] = function ( Container $container ) { + return new AMP_Cart_Controller( + [ + 'host' => $container[ Api::HOST ], + 'client_id' => $container[ Api::CLIENT_ID ], + 'access_token' => $container[ Api::ACCESS_TOKEN ], + 'proxy_base' => $container[ self::PROXY_BASE ], + ] + ); + }; + + add_action( + 'rest_api_init', + $this->create_callback( + 'init_amp_cart_controller', + function() use ( $container ) { + $container[ self::AMP_CART_CONTROLLER ]->register_routes(); + } + ) + ); + } } diff --git a/src/BigCommerce/Container/Rest.php b/src/BigCommerce/Container/Rest.php index c638ba3b..00282bee 100644 --- a/src/BigCommerce/Container/Rest.php +++ b/src/BigCommerce/Container/Rest.php @@ -18,45 +18,196 @@ use BigCommerce\Reviews\Review_Fetcher; use Pimple\Container; +/** + * Provides RESTful controllers and endpoints for BigCommerce integration. + * + * @package BigCommerce\Container + */ class Rest extends Provider { + /** + * The base namespace for REST API routes. + * + * @var string + */ const NAMESPACE_BASE = 'rest.namespace'; - const VERSION = 'rest.version'; + /** + * The version of the REST API. + * + * @var string + */ + const VERSION = 'rest.version'; + + /** + * The base route for the cart API. + * + * @var string + */ const CART_BASE = 'rest.cart_base'; - const CART = 'rest.cart'; + /** + * The cart API identifier. + * + * @var string + */ + const CART = 'rest.cart'; + + /** + * The base route for the products API. + * + * @var string + */ const PRODUCTS_BASE = 'rest.products_base'; - const PRODUCTS = 'rest.products'; + /** + * The products API identifier. + * + * @var string + */ + const PRODUCTS = 'rest.products'; + + /** + * The base route for the storefront API. + * + * @var string + */ const STOREFRONT_BASE = 'rest.storefront_base'; - const STOREFRONT = 'rest.storefront'; + /** + * The storefront API identifier. + * + * @var string + */ + const STOREFRONT = 'rest.storefront'; + + /** + * The base route for the terms API. + * + * @var string + */ const TERMS_BASE = 'rest.terms_base'; - const TERMS = 'rest.terms'; + /** + * The terms API identifier. + * + * @var string + */ + const TERMS = 'rest.terms'; + + /** + * The base route for the shortcode API. + * + * @var string + */ const SHORTCODE_BASE = 'rest.shortcode_base'; - const SHORTCODE = 'rest.shortcode'; + /** + * The shortcode API identifier. + * + * @var string + */ + const SHORTCODE = 'rest.shortcode'; + + /** + * The base route for the orders shortcode API. + * + * @var string + */ const ORDERS_SHORTCODE_BASE = 'rest.orders_shortcode_base'; - const ORDERS_SHORTCODE = 'rest.orders_shortcode'; + /** + * The orders shortcode API identifier. + * + * @var string + */ + const ORDERS_SHORTCODE = 'rest.orders_shortcode'; + + /** + * The base route for the product component shortcode API. + * + * @var string + */ const COMPONENT_SHORTCODE_BASE = 'rest.product_component_shortcode_base'; - const COMPONENT_SHORTCODE = 'rest.product_component_shortcode'; + /** + * The product component shortcode API identifier. + * + * @var string + */ + const COMPONENT_SHORTCODE = 'rest.product_component_shortcode'; + + /** + * The base route for the review list API. + * + * @var string + */ const REVIEW_LIST_BASE = 'rest.review_list_base'; - const REVIEW_LIST = 'rest.review_list'; + /** + * The review list API identifier. + * + * @var string + */ + const REVIEW_LIST = 'rest.review_list'; + + /** + * The base route for the pricing API. + * + * @var string + */ const PRICING_BASE = 'rest.pricing_base'; - const PRICING = 'rest.pricing'; + /** + * The pricing API identifier. + * + * @var string + */ + const PRICING = 'rest.pricing'; + + /** + * The base route for the shipping API. + * + * @var string + */ const SHIPPING_BASE = 'rest.shipping_base'; - const SHIPPING = 'rest.shipping'; + /** + * The shipping API identifier. + * + * @var string + */ + const SHIPPING = 'rest.shipping'; + + /** + * The base route for the coupon code API. + * + * @var string + */ const COUPON_CODE_BASE = 'rest.coupon_code_base'; - const COUPON_CODE = 'rest.coupon_code'; + /** + * The coupon code API identifier. + * + * @var string + */ + const COUPON_CODE = 'rest.coupon_code'; + + /** + * The version of the REST API used by the container. It is referenced when setting up the + * `VERSION` service in the container, ensuring that the API version can be applied to the various API endpoints + * and controllers. + * + * @var string + */ private $version = 1; + /** + * Registers services and controllers in the container and sets up REST API hooks. + * + * @param Container $container The dependency injection container instance. + * + * @return void + */ public function register( Container $container ) { $container[ self::NAMESPACE_BASE ] = function ( Container $container ) { /** diff --git a/src/BigCommerce/Container/Reviews.php b/src/BigCommerce/Container/Reviews.php index ba5bb9c8..77201f86 100644 --- a/src/BigCommerce/Container/Reviews.php +++ b/src/BigCommerce/Container/Reviews.php @@ -8,31 +8,96 @@ use BigCommerce\Reviews\Review_Fetcher; use Pimple\Container; +/** + * Provides functionality for managing reviews in the BigCommerce container. + * + * Registers services for handling review-related operations, including caching, + * fetching, and product updates. + */ class Reviews extends Provider { - const PRODUCT_LISTENER = 'reviews.product_listener'; - const FETCHER = 'reviews.fetcher'; - const CACHER = 'reviews.cacher'; - - public function register( Container $container ) { - $container[ self::PRODUCT_LISTENER ] = function ( Container $container ) { - return new Product_Update_Listener(); - }; - $meta_update = $this->create_callback( 'product_meta_updated', function ( $meta_id, $post_id, $meta_key, $meta_value ) use ( $container ) { - $container[ self::PRODUCT_LISTENER ]->meta_updated( $meta_id, $post_id, $meta_key, $meta_value ); - } ); - add_action( 'added_post_meta', $meta_update, 10, 4 ); - add_action( 'updated_post_meta', $meta_update, 10, 4 ); - - $container[ self::FETCHER ] = function ( Container $container ) { - return new Review_Fetcher( $container[ Api::FACTORY ]->catalog() ); - }; - - $container[ self::CACHER ] = function ( Container $container ) { - return new Review_Cache( $container[ self::FETCHER ] ); - }; - add_action( Product_Update_Listener::TRIGGER_UPDATE, $this->create_callback( 'update_cache', function ( $product_id ) use ( $container ) { - $container[ self::CACHER ]->update_cache( $product_id ); - } ), 10, 1 ); - } + /** + * Key for the product listener service. + * + * @var string + */ + const PRODUCT_LISTENER = 'reviews.product_listener'; + /** + * Key for the review fetcher service. + * + * @var string + */ + const FETCHER = 'reviews.fetcher'; + + /** + * Key for the review cache service. + * + * @var string + */ + const CACHER = 'reviews.cacher'; + + /** + * Registers review-related services in the container. + * + * Services include: + * - Product update listener for tracking metadata changes. + * - Review fetcher for retrieving reviews from the API. + * - Review cache for caching reviews and updating the cache on product updates. + * + * @param Container $container The DI container for registering services. + */ + public function register(Container $container) { + /** + * Registers the Product_Update_Listener service. + * + * Listens for updates to product metadata and processes them accordingly. + * + * @return Product_Update_Listener The product update listener instance. + */ + $container[self::PRODUCT_LISTENER] = function (Container $container) { + return new Product_Update_Listener(); + }; + + /** + * Callback for handling product meta updates. + * + * Triggered when product metadata is added or updated. + * + * @param int $meta_id The ID of the metadata entry. + * @param int $post_id The ID of the product post. + * @param string $meta_key The metadata key. + * @param mixed $meta_value The metadata value. + */ + $meta_update = $this->create_callback('product_meta_updated', function ($meta_id, $post_id, $meta_key, $meta_value) use ($container) { + $container[self::PRODUCT_LISTENER]->meta_updated($meta_id, $post_id, $meta_key, $meta_value); + }); + add_action('added_post_meta', $meta_update, 10, 4); + add_action('updated_post_meta', $meta_update, 10, 4); + + /** + * Registers the Review_Fetcher service. + * + * Fetches reviews from the API using the catalog client. + * + * @return Review_Fetcher The review fetcher instance. + */ + $container[self::FETCHER] = function (Container $container) { + return new Review_Fetcher($container[Api::FACTORY]->catalog()); + }; + + /** + * Registers the Review_Cache service. + * + * Handles caching of reviews and updating the cache when necessary. + * + * @return Review_Cache The review cache instance. + */ + $container[self::CACHER] = function (Container $container) { + return new Review_Cache($container[self::FETCHER]); + }; + + add_action(Product_Update_Listener::TRIGGER_UPDATE, $this->create_callback('update_cache', function ($product_id) use ($container) { + $container[self::CACHER]->update_cache($product_id); + }), 10, 1); + } } diff --git a/src/BigCommerce/Container/Rewrites.php b/src/BigCommerce/Container/Rewrites.php index fd4dac38..c705a85d 100644 --- a/src/BigCommerce/Container/Rewrites.php +++ b/src/BigCommerce/Container/Rewrites.php @@ -1,47 +1,90 @@ create_callback( 'register_action_route', function () use ( $container ) { - $container[ self::ACTION_ENDPOINT ]->register_route(); - } ), 10, 0 ); - - add_action( 'parse_request', $this->create_callback( 'parse_action_request', function ( \WP $wp ) use ( $container ) { - $container[ self::ACTION_ENDPOINT ]->handle_request( $wp ); - } ), 10, 1 ); - - $container[ self::FLUSH ] = function ( Container $container ) { - return new Flusher(); - }; - - add_action( 'wp_loaded', $this->create_callback( 'flush', function () use ( $container ) { - $container[ self::FLUSH ]->do_flush(); - } ), 10, 0 ); - - $schedule_flush = $this->create_callback( 'schedule_flush', function () use ( $container ) { - $container[ self::FLUSH ]->schedule_flush(); - } ); - add_action( 'update_option_' . Product_Archive::ARCHIVE_SLUG, $schedule_flush, 10, 0 ); - add_action( 'update_option_' . Product_Archive::CATEGORY_SLUG, $schedule_flush, 10, 0 ); - add_action( 'update_option_' . Product_Archive::BRAND_SLUG, $schedule_flush, 10, 0 ); - add_action( 'add_option_' . Product_Archive::ARCHIVE_SLUG, $schedule_flush, 10, 0 ); - add_action( 'add_option_' . Product_Archive::CATEGORY_SLUG, $schedule_flush, 10, 0 ); - add_action( 'add_option_' . Product_Archive::BRAND_SLUG, $schedule_flush, 10, 0 ); - } + /** + * Key for the Action_Endpoint service. + * + * @var string + */ + const ACTION_ENDPOINT = 'rewrites.action_endpoint'; + + /** + * Key for the Flusher service. + * + * @var string + */ + const FLUSH = 'rewrites.flush'; + + /** + * Registers rewrite-related services and hooks in the container. + * + * Services include: + * - Action endpoint for managing custom route registration and requests. + * - Flusher for handling permalink flush operations. + * + * @param Container $container The DI container for registering services. + */ + public function register(Container $container) { + /** + * Registers the Action_Endpoint service. + * + * Manages the registration of a custom action route and handles incoming + * requests for that route. + * + * @return Action_Endpoint The action endpoint instance. + */ + $container[self::ACTION_ENDPOINT] = function (Container $container) { + return new Action_Endpoint(); + }; + + add_action('init', $this->create_callback('register_action_route', function () use ($container) { + $container[self::ACTION_ENDPOINT]->register_route(); + }), 10, 0); + + add_action('parse_request', $this->create_callback('parse_action_request', function (\WP $wp) use ($container) { + $container[self::ACTION_ENDPOINT]->handle_request($wp); + }), 10, 1); + + /** + * Registers the Flusher service. + * + * Handles flushing permalink rules and scheduling flush operations. + * + * @return Flusher The flusher instance. + */ + $container[self::FLUSH] = function (Container $container) { + return new Flusher(); + }; + + add_action('wp_loaded', $this->create_callback('flush', function () use ($container) { + $container[self::FLUSH]->do_flush(); + }), 10, 0); + + /** + * Callback schedules a flush operation when certain product archive options are updated or added. + */ + $schedule_flush = $this->create_callback('schedule_flush', function () use ($container) { + $container[self::FLUSH]->schedule_flush(); + }); + + add_action('update_option_' . Product_Archive::ARCHIVE_SLUG, $schedule_flush, 10, 0); + add_action('update_option_' . Product_Archive::CATEGORY_SLUG, $schedule_flush, 10, 0); + add_action('update_option_' . Product_Archive::BRAND_SLUG, $schedule_flush, 10, 0); + add_action('add_option_' . Product_Archive::ARCHIVE_SLUG, $schedule_flush, 10, 0); + add_action('add_option_' . Product_Archive::CATEGORY_SLUG, $schedule_flush, 10, 0); + add_action('add_option_' . Product_Archive::BRAND_SLUG, $schedule_flush, 10, 0); + } } diff --git a/src/BigCommerce/Container/Schema.php b/src/BigCommerce/Container/Schema.php index 71604967..885a2544 100644 --- a/src/BigCommerce/Container/Schema.php +++ b/src/BigCommerce/Container/Schema.php @@ -1,52 +1,142 @@ tables( $container ); - $this->roles( $container ); - } - - private function tables( Container $container ) { - $container[ self::TABLE_REVIEWS ] = function( Container $container ) { - return new Reviews_Table(); - }; - - $container[ self::TABLE_QUEUES ] = function( Container $container ) { - return new Queue_Table(); - }; - - add_action( 'plugins_loaded', $this->create_callback( 'tables_plugins_loaded', function () use ( $container ) { - $container[ self::TABLE_REVIEWS ]->register_tables(); - $container[ self::TABLE_QUEUES ]->register_tables(); - } ), 10, 0 ); - } - - private function roles( Container $container ) { - $container[ self::CUSTOMER_ROLE ] = function ( Container $container ) { - return new Customer(); - }; - $container[ self::ROLE_SCHEMA ] = function ( Container $container ) { - return new User_Roles( [ - $container[ self::CUSTOMER_ROLE ], - ] ); - }; - add_action( 'admin_init', $this->create_callback( 'init_roles', function () use ( $container ) { - $container[ self::ROLE_SCHEMA ]->register_roles(); - } ), 10, 0 ); - } + /** + * Key for the Reviews Table schema service. + * + * @var string + */ + const TABLE_REVIEWS = 'schema.table.reviews'; + + /** + * Key for the Queue Table schema service. + * + * @var string + */ + const TABLE_QUEUES = 'schema.table.queue'; + + /** + * Key for the Role Schema service. + * + * @var string + */ + const ROLE_SCHEMA = 'schema.roles'; + + /** + * Key for the Customer Role service. + * + * @var string + */ + const CUSTOMER_ROLE = 'schema.roles.customer'; + + /** + * Registers database schema and roles into the container. + * + * Services registered: + * - Reviews Table schema. + * - Queue Table schema. + * - Customer Role. + * - User Roles schema. + * + * Hooks registered: + * - `plugins_loaded`: Registers database tables. + * - `admin_init`: Registers user roles. + * + * @param Container $container The DI container for registering services. + */ + public function register(Container $container) { + $this->tables($container); + $this->roles($container); + } + + /** + * Registers database table-related services and hooks. + * + * Services registered: + * - `TABLE_REVIEWS`: Handles the schema for the reviews table. + * - `TABLE_QUEUES`: Handles the schema for the queue table. + * + * Hooks registered: + * - `plugins_loaded`: Triggers table schema registration. + * + * @param Container $container The DI container for registering services. + */ + private function tables(Container $container) { + /** + * Registers the Reviews Table schema service. + * + * @return Reviews_Table The reviews table schema handler. + */ + $container[self::TABLE_REVIEWS] = function (Container $container) { + return new Reviews_Table(); + }; + + /** + * Registers the Queue Table schema service. + * + * @return Queue_Table The queue table schema handler. + */ + $container[self::TABLE_QUEUES] = function (Container $container) { + return new Queue_Table(); + }; + + add_action('plugins_loaded', $this->create_callback('tables_plugins_loaded', function () use ($container) { + $container[self::TABLE_REVIEWS]->register_tables(); + $container[self::TABLE_QUEUES]->register_tables(); + }), 10, 0); + } + + /** + * Registers user role-related services and hooks. + * + * Services registered: + * - `CUSTOMER_ROLE`: Handles the "Customer" user role. + * - `ROLE_SCHEMA`: Manages user roles and their permissions. + * + * Hooks registered: + * - `admin_init`: Triggers user role registration. + * + * @param Container $container The DI container for registering services. + */ + private function roles(Container $container) { + /** + * Registers the Customer Role service. + * + * @return Customer The customer role handler. + */ + $container[self::CUSTOMER_ROLE] = function (Container $container) { + return new Customer(); + }; + + /** + * Registers the User Roles schema service. + * + * @return User_Roles The user roles schema handler. + */ + $container[self::ROLE_SCHEMA] = function (Container $container) { + return new User_Roles([ + $container[self::CUSTOMER_ROLE], + ]); + }; + + add_action('admin_init', $this->create_callback('init_roles', function () use ($container) { + $container[self::ROLE_SCHEMA]->register_roles(); + }), 10, 0); + } } diff --git a/src/BigCommerce/Container/Settings.php b/src/BigCommerce/Container/Settings.php index 19b8432b..5357d748 100644 --- a/src/BigCommerce/Container/Settings.php +++ b/src/BigCommerce/Container/Settings.php @@ -48,57 +48,289 @@ use BigCommerce\Taxonomies\Channel\Channel; use Pimple\Container; +/** + * Provides various screens and settings for BigCommerce. + * + * This class is responsible for registering settings screens, handling API credentials, + * and managing various onboarding steps in the BigCommerce plugin. + */ class Settings extends Provider { - const SETTINGS_SCREEN = 'settings.screen.settings'; - const WELCOME_SCREEN = 'settings.screen.welcome'; - const CREATE_SCREEN = 'settings.screen.create'; - const STORE_TYPE_SCREEN = 'settings.screen.store_type'; - const CHANNEL_SCREEN = 'settings.screen.channel'; - const PENDING_SCREEN = 'settings.screen.pending'; + /** + * Settings screen for general settings. + * @var string + */ + const SETTINGS_SCREEN = 'settings.screen.settings'; + + /** + * Welcome screen for onboarding. + * @var string + */ + const WELCOME_SCREEN = 'settings.screen.welcome'; + + /** + * Screen for creating an account. + * @var string + */ + const CREATE_SCREEN = 'settings.screen.create'; + + /** + * Screen for selecting the store type. + * @var string + */ + const STORE_TYPE_SCREEN = 'settings.screen.store_type'; + + /** + * Screen for channel settings. + * @var string + */ + const CHANNEL_SCREEN = 'settings.screen.channel'; + + /** + * Screen for pending accounts. + * @var string + */ + const PENDING_SCREEN = 'settings.screen.pending'; + + /** + * Screen for entering API credentials. + * @var string + */ const CREDENTIALS_SCREEN = 'settings.screen.credentials'; - const MENU_SETUP_SCREEN = 'settings.screen.nav_menu'; - const COMPLETE_SCREEN = 'settings.screen.onboarding_complete'; - const RESOURCES_SCREEN = 'settings.screen.resources'; - const API_SECTION = 'settings.section.api'; + /** + * Screen for setting up navigation menus. + * @var string + */ + const MENU_SETUP_SCREEN = 'settings.screen.nav_menu'; + + /** + * Screen for onboarding completion. + * @var string + */ + const COMPLETE_SCREEN = 'settings.screen.onboarding_complete'; + + /** + * Resources screen. + * @var string + */ + const RESOURCES_SCREEN = 'settings.screen.resources'; + + /** + * Section for API settings. + * @var string + */ + const API_SECTION = 'settings.section.api'; + + /** + * Section for connecting an account. + * @var string + */ const CONNECT_ACCOUNT_SECTION = 'settings.section.connect_account'; + + /** + * Section for cart-related settings. + * @var string + */ const CART_SECTION = 'settings.section.cart'; + + /** + * Section for gift certificate settings. + * @var string + */ const GIFT_CERTIFICATE_SECTION = 'settings.section.gift_certificates'; + + /** + * Section for currency settings. + * @var string + */ const CURRENCY_SECTION = 'settings.section.currency'; + + /** + * Section for data import settings. + * @var string + */ const IMPORT_SECTION = 'settings.section.import'; + + /** + * Section for account-related settings. + * @var string + */ const ACCOUNTS_SECTION = 'settings.section.accounts'; + + /** + * Section for analytics settings. + * @var string + */ const ANALYTICS_SECTION = 'settings.section.analytics'; + + /** + * Section for managing reviews. + * @var string + */ const REVIEWS_SECTION = 'settings.section.reviews'; + + /** + * Section for new account setup. + * @var string + */ const NEW_ACCOUNT_SECTION = 'settings.section.new_account'; + + /** + * Section for selecting a channel. + * @var string + */ const SELECT_CHANNEL_SECTION = 'settings.section.select_channel'; + + /** + * Section for configuring import settings. + * @var string + */ const IMPORT_SETTINGS_SECTION = 'settings.section.import_settings'; + + /** + * Section for channel settings. + * @var string + */ const CHANNEL_SECTION = 'settings.section.channel'; + + /** + * Section for diagnostics and troubleshooting. + * @var string + */ const DIAGNOSTICS_SECTION = 'settings.section.diagnostics'; + + /** + * Section for navigation menu options. + * @var string + */ const MENU_OPTIONS_SECTION = 'settings.section.nav_menu_options'; + + /** + * Section for next steps in the process. + * @var string + */ const NEXT_STEPS_SECTION = 'settings.section.next_steps'; + /** + * Represents the API connection status. + * @var string + */ const API_STATUS = 'settings.api_status'; + + /** + * Trigger for importing data immediately. + * @var string + */ const IMPORT_NOW = 'settings.import_now'; + + /** + * Status of the import process. + * @var string + */ const IMPORT_STATUS = 'settings.import_status'; + + /** + * Live status of the ongoing import process. + * @var string + */ const IMPORT_LIVE_STATUS = 'settings.import_status_live'; + + /** + * Action to restart the onboarding process. + * @var string + */ const START_OVER = 'settings.start_over'; + + /** + * Represents the progress of the onboarding process. + * @var string + */ const ONBOARDING_PROGRESS = 'settings.onboarding.progress_bar'; + + /** + * Synchronizes the site URL settings. + * @var string + */ const SITE_URL_SYNC = 'settings.site_url_sync'; + + /** + * Action to abort the product import process. + * @var string + */ const ABORT_IMPORT = 'settings.abort_product_import'; + + /** + * Action to clear cached data. + * @var string + */ const FLUSH_CACHE = 'settings.flush_cache'; + + /** + * Indicates headless processing status. + * @var string + */ const HEADLESS = 'settings.headless_processing'; + /** + * Overall configuration status. + * @var string + */ const CONFIG_STATUS = 'settings.configuration_status'; + + /** + * Display menus configuration option. + * @var string + */ const CONFIG_DISPLAY_MENUS = 'settings.configuration_display_menus'; + + /** + * Initial status for new configurations. + * @var string + */ const STATUS_NEW = 0; + + /** + * Status indicating account connection is pending. + * @var string + */ const STATUS_ACCOUNT_PENDING = 10; + + /** + * Status indicating the API connection is established. + * @var string + */ const STATUS_API_CONNECTED = 20; + + /** + * Status indicating a channel is connected. + * @var string + */ const STATUS_CHANNEL_CONNECTED = 40; + + /** + * Status indicating a store type has been selected. + * @var string + */ const STATUS_STORE_TYPE_SELECTED = 50; + + /** + * Status indicating menus have been created. + * @var string + */ const STATUS_MENUS_CREATED = 70; - const STATUS_COMPLETE = 1000; + /** + * Final status indicating the process is complete. + * @var string + */ + const STATUS_COMPLETE = 1000; + /** + * Registers settings and screens in the container. + * + * @param Container $container Dependency injection container. + * @return void + */ public function register( Container $container ) { $this->settings_screen( $container ); $this->api_credentials( $container ); @@ -121,6 +353,7 @@ private function settings_screen( Container $container ) { $container[ self::SETTINGS_SCREEN ] = function ( Container $container ) { return new Settings_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); }; + add_action( 'admin_menu', $this->create_callback( 'settings_screen_admin_menu', function () use ( $container ) { $container[ self::SETTINGS_SCREEN ]->register_settings_page(); } ), 10, 0 ); @@ -192,6 +425,7 @@ private function api_credentials( Container $container ) { $register_callback = $this->create_callback( 'api_credentials_register', function ( $suffix, $screen ) use ( $container ) { $container[ self::API_SECTION ]->register_settings_section( $suffix, $screen ); } ); + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $register_callback, 70, 2 ); add_action( 'bigcommerce/settings/register/screen=' . Api_Credentials_Screen::NAME, $register_callback, 10, 2 ); add_action( 'bigcommerce/settings/render/credentials', $this->create_callback( 'api_credentials_description', function () use ( $container ) { @@ -200,6 +434,7 @@ private function api_credentials( Container $container ) { $env_filter = $this->create_callback( 'api_credentials_env_override', function ( $value, $option, $default ) use ( $container ) { return $container[ self::API_SECTION ]->filter_option_with_env( $value, $option, $default ); } ); + add_filter( 'pre_option_' . Api_Credentials::OPTION_STORE_URL, $env_filter, 10, 3 ); add_filter( 'pre_option_' . Api_Credentials::OPTION_CLIENT_ID, $env_filter, 10, 3 ); add_filter( 'pre_option_' . Api_Credentials::OPTION_CLIENT_SECRET, $env_filter, 10, 3 ); @@ -243,7 +478,6 @@ private function api_credentials( Container $container ) { add_filter( 'pre_update_option_' . Api_Credentials::OPTION_CLIENT_ID, $pre_update_options_action, 10, 3 ); add_filter( 'pre_update_option_' . Api_Credentials::OPTION_CLIENT_SECRET, $pre_update_options_action, 10, 3 ); add_filter( 'pre_update_option_' . Api_Credentials::OPTION_ACCESS_TOKEN, $pre_update_options_action, 10, 3 ); - add_action( 'update_option_' . Api_Credentials::OPTION_STORE_URL, $update_options_action, 10, 2 ); add_action( 'update_option_' . Api_Credentials::OPTION_CLIENT_ID, $update_options_action, 10, 2 ); add_action( 'update_option_' . Api_Credentials::OPTION_CLIENT_SECRET, $update_options_action, 10, 2 ); @@ -288,6 +522,7 @@ private function cart( Container $container ) { $container[ self::CART_SECTION ] = function ( Container $container ) { return new Cart_Settings( $container[ Pages::CART_PAGE ], $container[ Pages::CHECKOUT_PAGE ], $container[ Pages::CHECKOUT_COMPLETE_PAGE ] ); }; + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'cart_settings_register', function () use ( $container ) { $container[ self::CART_SECTION ]->register_settings_section(); } ), 30, 0 ); @@ -302,6 +537,7 @@ private function gift_certificates( Container $container ) { return new Gift_Ceritifcate_Settings( $pages ); }; + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'gift_certificate_settings_register', function () use ( $container ) { $container[ self::GIFT_CERTIFICATE_SECTION ]->register_settings_section(); } ), 35, 0 ); @@ -323,6 +559,7 @@ private function import( Container $container ) { add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'import_register', function () use ( $container ) { $container[ self::IMPORT_SECTION ]->register_settings_section(); } ), 20, 0 ); + add_action( 'bigcommerce/settings/register/screen=' . Connect_Channel_Screen::NAME, $this->create_callback( 'import_register_for_channels', function () use ( $container ) { $container[ self::IMPORT_SECTION ]->register_connect_channel_fields(); } ), 20, 0 ); @@ -362,9 +599,9 @@ private function import( Container $container ) { $container[ self::IMPORT_STATUS ]->render_status(); } } ); + add_action( 'bigcommerce/settings/section/after_fields/id=' . Import_Settings::NAME, $render_import_status, 20, 0 ); add_action( 'bigcommerce/settings/before_title/page=' . Onboarding_Complete_Screen::NAME, $render_import_status, 0, 0 ); - add_action( 'bigcommerce/settings/import/product_list_table_notice', $this->create_callback( 'import_current_status_notice', function () use ( $container ) { if ( $container[ self::CONFIG_STATUS ] >= self::STATUS_COMPLETE ) { $container[ self::IMPORT_STATUS ]->current_status_notice(); @@ -381,6 +618,8 @@ private function import( Container $container ) { add_action( 'wp_ajax_' . Import_Status::AJAX_ACTION_IMPORT_STATUS, $this->create_callback( 'validate_current_status_ajax', function () use ( $container ) { $container[ self::IMPORT_STATUS ]->validate_ajax_current_status_request(); } ), 0, 0 ); + + add_action( 'wp_ajax_' . Import_Status::AJAX_ACTION_IMPORT_STATUS, $this->create_callback( 'import_current_status_message', function () use ( $container ) { $container[ self::IMPORT_STATUS ]->ajax_current_status(); } ), 10, 0 ); @@ -394,6 +633,7 @@ private function currency( Container $container ) { $container[ self::CURRENCY_SECTION ] = function ( Container $container ) { return new \BigCommerce\Settings\Sections\Currency(); }; + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'currency_settings_register', function () use ( $container ) { $container[ self::CURRENCY_SECTION ]->register_settings_section(); } ), 50, 0 ); @@ -405,6 +645,7 @@ private function next_steps( Container $container ) { return new Next_Steps( $container[ Merchant::SETUP_STATUS ], $path ); }; + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'next_steps_settings_register', function () use ( $container ) { $container[ self::NEXT_STEPS_SECTION ]->register_settings_section(); } ), 10, 0 ); @@ -442,72 +683,74 @@ private function analytics( Container $container ) { $container[ self::ANALYTICS_SECTION ] = function ( Container $container ) { return new Analytics_Settings( $container[ Api::FACTORY ]->store(), $container[ Api::FACTORY ]->storefront_settings() ); }; - + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'analytics_settings_register', function () use ( $container ) { $container[ self::ANALYTICS_SECTION ]->register_settings_section(); } ), 60, 0 ); - + add_action( 'update_option_' . Analytics_Settings::FACEBOOK_PIXEL, $this->create_callback( 'update_pixel_id', function ( $old_value, $new_value ) use ( $container ) { $container[ self::ANALYTICS_SECTION ]->update_pixel_option( $old_value, $new_value ); } ), 10, 2 ); - + add_action( 'update_option_' . Analytics_Settings::GOOGLE_ANALYTICS, $this->create_callback( 'update_google_option', function ( $old_value, $new_value ) use ( $container ) { $container[ self::ANALYTICS_SECTION ]->update_google_option( $old_value, $new_value ); } ), 10, 2 ); } + private function reviews( Container $container ) { $container[ self::REVIEWS_SECTION ] = function ( Container $container ) { return new Review_Settings(); }; - + add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'review_settings_register', function () use ( $container ) { $container[ self::REVIEWS_SECTION ]->register_settings_section(); } ), 60, 0 ); } + private function onboarding( Container $container ) { $container[ self::WELCOME_SCREEN ] = function ( Container $container ) { $path = dirname( $container['plugin_file'] ) . '/templates/admin'; - + return new Welcome_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ], $path ); }; + add_action( 'admin_menu', $this->create_callback( 'welcome_screen_admin_menu', function () use ( $container ) { $container[ self::WELCOME_SCREEN ]->register_settings_page(); } ), 10, 0 ); + $welcome_screen_url = $this->create_callback( 'welcome_screen_url', function ( $url ) use ( $container ) { return $container[ self::WELCOME_SCREEN ]->get_url(); } ); + add_filter( 'bigcommerce/onboarding/error_redirect', $welcome_screen_url, 10, 1 ); add_filter( 'bigcommerce/onboarding/reset', $welcome_screen_url, 10, 1 ); - + $container[ self::CREATE_SCREEN ] = function ( Container $container ) { return new Create_Account_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); }; + add_action( 'admin_menu', $this->create_callback( 'create_screen_admin_menu', function () use ( $container ) { $container[ self::CREATE_SCREEN ]->register_settings_page(); } ), 10, 0 ); + add_filter( 'bigcommerce/settings/create_account_url', $this->create_callback( 'create_account_url', function ( $url ) use ( $container ) { return $container[ self::CREATE_SCREEN ]->get_url(); } ), 10, 1 ); + add_action( 'admin_post_' . Create_Account_Screen::NAME, $this->create_callback( 'handle_create_account', function () use ( $container ) { $container[ self::CREATE_SCREEN ]->handle_submission(); } ), 10, 1 ); - $container[ self::NEW_ACCOUNT_SECTION ] = function ( Container $container ) { - return new New_Account_Section(); - }; add_action( 'bigcommerce/settings/register/screen=' . Create_Account_Screen::NAME, $this->create_callback( 'new_account_action_register', function () use ( $container ) { $container[ self::NEW_ACCOUNT_SECTION ]->register_settings_section(); } ), 50, 0 ); + add_action( 'bigcommerce/create_account/validate_request', $this->create_callback( 'new_account_validate', function ( $submission, $errors ) use ( $container ) { $container[ self::NEW_ACCOUNT_SECTION ]->validate_request( $submission, $errors ); } ), 10, 2 ); - // Choose full store or Blog screen - $container[ self::STORE_TYPE_SCREEN ] = function ( Container $container ) { - return new Store_Type_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); - }; add_action( 'admin_menu', $this->create_callback( 'create_choose_blog_full_store_admin_menu', function () use ( $container ) { $container[ self::STORE_TYPE_SCREEN ]->register_settings_page(); } ), 10, 0 ); @@ -520,65 +763,68 @@ private function onboarding( Container $container ) { $container[ self::STORE_TYPE_SCREEN ]->handle_submission_for_full_store(); } ), 10, 1 ); - // Select a channel screen - $container[ self::CHANNEL_SCREEN ] = function ( Container $container ) { - return new Connect_Channel_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); - }; add_action( 'admin_menu', $this->create_callback( 'create_channel_screen_admin_menu', function () use ( $container ) { $container[ self::CHANNEL_SCREEN ]->register_settings_page(); } ), 10, 0 ); - $container [ self::SELECT_CHANNEL_SECTION ] = function ( Container $container ) { - return new Channel_Select(); - }; - $container [ self::IMPORT_SETTINGS_SECTION ] = function ( Container $container ) { - return new Onboarding_Import_Settings(); - }; add_action( 'bigcommerce/settings/register/screen=' . Connect_Channel_Screen::NAME, $this->create_callback( 'select_channel_section_register', function () use ( $container ) { $container[ self::SELECT_CHANNEL_SECTION ]->register_settings_section(); $container[ self::IMPORT_SETTINGS_SECTION ]->register_settings_section(); } ), 10, 0 ); - $container [ self::CHANNEL_SECTION ] = function ( Container $container ) { - return new Channel_Settings(); - }; add_action( 'bigcommerce/settings/register/screen=' . Settings_Screen::NAME, $this->create_callback( 'channel_section_register', function () use ( $container ) { $container[ self::CHANNEL_SECTION ]->register_settings_section(); } ), 80, 0 ); + add_action( 'admin_post_' . Channel_Settings::POST_ACTION, $this->create_callback( 'handle_channel_operation', function () use ( $container ) { if ( Channel::multichannel_enabled() ) { $container[ self::CHANNEL_SECTION ]->handle_action_submission( $container[ self::SETTINGS_SCREEN ]->get_url() . '#' . Channel_Settings::NAME ); } } ), 10, 0 ); + add_action( 'bigcommerce/channel/promote', $this->create_callback( 'promote_channel', function ( \WP_Term $term ) use ( $container ) { $container[ self::CHANNEL_SECTION ]->promote_channel( $term ); } ), 10, 1 ); - $container[ self::PENDING_SCREEN ] = function ( Container $container ) { - return new Pending_Account_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); - }; add_action( 'admin_menu', $this->create_callback( 'pending_screen_admin_menu', function () use ( $container ) { $container[ self::PENDING_SCREEN ]->register_settings_page(); } ), 10, 0 ); + $pending_screen_url = $this->create_callback( 'pending_screen_url', function ( $url ) use ( $container ) { return $container[ self::PENDING_SCREEN ]->get_url(); } ); + add_filter( 'bigcommerce/onboarding/success_redirect', $pending_screen_url, 10, 1 ); $container[ self::CREDENTIALS_SCREEN ] = function ( Container $container ) { return new Api_Credentials_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); }; + add_action( 'admin_menu', $this->create_callback( 'credentials_screen_admin_menu', function () use ( $container ) { $container[ self::CREDENTIALS_SCREEN ]->register_settings_page(); } ), 10, 0 ); + + /** + * Provides the URL for the API credentials page. + * + * @param string $url The existing URL. + * @return string The URL for the API credentials page. + */ $api_credentials_url = $this->create_callback( 'api_credentials_url', function ( $url ) use ( $container ) { return $container[ self::CREDENTIALS_SCREEN ]->get_url(); } ); add_filter( 'bigcommerce/settings/credentials_url', $api_credentials_url ); + add_action( 'admin_action_update', $this->create_callback( 'validate_api_credentials', function () use ( $container ) { $container[ self::CREDENTIALS_SCREEN ]->validate_credentials(); } ), 10, 0 ); + /** + * Registers the Nav Menu setup screen in the admin menu. + * + * @param Container $container The container instance holding the service dependencies. + * @return void + */ $container[ self::MENU_SETUP_SCREEN ] = function ( Container $container ) { return new Nav_Menu_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ] ); }; @@ -586,6 +832,12 @@ private function onboarding( Container $container ) { $container[ self::MENU_SETUP_SCREEN ]->register_settings_page(); } ), 10, 0 ); + /** + * Registers the Complete Onboarding screen in the admin menu. + * + * @param Container $container The container instance holding the service dependencies. + * @return void + */ $container[ self::COMPLETE_SCREEN ] = function ( Container $container ) { $path = dirname( $container['plugin_file'] ) . '/templates/admin'; @@ -595,6 +847,11 @@ private function onboarding( Container $container ) { $container[ self::COMPLETE_SCREEN ]->register_settings_page(); } ), 10, 0 ); + /** + * Registers the Nav Menu options section for settings. + * + * @return void + */ $container[ self::MENU_OPTIONS_SECTION ] = function ( Container $container ) { return new Nav_Menu_Options(); }; @@ -624,7 +881,7 @@ private function onboarding( Container $container ) { } } ), 10, 1 ); - + $container[ self::START_OVER ] = function ( Container $container ) { return new Start_Over(); }; @@ -632,6 +889,7 @@ private function onboarding( Container $container ) { $start_over_link = $this->create_callback( 'start_over_link', function () use ( $container ) { $container[ self::START_OVER ]->add_link_to_settings_screen(); } ); + add_action( 'bigcommerce/settings/after_form/page=' . Api_Credentials_Screen::NAME, $start_over_link ); add_action( 'bigcommerce/settings/after_form/page=' . Create_Account_Screen::NAME, $start_over_link ); add_action( 'bigcommerce/settings/after_form/page=' . Connect_Channel_Screen::NAME, $start_over_link ); @@ -657,11 +915,13 @@ private function onboarding_progress_bar( Container $container ) { $container[ self::ONBOARDING_PROGRESS ]->render(); } } ); + add_action( 'bigcommerce/settings/onboarding/progress', $progress_bar, 10, 0 ); $subheader = $this->create_callback( 'onboarding_subheader', function () use ( $container ) { $container[ self::ONBOARDING_PROGRESS ]->step_subheader(); } ); + add_action( 'bigcommerce/settings/before_title/page=' . Welcome_Screen::NAME, $subheader, 10, 0 ); add_action( 'bigcommerce/settings/before_title/page=' . Create_Account_Screen::NAME, $subheader, 10, 0 ); add_action( 'bigcommerce/settings/before_title/page=' . Api_Credentials_Screen::NAME, $subheader, 10, 0 ); @@ -672,7 +932,7 @@ private function onboarding_progress_bar( Container $container ) { } /** - * Handles menus visibility for the settings screen and nav menu page + * Handles menus visibility for the settings screen and nav menu page * * @param Container $container */ @@ -741,9 +1001,11 @@ private function resources( Container $container ) { return new Resources_Screen( $container[ self::CONFIG_STATUS ], $container[ Assets::PATH ], $path ); }; + add_action( 'admin_menu', $this->create_callback( 'resources_screen_register', function () use ( $container ) { $container[ self::RESOURCES_SCREEN ]->register_settings_page(); } ), 10, 0 ); + add_filter( 'bigcommerce/settings/resources_url', $this->create_callback( 'resources_url', function ( $url ) use ( $container ) { return $container[ self::RESOURCES_SCREEN ]->get_url(); } ), 10, 1 ); diff --git a/src/BigCommerce/Container/Shortcodes.php b/src/BigCommerce/Container/Shortcodes.php index f1c52fe1..e5d8398b 100644 --- a/src/BigCommerce/Container/Shortcodes.php +++ b/src/BigCommerce/Container/Shortcodes.php @@ -1,82 +1,190 @@ cart() ); - }; - $container[ self::CHECKOUT ] = function ( Container $container ) { - return new Codes\Checkout( $container[ Api::FACTORY ]->cart() ); - }; - $container[ self::LOGIN ] = function ( Container $container ) { - return new Codes\Login_Form(); - }; - $container[ self::REGISTER ] = function ( Container $container ) { - return new Codes\Registration_Form(); - }; - $container[ self::ACCOUNT ] = function ( Container $container ) { - return new Codes\Account_Profile(); - }; - $container[ self::ADDRESS ] = function ( Container $container ) { - return new Codes\Address_List(); - }; - $container[ self::ORDERS ] = function ( Container $container ) { - return new Codes\Order_History( $container[ Rest::ORDERS_SHORTCODE ] ); - }; - $container[ self::GIFT_FORM ] = function ( Container $container ) { - return new Codes\Gift_Certificate_Form( $container[ Api::FACTORY ]->marketing() ); - }; - $container[ self::GIFT_BALANCE ] = function ( Container $container ) { - return new Codes\Gift_Certificate_Balance( $container[ Api::FACTORY ]->marketing() ); - }; - $container[ self::PRODUCT_REVIEWS ] = function ( Container $container ) { - return new Codes\Product_Reviews(); - }; - $container[ self::PRODUCT_COMPONENTS ] = function () { - return new Codes\Product_Components(); - }; - $container[ self::WISHLIST ] = function ( Container $container ) { - return new Codes\Wishlist( $container[ Api::FACTORY ]->wishlists() ); - }; - - add_action( 'after_setup_theme', $this->create_callback( 'register', function () use ( $container ) { - add_shortcode( Codes\Products::NAME, [ $container[ self::PRODUCTS ], 'render' ] ); - add_shortcode( Codes\Cart::NAME, [ $container[ self::CART ], 'render' ] ); - add_shortcode( Codes\Checkout::NAME, [ $container[ self::CHECKOUT ], 'render' ] ); - add_shortcode( Codes\Login_Form::NAME, [ $container[ self::LOGIN ], 'render' ] ); - add_shortcode( Codes\Registration_Form::NAME, [ $container[ self::REGISTER ], 'render' ] ); - add_shortcode( Codes\Account_Profile::NAME, [ $container[ self::ACCOUNT ], 'render' ] ); - add_shortcode( Codes\Address_List::NAME, [ $container[ self::ADDRESS ], 'render' ] ); - add_shortcode( Codes\Order_History::NAME, [ $container[ self::ORDERS ], 'render' ] ); - add_shortcode( Codes\Gift_Certificate_Form::NAME, [ $container[ self::GIFT_FORM ], 'render' ] ); - add_shortcode( Codes\Gift_Certificate_Balance::NAME, [ $container[ self::GIFT_BALANCE ], 'render' ] ); - add_shortcode( Codes\Product_Reviews::NAME, [ $container[ self::PRODUCT_REVIEWS ], 'render' ] ); - add_shortcode( Codes\Product_Components::NAME, [ $container[ self::PRODUCT_COMPONENTS ], 'render' ] ); - add_shortcode( Codes\Wishlist::NAME, [ $container[ self::WISHLIST ], 'render' ] ); - } ), 10, 0 ); - } + /** + * Shortcode for rendering a product list. + * + * @var string + */ + const PRODUCTS = 'shortcode.products'; + + /** + * Shortcode for rendering the cart. + * + * @var string + */ + const CART = 'shortcode.cart'; + + /** + * Shortcode for rendering the checkout page. + * + * @var string + */ + const CHECKOUT = 'shortcode.checkout'; + + /** + * Shortcode for rendering the login form. + * + * @var string + */ + const LOGIN = 'shortcode.login'; + + /** + * Shortcode for rendering the registration form. + * + * @var string + */ + const REGISTER = 'shortcode.register'; + + /** + * Shortcode for rendering the account profile. + * + * @var string + */ + const ACCOUNT = 'shortcode.account'; + + /** + * Shortcode for rendering the address list. + * + * @var string + */ + const ADDRESS = 'shortcode.address'; + + /** + * Shortcode for rendering the order history. + * + * @var string + */ + const ORDERS = 'shortcode.orders'; + + /** + * Shortcode for rendering the gift certificate form. + * + * @var string + */ + const GIFT_FORM = 'shortcode.gift_certificate.form'; + + /** + * Shortcode for checking the balance of a gift certificate. + * + * @var string + */ + const GIFT_BALANCE = 'shortcode.gift_certificate.balance'; + + /** + * Shortcode for rendering product reviews. + * + * @var string + */ + const PRODUCT_REVIEWS = 'shortcode.products_reviews'; + + /** + * Shortcode for rendering product components. + * + * @var string + */ + const PRODUCT_COMPONENTS = 'shortcode.products_components'; + + /** + * Shortcode for rendering a wishlist. + * + * @var string + */ + const WISHLIST = 'shortcode.wishlist'; + + /** + * Registers all shortcodes into the DI container and attaches WordPress hooks. + * + * Services registered: + * - Shortcode classes like `Products`, `Cart`, `Checkout`, etc. + * + * Hook registered: + * - `after_setup_theme`: Registers WordPress shortcodes. + * + * @param Container $container The DI container for registering services. + */ + public function register(Container $container) { + // Register each shortcode class as a service. + $container[self::PRODUCTS] = function (Container $container) { + return new Codes\Products($container[Rest::SHORTCODE]); + }; + + $container[self::CART] = function (Container $container) { + return new Codes\Cart($container[Api::FACTORY]->cart()); + }; + + $container[self::CHECKOUT] = function (Container $container) { + return new Codes\Checkout($container[Api::FACTORY]->cart()); + }; + + $container[self::LOGIN] = function (Container $container) { + return new Codes\Login_Form(); + }; + + $container[self::REGISTER] = function (Container $container) { + return new Codes\Registration_Form(); + }; + + $container[self::ACCOUNT] = function (Container $container) { + return new Codes\Account_Profile(); + }; + + $container[self::ADDRESS] = function (Container $container) { + return new Codes\Address_List(); + }; + + $container[self::ORDERS] = function (Container $container) { + return new Codes\Order_History($container[Rest::ORDERS_SHORTCODE]); + }; + + $container[self::GIFT_FORM] = function (Container $container) { + return new Codes\Gift_Certificate_Form($container[Api::FACTORY]->marketing()); + }; + + $container[self::GIFT_BALANCE] = function (Container $container) { + return new Codes\Gift_Certificate_Balance($container[Api::FACTORY]->marketing()); + }; + + $container[self::PRODUCT_REVIEWS] = function (Container $container) { + return new Codes\Product_Reviews(); + }; + + $container[self::PRODUCT_COMPONENTS] = function () { + return new Codes\Product_Components(); + }; + + $container[self::WISHLIST] = function (Container $container) { + return new Codes\Wishlist($container[Api::FACTORY]->wishlists()); + }; + + add_action('after_setup_theme', $this->create_callback('register', function () use ($container) { + add_shortcode(Codes\Products::NAME, [$container[self::PRODUCTS], 'render']); + add_shortcode(Codes\Cart::NAME, [$container[self::CART], 'render']); + add_shortcode(Codes\Checkout::NAME, [$container[self::CHECKOUT], 'render']); + add_shortcode(Codes\Login_Form::NAME, [$container[self::LOGIN], 'render']); + add_shortcode(Codes\Registration_Form::NAME, [$container[self::REGISTER], 'render']); + add_shortcode(Codes\Account_Profile::NAME, [$container[self::ACCOUNT], 'render']); + add_shortcode(Codes\Address_List::NAME, [$container[self::ADDRESS], 'render']); + add_shortcode(Codes\Order_History::NAME, [$container[self::ORDERS], 'render']); + add_shortcode(Codes\Gift_Certificate_Form::NAME, [$container[self::GIFT_FORM], 'render']); + add_shortcode(Codes\Gift_Certificate_Balance::NAME, [$container[self::GIFT_BALANCE], 'render']); + add_shortcode(Codes\Product_Reviews::NAME, [$container[self::PRODUCT_REVIEWS], 'render']); + add_shortcode(Codes\Product_Components::NAME, [$container[self::PRODUCT_COMPONENTS], 'render']); + add_shortcode(Codes\Wishlist::NAME, [$container[self::WISHLIST], 'render']); + }), 10, 0); + } } \ No newline at end of file diff --git a/src/BigCommerce/Container/Taxonomies.php b/src/BigCommerce/Container/Taxonomies.php index d7b6c000..c5b71044 100644 --- a/src/BigCommerce/Container/Taxonomies.php +++ b/src/BigCommerce/Container/Taxonomies.php @@ -27,89 +27,208 @@ use BigCommerce\Taxonomies\Product_Type; use Pimple\Container; +/** + * This class is responsible for managing and registering taxonomies for BigCommerce integration. It defines constants for various taxonomies and handles their configuration and filtering via WordPress hooks. + * + * @package BigCommerce\Container + */ class Taxonomies extends Provider { - const PRODUCT_CATEGORY = 'taxonomy.product_category'; - const PRODUCT_CATEGORY_CONFIG = 'taxonomy.product_category.config'; - const PRODUCT_CATEGORY_GROUP_FILTERED_TERMS = 'taxonomy.product_category.group_filtered_terms'; - const PRODUCT_CATEGORY_QUERY_FILTER = 'taxonomy.product_category.query_filter'; - - const BRAND = 'taxonomy.brand'; - const BRAND_CONFIG = 'taxonomy.brand.config'; - - const AVAILABILITY = 'taxonomy.availability'; - const AVAILABILITY_CONFIG = 'taxonomy.availability.config'; - - const CONDITION = 'taxonomy.condition'; - const CONDITION_CONFIG = 'taxonomy.condition.config'; - - const PRODUCT_TYPE = 'taxonomy.product_type'; - const PRODUCT_TYPE_CONFIG = 'taxonomy.product_type.config'; - - const FLAG = 'taxonomy.flag'; - const FLAG_CONFIG = 'taxonomy.flag.config'; - - const CHANNEL = 'taxonomy.channel'; - const CHANNEL_CONFIG = 'taxonomy.channel.config'; - const CHANNEL_SYNC = 'taxonomy.channel.sync'; - const CHANNEL_CONNECTOR = 'taxonomy.channel.connector'; - const CHANNEL_ADMIN_FILTER = 'taxonomy.channel.admin_products_filter'; - const CHANNEL_QUERY_FILTER = 'taxonomy.channel.query_filter'; - const CHANNEL_CURRENCY_FILTER = 'taxonomy.channel.currency_filter'; - const CHANNEL_BC_STATUS = 'taxonomy.channel.bc_status'; - - const ROUTES = 'taxonomy.channel.routes'; - - public function register( Container $container ) { - $this->product_category( $container ); - $this->brand( $container ); - $this->availability( $container ); - $this->condition( $container ); - $this->product_type( $container ); - $this->flag( $container ); - $this->channel( $container ); - - add_action( 'init', $this->create_callback( 'register', function () use ( $container ) { - $container[ self::PRODUCT_CATEGORY_CONFIG ]->register(); - $container[ self::BRAND_CONFIG ]->register(); - $container[ self::AVAILABILITY_CONFIG ]->register(); - $container[ self::CONDITION_CONFIG ]->register(); - $container[ self::PRODUCT_TYPE_CONFIG ]->register(); - $container[ self::FLAG_CONFIG ]->register(); - $container[ self::CHANNEL_CONFIG ]->register(); - } ), 0, 0 ); - } - - private function product_category( Container $container ) { - $container[ self::PRODUCT_CATEGORY_CONFIG ] = function ( Container $container ) { - return new Product_Category\Config( Product_Category\Product_Category::NAME, [ Product::NAME ] ); - }; - - $container[ self::PRODUCT_CATEGORY_GROUP_FILTERED_TERMS ] = function ( Container $container ) { - return new Product_Category\Group_Filtered_Terms(); - }; - - $container[ self::PRODUCT_CATEGORY_QUERY_FILTER ] = function () use ( $container ) { - return new Product_Category\Query_Filter( $container[ self::PRODUCT_CATEGORY_GROUP_FILTERED_TERMS ] ); - }; - add_filter( 'get_terms_args', $this->create_callback( 'exclude_product_categories_by_group', function ( $args, $taxonomies ) use ( $container ) { - if ( ! is_admin() ) { - $args = $container[ self::PRODUCT_CATEGORY_GROUP_FILTERED_TERMS ]->exclude_hidden_terms( $args, $taxonomies ); - } - - return $args; - } ), 10, 3 ); - - add_action( 'pre_get_posts', $this->create_callback( 'filter_query_by_product_category', function ( $query ) use ( $container ) { - if ( ! is_admin() ) { - $container[ self::PRODUCT_CATEGORY_QUERY_FILTER ]->apply( $query ); - } - } ), 10, 1 ); - - add_action( 'parse_tax_query', $this->create_callback( 'hide_children_by_default', function ( $query ) use ( $container ) { - $container[ self::PRODUCT_CATEGORY_QUERY_FILTER ]->maybe_hide_children( $query ); - } ), 10, 1 ); - } + /** + * Constant for Product Category taxonomy. + * @var string + */ + const PRODUCT_CATEGORY = 'taxonomy.product_category'; + + /** + * Constant for Product Category configuration. + * @var string + */ + const PRODUCT_CATEGORY_CONFIG = 'taxonomy.product_category.config'; + + /** + * Constant for Product Category group filtered terms. + * @var string + */ + const PRODUCT_CATEGORY_GROUP_FILTERED_TERMS = 'taxonomy.product_category.group_filtered_terms'; + + /** + * Constant for Product Category query filter. + * @var string + */ + const PRODUCT_CATEGORY_QUERY_FILTER = 'taxonomy.product_category.query_filter'; + + /** + * Constant for Brand taxonomy. + * @var string + */ + const BRAND = 'taxonomy.brand'; + + /** + * Constant for Brand configuration. + * @var string + */ + const BRAND_CONFIG = 'taxonomy.brand.config'; + + /** + * Constant for Availability taxonomy. + * @var string + */ + const AVAILABILITY = 'taxonomy.availability'; + + /** + * Constant for Availability configuration. + * @var string + */ + const AVAILABILITY_CONFIG = 'taxonomy.availability.config'; + + /** + * Constant for Condition taxonomy. + * @var string + */ + const CONDITION = 'taxonomy.condition'; + + /** + * Constant for Condition configuration. + * @var string + */ + const CONDITION_CONFIG = 'taxonomy.condition.config'; + + /** + * Constant for Product Type taxonomy. + * @var string + */ + const PRODUCT_TYPE = 'taxonomy.product_type'; + + /** + * Constant for Product Type configuration. + * @var string + */ + const PRODUCT_TYPE_CONFIG = 'taxonomy.product_type.config'; + + /** + * Constant for Flag taxonomy. + * @var string + */ + const FLAG = 'taxonomy.flag'; + + /** + * Constant for Flag configuration. + * @var string + */ + const FLAG_CONFIG = 'taxonomy.flag.config'; + + /** + * Constant for Channel taxonomy. + * @var string + */ + const CHANNEL = 'taxonomy.channel'; + + /** + * Constant for Channel configuration. + * @var string + */ + const CHANNEL_CONFIG = 'taxonomy.channel.config'; + + /** + * Constant for Channel synchronization. + * @var string + */ + const CHANNEL_SYNC = 'taxonomy.channel.sync'; + + /** + * Constant for Channel connector. + * @var string + */ + const CHANNEL_CONNECTOR = 'taxonomy.channel.connector'; + + /** + * Constant for Channel admin filter. + * @var string + */ + const CHANNEL_ADMIN_FILTER = 'taxonomy.channel.admin_products_filter'; + + /** + * Constant for Channel query filter. + * @var string + */ + const CHANNEL_QUERY_FILTER = 'taxonomy.channel.query_filter'; + + /** + * Constant for Channel currency filter. + * @var string + */ + const CHANNEL_CURRENCY_FILTER = 'taxonomy.channel.currency_filter'; + + /** + * Constant for Channel BigCommerce status. + * @var string + */ + const CHANNEL_BC_STATUS = 'taxonomy.channel.bc_status'; + + /** + * Constant for Routes related to Channel. + * @var string + */ + const ROUTES = 'taxonomy.channel.routes'; + + + /** + * Registers all taxonomies and related actions and filters. + * + * @param Container $container The container object. + */ + public function register( Container $container ) { + $this->product_category( $container ); + $this->brand( $container ); + $this->availability( $container ); + $this->condition( $container ); + $this->product_type( $container ); + $this->flag( $container ); + $this->channel( $container ); + + add_action( 'init', $this->create_callback( 'register', function () use ( $container ) { + $container[ self::PRODUCT_CATEGORY_CONFIG ]->register(); + $container[ self::BRAND_CONFIG ]->register(); + $container[ self::AVAILABILITY_CONFIG ]->register(); + $container[ self::CONDITION_CONFIG ]->register(); + $container[ self::PRODUCT_TYPE_CONFIG ]->register(); + $container[ self::FLAG_CONFIG ]->register(); + $container[ self::CHANNEL_CONFIG ]->register(); + } ), 0, 0 ); + } + + private function product_category( Container $container ) { + $container[ self::PRODUCT_CATEGORY_CONFIG ] = function ( Container $container ) { + return new Product_Category\Config( Product_Category\Product_Category::NAME, [ Product::NAME ] ); + }; + + $container[ self::PRODUCT_CATEGORY_GROUP_FILTERED_TERMS ] = function ( Container $container ) { + return new Product_Category\Group_Filtered_Terms(); + }; + + $container[ self::PRODUCT_CATEGORY_QUERY_FILTER ] = function () use ( $container ) { + return new Product_Category\Query_Filter( $container[ self::PRODUCT_CATEGORY_GROUP_FILTERED_TERMS ] ); + }; + + add_filter( 'get_terms_args', $this->create_callback( 'exclude_product_categories_by_group', function ( $args, $taxonomies ) use ( $container ) { + if ( ! is_admin() ) { + $args = $container[ self::PRODUCT_CATEGORY_GROUP_FILTERED_TERMS ]->exclude_hidden_terms( $args, $taxonomies ); + } + + return $args; + } ), 10, 3 ); + + add_action( 'pre_get_posts', $this->create_callback( 'filter_query_by_product_category', function ( $query ) use ( $container ) { + if ( ! is_admin() ) { + $container[ self::PRODUCT_CATEGORY_QUERY_FILTER ]->apply( $query ); + } + } ), 10, 1 ); + + add_action( 'parse_tax_query', $this->create_callback( 'hide_children_by_default', function ( $query ) use ( $container ) { + $container[ self::PRODUCT_CATEGORY_QUERY_FILTER ]->maybe_hide_children( $query ); + } ), 10, 1 ); + } private function brand( Container $container ) { $container[ self::BRAND_CONFIG ] = function ( Container $container ) { @@ -166,9 +285,10 @@ private function channel( Container $container ) { $channel_sync = $this->create_callback( 'channel_sync', function () use ( $container ) { $container[ self::CHANNEL_SYNC ]->sync(); } ); + + add_action( 'bigcommerce/settings/before_form/page=' . Connect_Channel_Screen::NAME, $channel_sync, 10, 0 ); add_action( 'bigcommerce/import/start', $channel_sync, 10, 0 ); - add_action( 'bigcommerce/settings/before_form/page=' . Settings_Screen::NAME, function () use ( $container ) { $container[ self::CHANNEL_SYNC ]->initial_sync(); }, 10, 0 ); @@ -208,11 +328,13 @@ private function channel( Container $container ) { $container[ self::CHANNEL_ADMIN_FILTER ] = function ( Container $container ) { return new Channel\Admin_Products_Filter(); }; + add_action( 'load-edit.php', $this->create_callback( 'init_list_table_hooks', function () use ( $container ) { if ( Channel\Channel::multichannel_enabled() ) { add_filter( 'restrict_manage_posts', $this->create_callback( 'products_admin_channel_select', function ( $post_type, $which ) use ( $container ) { $container[ self::CHANNEL_ADMIN_FILTER ]->display_channel_select( $post_type, $which ); } ), 10, 2 ); + add_filter( 'parse_request', $this->create_callback( 'parse_products_admin_request', function ( \WP $wp ) use ( $container ) { $container[ self::CHANNEL_ADMIN_FILTER ]->filter_list_table_request( $wp ); } ), 10, 1 ); @@ -222,6 +344,7 @@ private function channel( Container $container ) { $container[ self::CHANNEL_QUERY_FILTER ] = function ( Container $container ) { return new Channel\Query_Filter(); }; + add_action( 'pre_get_posts', $this->create_callback( 'filter_query_by_channel', function ( $query ) use ( $container ) { if ( ! is_admin() && Channel\Channel::multichannel_enabled() ) { $container[ self::CHANNEL_QUERY_FILTER ]->apply( $query ); @@ -231,6 +354,7 @@ private function channel( Container $container ) { $container[ self::CHANNEL_CURRENCY_FILTER ] = function ( Container $container ) { return new Channel\Currency_Filter(); }; + add_action( 'pre_option_' . \BigCommerce\Settings\Sections\Currency::CURRENCY_CODE, $this->create_callback( 'filter_channel_currency', function ( $currency_code ) use ( $container ) { return $container[ self::CHANNEL_CURRENCY_FILTER ]->filter_currency( $currency_code ); } ), 5, 1 ); @@ -240,6 +364,7 @@ private function routes( Container $container ) { $container[ self::ROUTES ] = function ( Container $container ) { return new Channel\Routes( $container[ Api::FACTORY ]->sites(), $container[ Api::FACTORY ]->channels() ); }; + add_action( 'bigcommerce/channel/updated_channel_id', $this->create_callback( 'set_routes_for_channel', function ( $channel_id ) use ( $container ) { $container[ self::ROUTES ]->set_routes( $channel_id ); } ), 10, 1 ); @@ -271,18 +396,14 @@ private function routes( Container $container ) { add_action( 'update_option_' . Product_Archive::BRAND_SLUG, $route_changed, 10, 0 ); add_action( 'add_option_' . Product_Archive::BRAND_SLUG, $route_changed, 10, 0 ); add_action( 'bigcommerce/channel/connection_changed', $route_changed ); - - //for when site is updated add_action( 'update_option_home', $this->create_callback( 'update_site_home', function () use ( $container ) { $container[ self::ROUTES ]->update_site_home(); } ), 10, 0 ); - //for when route assigned pages changed permalink add_action( 'post_updated', $this->create_callback( 'update_route_permalink', function ( $post_id, $new_post, $old_post ) use ( $container ) { $container[ self::ROUTES ]->update_route_permalink( $post_id, $new_post, $old_post ); } ), 10, 3 ); - // check that we're updated when an import runs add_action( 'bigcommerce/import/fetched_store_settings', $this->create_callback( 'check_and_update_routes_version', function () use ( $container ) { $container[ self::ROUTES ]->maybe_update_routes(); } ), 10, 0 ); diff --git a/src/BigCommerce/Container/Templates.php b/src/BigCommerce/Container/Templates.php index 236ac650..a9857a84 100644 --- a/src/BigCommerce/Container/Templates.php +++ b/src/BigCommerce/Container/Templates.php @@ -8,11 +8,40 @@ use BigCommerce\Templates\Template_Override; use Pimple\Container; +/** + * Handles template overrides and body class modifications + * within the BigCommerce integration. It registers various filters to modify the template paths and + * the body class dynamically based on the context, such as product pages, archives, taxonomies, and search results. + */ class Templates extends Provider { - const OVERRIDE = 'template.override'; - const BODY_CLASS = 'template.body_class'; - - public function register( Container $container ) { + /** + * The container key for the template override service. + * + * This constant is used to define the key for the `Template_Override` service within the container. + * It is utilized when accessing the template override functionality, such as rendering product templates. + * @var string + */ + const OVERRIDE = 'template.override'; + + /** + * The container key for the body class service. + * + * This constant is used to define the key for the `Body_Classes` service within the container. + * It is used to modify the body class on the front end by adding relevant classes. + * @var string + */ + const BODY_CLASS = 'template.body_class'; + + /** + * Register the template-related services and filters. + * + * This method registers all the necessary services and filters related to templates, including + * template overrides, body classes, and template hierarchy modifications. It is called when the + * container is initialized and hooks into various WordPress actions and filters for template management. + * + * @param Container $container The container instance used to register services. + */ + public function register( Container $container ) { $container[ self::OVERRIDE ] = function ( Container $container ) { return new Template_Override(); }; @@ -21,24 +50,14 @@ public function register( Container $container ) { return new Body_Classes(); }; - - /** - * Look for plugin templates in [plugin]/templates/public - */ add_filter( 'bigcommerce/template/directory/plugin', $this->create_callback( 'plugin_directory', function ( $directory ) use ( $container ) { return $directory ?: plugin_dir_path( $container['plugin_file'] ) . 'templates/public'; } ), 20, 1 ); - /** - * Look for template overrides in [theme]/bigcommerce - */ add_filter( 'bigcommerce/template/directory/theme', $this->create_callback( 'theme_directory', function ( $directory ) { return $directory ?: 'bigcommerce'; } ), 20, 1 ); - /** - * Render the product single - */ add_filter( 'bigcommerce/template/product/single', $this->create_callback( 'product_single', function ( $output, $post_id ) use ( $container ) { if ( ! empty( $output ) ) { return $output; @@ -47,9 +66,6 @@ public function register( Container $container ) { return $container[ self::OVERRIDE ]->render_product_single( $post_id ); } ), 10, 2 ); - /** - * Render the product archive - */ add_filter( 'bigcommerce/template/product/archive', $this->create_callback( 'product_archive', function ( $output ) use ( $container ) { if ( ! empty( $output ) ) { return $output; @@ -61,6 +77,7 @@ public function register( Container $container ) { $single_template_hierarchy = $this->create_callback( 'single_template_hierarchy', function ( $templates ) use ( $container ) { return $container[ self::OVERRIDE ]->set_product_single_template_path( $templates ); } ); + add_filter( 'single_template_hierarchy', $single_template_hierarchy, 10, 1 ); add_filter( 'singular_template_hierarchy', $single_template_hierarchy, 10, 1 ); add_filter( 'index_template_hierarchy', $single_template_hierarchy, 10, 1 ); @@ -68,12 +85,14 @@ public function register( Container $container ) { $archive_template_hierarchy = $this->create_callback( 'archive_template_hierarchy', function ( $templates ) use ( $container ) { return $container[ self::OVERRIDE ]->set_product_archive_template_path( $templates ); } ); + add_filter( 'archive_template_hierarchy', $archive_template_hierarchy, 10, 1 ); add_filter( 'index_template_hierarchy', $archive_template_hierarchy, 10, 1 ); $tax_template_hierarchy = $this->create_callback( 'taxonomy_template_hierarchy', function ( $templates ) use ( $container ) { return $container[ self::OVERRIDE ]->set_taxonomy_archive_template_path( $templates ); } ); + add_filter( 'taxonomy_template_hierarchy', $tax_template_hierarchy, 10, 1 ); add_filter( 'archive_template_hierarchy', $tax_template_hierarchy, 10, 1 ); add_filter( 'index_template_hierarchy', $tax_template_hierarchy, 10, 1 ); @@ -81,10 +100,10 @@ public function register( Container $container ) { $search_template_hierarchy = $this->create_callback( 'search_template_hierarchy', function ( $templates ) use ( $container ) { return $container[ self::OVERRIDE ]->set_search_template_path( $templates ); } ); + add_filter( 'search_template_hierarchy', $search_template_hierarchy, 10, 1 ); add_filter( 'index_template_hierarchy', $search_template_hierarchy, 10, 1 ); - add_filter( 'template_include', $this->create_callback( 'template_include', function ( $path ) use ( $container ) { return $container[ self::OVERRIDE ]->include_product_template( $path ); } ), 10, 1 ); diff --git a/src/BigCommerce/Container/Theme_Customizer.php b/src/BigCommerce/Container/Theme_Customizer.php index 1e9f3fce..1e65abc4 100644 --- a/src/BigCommerce/Container/Theme_Customizer.php +++ b/src/BigCommerce/Container/Theme_Customizer.php @@ -1,90 +1,189 @@ create_callback( 'customize_register', function ( $wp_customize ) use ( $container ) { - $container[ self::PANEL_PRIMARY ]->register( $wp_customize ); - $container[ self::SECTION_BUTTONS ]->register( $wp_customize ); - $container[ self::SECTION_COLORS ]->register( $wp_customize ); - $container[ self::SECTION_PRODUCT_SINGLE ]->register( $wp_customize ); - $container[ self::SECTION_PRODUCT_ARCHIVE ]->register( $wp_customize ); - $container[ self::SECTION_PRODUCT_CATEGORIES ]->register( $wp_customize ); - $container[ self::SECTION_BANNERS ]->register( $wp_customize ); - - if ( get_option( \BigCommerce\Settings\Sections\Cart::OPTION_ENABLE_CART, true ) ) { - $container[ self::SECTION_CART ]->register( $wp_customize ); - } - - if ( get_option( \BigCommerce\Settings\Sections\Cart::OPTION_EMBEDDED_CHECKOUT, true ) ) { - $container[ self::SECTION_CHECKOUT ]->register( $wp_customize ); - } - } ), 10, 1 ); - - add_action( 'wp_head', $this->create_callback( 'customizer_styles', function () use ( $container ) { - $container[ self::STYLES ]->print_styles(); - } ), 10, 0 ); - } + /** + * Identifier for the cart customizer section. + * + * @var string + */ + const SECTION_CART = 'customizer.section.cart'; + + /** + * Identifier for the checkout customizer section. + * + * @var string + */ + const SECTION_CHECKOUT = 'customizer.section.checkout'; + + /** + * Identifier for the banners customizer section. + * + * @var string + */ + const SECTION_BANNERS = 'customizer.section.banners'; + + /** + * Identifier for the customizer styles. + * + * @var string + */ + const STYLES = 'customizer.styles'; + + /** + * Registers customizer panels, sections, and styles in the Pimple container. + * + * @param Container $container Dependency injection container. + * + * @return void + */ + public function register(Container $container) { + /** + * @return Panels\Primary The primary customizer panel instance. + */ + $container[self::PANEL_PRIMARY] = function (Container $container) { + return new Panels\Primary(); + }; + + /** + * @return Sections\Buttons The buttons customizer section instance. + */ + $container[self::SECTION_BUTTONS] = function (Container $container) { + return new Sections\Buttons(); + }; + + /** + * @return Sections\Colors The colors customizer section instance. + */ + $container[self::SECTION_COLORS] = function (Container $container) { + return new Sections\Colors(); + }; + + /** + * @return Sections\Product_Single The product single customizer section instance. + */ + $container[self::SECTION_PRODUCT_SINGLE] = function (Container $container) { + return new Sections\Product_Single(); + }; + + /** + * @return Sections\Product_Archive The product archive customizer section instance. + */ + $container[self::SECTION_PRODUCT_ARCHIVE] = function (Container $container) { + return new Sections\Product_Archive(); + }; + + /** + * @return Sections\Product_Category The product categories customizer section instance. + */ + $container[self::SECTION_PRODUCT_CATEGORIES] = function (Container $container) { + return new Sections\Product_Category(); + }; + + /** + * @return Sections\Cart The cart customizer section instance. + */ + $container[self::SECTION_CART] = function (Container $container) { + return new Sections\Cart(); + }; + + /** + * @return Sections\Checkout The checkout customizer section instance. + */ + $container[self::SECTION_CHECKOUT] = function (Container $container) { + return new Sections\Checkout(); + }; + + /** + * @return Sections\Banners The banners customizer section instance. + */ + $container[self::SECTION_BANNERS] = function (Container $container) { + return new Sections\Banners(); + }; + + /** + * @return Styles The styles instance for printing customizer styles. + */ + $container[self::STYLES] = function (Container $container) { + $path = dirname($container['plugin_file']) . '/assets/customizer.template.css'; + return new Styles($path); + }; + + add_action('customize_register', $this->create_callback('customize_register', function ($wp_customize) use ($container) { + $container[self::PANEL_PRIMARY]->register($wp_customize); + $container[self::SECTION_BUTTONS]->register($wp_customize); + $container[self::SECTION_COLORS]->register($wp_customize); + $container[self::SECTION_PRODUCT_SINGLE]->register($wp_customize); + $container[self::SECTION_PRODUCT_ARCHIVE]->register($wp_customize); + $container[self::SECTION_PRODUCT_CATEGORIES]->register($wp_customize); + $container[self::SECTION_BANNERS]->register($wp_customize); + + if (get_option(\BigCommerce\Settings\Sections\Cart::OPTION_ENABLE_CART, true)) { + $container[self::SECTION_CART]->register($wp_customize); + } + + if (get_option(\BigCommerce\Settings\Sections\Cart::OPTION_EMBEDDED_CHECKOUT, true)) { + $container[self::SECTION_CHECKOUT]->register($wp_customize); + } + }), 10, 1); + + add_action('wp_head', $this->create_callback('customizer_styles', function () use ($container) { + $container[self::STYLES]->print_styles(); + }), 10, 0); + } } diff --git a/src/BigCommerce/Container/Util.php b/src/BigCommerce/Container/Util.php index 942cd742..73f81d45 100644 --- a/src/BigCommerce/Container/Util.php +++ b/src/BigCommerce/Container/Util.php @@ -1,23 +1,45 @@ create_callback( 'kses_allowed_html', function ( $allowed_tags, $context ) use ( $container ) { - return $container[ self::KSES ]->product_description_allowed_html( $allowed_tags, $context ); - } ), 10, 2 ); - } - + /** + * Identifier for the KSES utility service. + * + * @var string + */ + const KSES = 'util.kses'; + + /** + * Registers utility services in the container. + * + * @param Container $container The service container to register services into. + */ + public function register( Container $container ) { + $container[ self::KSES ] = function ( Container $container ) { + return new Kses(); + }; + + add_action( + 'wp_kses_allowed_html', + $this->create_callback( + 'kses_allowed_html', + function ( $allowed_tags, $context ) use ( $container ) { + return $container[ self::KSES ]->product_description_allowed_html( $allowed_tags, $context ); + } + ), + 10, + 2 + ); + } } diff --git a/src/BigCommerce/Container/Webhooks.php b/src/BigCommerce/Container/Webhooks.php index efdebbe2..7067cef1 100644 --- a/src/BigCommerce/Container/Webhooks.php +++ b/src/BigCommerce/Container/Webhooks.php @@ -36,35 +36,176 @@ use Pimple\Container; /** - * Provider for webhooks + * Provider for handling BigCommerce webhooks. + * + * This class sets up webhook-related constants, services, and handlers + * to process webhook requests, manage their lifecycle, and integrate + * with BigCommerce APIs. + * + * @package BigCommerce\Container */ class Webhooks extends Provider { + + /** + * Base identifier for webhooks. + * @var string + */ const WEBHOOKS = 'webhooks.webhooks'; + + /** + * Status of webhook enablement or disablement. + * @var string + */ const WEBHOOKS_STATUS = 'webhooks.webhooks_status'; + + /** + * Listener for handling incoming webhook payloads. + * @var string + */ const WEBHOOKS_LISTENER = 'webhooks.listener_webhook'; + + /** + * General handler for channel webhooks. + * @var string + */ const CHANNELS_HANDLE_WEBHOOK = 'webhooks.channels_handle_webhook'; + + /** + * Updates product information. + * @var string + */ const PRODUCT_UPDATE_WEBHOOK = 'webhooks.product_update_webhook'; + + /** + * Deletes product data. + * @var string + */ const PRODUCT_DELETE_WEBHOOK = 'webhooks.product_delete_webhook'; + + /** + * Creates new product entries. + * @var string + */ const PRODUCT_CREATE_WEBHOOK = 'webhooks.product_create_webhook'; + + /** + * Updates product inventory. + * @var string + */ const PRODUCT_INVENTORY_UPDATE_WEBHOOK = 'webhooks.inventory_update_webhook'; + + /** + * Creates new customer entries. + * @var string + */ const CUSTOMER_CREATE_WEBHOOK = 'webhooks.customer_create_webhook'; + + /** + * Updates customer details. + * @var string + */ const CUSTOMER_UPDATE_WEBHOOK = 'webhooks.customer_update_webhook'; + + /** + * Deletes customer records. + * @var string + */ const CUSTOMER_DELETE_WEBHOOK = 'webhooks.customer_delete_webhook'; + + /** + * Cron-based product updater. + * @var string + */ const PRODUCT_UPDATER = 'webhooks.cron.product_updater'; + + /** + * Cron-based product creator. + * @var string + */ const PRODUCT_CREATOR = 'webhooks.cron.product_creator'; + + /** + * Assigns a product to a channel. + * @var string + */ const CHANNEL_PRODUCT_ASSIGNED = 'webhooks.product.channels_assign'; + + /** + * Unassigns a product from a channel. + * @var string + */ const CHANNEL_PRODUCT_UNASSIGNED = 'webhooks.product.channels_unassign'; + + /** + * Updates channel details. + * @var string + */ const CHANNEL_UPDATER = 'webhooks.product.channels_updater'; + + /** + * Updates currency configuration for channels. + * @var string + */ const CHANNEL_CURRENCY_UPDATED = 'webhooks.channels.currency_updated'; + + /** + * Cron-based customer creator. + * @var string + */ const CUSTOMER_CREATOR = 'webhooks.cron.customer_creator'; + + /** + * Cron-based customer updater. + * @var string + */ const CUSTOMER_UPDATER = 'webhooks.cron.customer_updater'; + + /** + * Cron-based customer deleter. + * @var string + */ const CUSTOMER_DELETER = 'webhooks.cron.customer_deleter'; + + /** + * Updates customer channel access. + * @var string + */ const CUSTOMER_CHANNEL_ACCESS_UPDATER = 'webhooks.cron.customer_channel_access_updater'; + + /** + * Handles customer access per channel. + * @var string + */ const CUSTOMER_CHANNEL_ACCESS = 'webhooks.cron.customer_channel_access'; + + /** + * Triggered when a checkout process is completed. + * @var string + */ const CHECKOUT_COMPLETE_WEBHOOK = 'webhooks.checkout_complete'; + + /** + * Versioning logic for webhooks. + * @var string + */ const WEBHOOKS_VERSIONING = 'webhooks.version'; + + /** + * Cron tasks associated with webhooks. + * @var string + */ const WEBHOOKS_CRON_TASKS = 'webhooks.cron_tasks'; + /** + * Registers services related to webhooks in the container. + * + * Sets up webhook declarations, their statuses, and actions + * for processing and managing webhook events. + * + * @param Container $container The Pimple container instance. + * + * @return void + */ public function register( Container $container ) { $this->declare_webhooks( $container ); $this->status( $container ); @@ -269,7 +410,6 @@ private function handle_requests( Container $container ) { return; } - // Listener for all webhook actions add_action( 'bigcommerce/action_endpoint/webhook', $this->create_callback( 'webhook_listener', function ( $args ) use ( $container ) { $container[ self::WEBHOOKS_LISTENER ]->handle_request( $args ); } ), 10, 1 ); @@ -280,7 +420,6 @@ private function customer_webhook_actions( Container $container ) { return; } - // Delete customer webhook add_action('bigcommerce/webhooks/customer_deleted', $this->create_callback('delete_customer_webhook_handler', function ( $params ) use ( $container ) { if ( ! $this->customer_webhooks_enabled() ) { return; @@ -289,7 +428,6 @@ private function customer_webhook_actions( Container $container ) { $container[ self::CUSTOMER_DELETER ]->handle_request( $params ); } ), 10, 1 ); - // Create customer webhook add_action('bigcommerce/webhooks/customer_created', $this->create_callback('create_customer_webhook_handler', function ( $customer_id ) use ( $container ) { if ( ! $this->customer_webhooks_enabled() ) { return; @@ -298,7 +436,6 @@ private function customer_webhook_actions( Container $container ) { $container[ self::CUSTOMER_CREATOR ]->handle_request( $customer_id ); } ), 10, 1 ); - // Update customer webhook add_action('bigcommerce/webhooks/customer_updated', $this->create_callback('update_customer_webhook_handler', function ( $customer_id ) use ( $container ) { if ( ! $this->customer_webhooks_enabled() ) { return; @@ -328,7 +465,6 @@ private function webhook_actions( Container $container ) { return; } - // Update product inventory webhook cron task add_action( 'bigcommerce/webhooks/product_inventory_updated', $this->create_callback( 'check_and_update_product_inventory_task', function ( $params ) use ( $container ) { if ( ! $this->product_webhooks_enabled() ) { return; @@ -338,7 +474,6 @@ private function webhook_actions( Container $container ) { $container[ self::PRODUCT_UPDATER ]->update( $params['product_id'] ); } ), 10, 1 ); - // Update product inventory webhook cron task add_action( 'bigcommerce/webhooks/product_updated', $this->create_callback( 'check_and_update_product_data_task', function ( $params ) use ( $container ) { if ( ! $this->product_webhooks_enabled() ) { return; @@ -348,7 +483,6 @@ private function webhook_actions( Container $container ) { $container[ self::WEBHOOKS_CRON_TASKS ]->set_product_update_cron_task( $params ); } ), 10, 1 ); - // Delete product webhook add_action('bigcommerce/webhooks/product_deleted', $this->create_callback('delete_single_product_handler', function ( $params ) use ( $container ) { if ( ! $this->product_webhooks_enabled() ) { return; @@ -357,7 +491,6 @@ private function webhook_actions( Container $container ) { $container[ self::PRODUCT_DELETE_WEBHOOK ]->delete_the_product( $params ); } ), 10, 1 ); - // Create product webhook add_action('bigcommerce/webhooks/product_created', $this->create_callback('create_single_product_handler', function ( $params ) use ( $container ) { if ( ! $this->product_webhooks_enabled() ) { return; @@ -366,7 +499,6 @@ private function webhook_actions( Container $container ) { $container[self::PRODUCT_CREATOR]->create($params); } ), 10, 1 ); - add_action ( sprintf('%s_assigned',Channels_Management_Webhook::PRODUCT_CHANNEL_HOOK ), $this->create_callback( 'product_channel_was_assigned', function ( $product_id, $channel_id ) use ( $container ) { if ( ! $this->product_webhooks_enabled() ) { return; diff --git a/src/BigCommerce/Container/Widgets.php b/src/BigCommerce/Container/Widgets.php index ea9d8104..1a8b36bf 100644 --- a/src/BigCommerce/Container/Widgets.php +++ b/src/BigCommerce/Container/Widgets.php @@ -1,31 +1,47 @@ create_callback( 'widgets_init', function () use ( $container ) { - foreach ( $container[ self::WIDGET_LIST ] as $class ) { - register_widget( $class ); - } - } ), 10, 0 ); - } - + /** + * The key used to store the widget list in the container. + * + * @var string + */ + const WIDGET_LIST = 'widgets.list'; + + /** + * Registers the widgets and initializes the widget registration action. + * + * Registers a list of widgets and hooks them into WordPress using `widgets_init`. + * + * @param Container $container The service container to register services into. + */ + public function register( Container $container ) { + // Register the list of widgets. + $container[ self::WIDGET_LIST ] = function ( Container $container ) { + return [ + Product_Category_Widget::class, + Mini_Cart_Widget::class, + Currency_Switcher_Widget::class, + ]; + }; + + add_action( 'widgets_init', $this->create_callback( 'widgets_init', function () use ( $container ) { + foreach ( $container[ self::WIDGET_LIST ] as $class ) { + register_widget( $class ); + } + } ), 10, 0 ); + } } diff --git a/src/BigCommerce/Currency/Configurable_Formatter.php b/src/BigCommerce/Currency/Configurable_Formatter.php index e7632abc..c4813ce1 100644 --- a/src/BigCommerce/Currency/Configurable_Formatter.php +++ b/src/BigCommerce/Currency/Configurable_Formatter.php @@ -6,31 +6,67 @@ use BigCommerce\Settings\Sections\Currency as Position; +/** + * Class for configuring and formatting currency values. + * + * Allows for customizable currency symbol, position, and decimal precision when formatting monetary values. + */ class Configurable_Formatter implements Currency_Formatter { - private $symbol; - private $position; - private $decimals; - - public function __construct( $symbol = '¤', $symbol_position = Position::POSITION_LEFT, $decimals = 2 ) { - $this->symbol = $symbol; - $this->position = $symbol_position; - $this->decimals = (int) $decimals; - } - - public function format( $value ) { - $formatted = number_format_i18n( $value, $this->decimals ); - switch ( $this->position ) { - case Position::POSITION_LEFT_SPACE: - return $this->symbol . ' ' . $formatted; - case Position::POSITION_RIGHT: - return $formatted . $this->symbol; - case Position::POSITION_RIGHT_SPACE: - return $formatted . ' ' . $this->symbol; - case Position::POSITION_LEFT: - default: - return $this->symbol . $formatted; - } - } + /** + * The currency symbol. + * + * @var string + */ + private $symbol; + /** + * The position of the currency symbol relative to the value. + * + * @var string + */ + private $position; + /** + * The number of decimal places for formatting. + * + * @var int + */ + private $decimals; + + /** + * Constructor for Configurable_Formatter. + * + * @param string $symbol The currency symbol to use (default is '¤'). + * @param string $symbol_position The position of the currency symbol, using constants from `Position` (default is left). + * @param int $decimals The number of decimal places for formatted values (default is 2). + */ + public function __construct( $symbol = '¤', $symbol_position = Position::POSITION_LEFT, $decimals = 2 ) { + $this->symbol = $symbol; + $this->position = $symbol_position; + $this->decimals = (int) $decimals; + } + + /** + * Formats a currency value based on the configured settings. + * + * @param float $value The numeric value to format. + * + * @return string The formatted currency value with the symbol in the configured position. + */ + public function format( $value ) { + $formatted = number_format_i18n( $value, $this->decimals ); + switch ( $this->position ) { + case Position::POSITION_LEFT_SPACE: + return $this->symbol . ' ' . $formatted; + case Position::POSITION_RIGHT: + return $formatted . $this->symbol; + case Position::POSITION_RIGHT_SPACE: + return $formatted . ' ' . $this->symbol; + case Position::POSITION_LEFT: + default: + return $this->symbol . $formatted; + } + } + + } \ No newline at end of file diff --git a/src/BigCommerce/Currency/Currency.php b/src/BigCommerce/Currency/Currency.php index 88ff37a5..1675cf08 100644 --- a/src/BigCommerce/Currency/Currency.php +++ b/src/BigCommerce/Currency/Currency.php @@ -7,115 +7,133 @@ use BigCommerce\Settings\Sections\Currency as Currency_Settings; use BigCommerce\Taxonomies\Channel\Connections; +/** + * Handles currency operations, including fetching and setting currency codes and managing channel-aware currencies. + */ class Currency { - const CURRENCY_CODE_COOKIE = 'wp-bigcommerce-currency-code'; - - /** - * Get the currency code - * - * @return string - */ - public function get_currency_code() { - $default_currency_code = get_option( Currency_Settings::CURRENCY_CODE, 'USD' ); - $channels = new Connections(); - $current = $channels->current(); - $channel_default_code = get_term_meta( $current->term_id, Currency_Settings::CHANNEL_CURRENCY_CODE, true ); - if ( ! get_option( Currency_Settings::ENABLE_CURRENCY_SWITCHER, false ) && empty( $channel_default_code ) ) { - return $default_currency_code; - } elseif ( ! get_option( Currency_Settings::ENABLE_CURRENCY_SWITCHER, false ) && ! empty( $channel_default_code ) ) { - return $channel_default_code; - } - - $currency_code = ''; - if ( is_user_logged_in() ) { - $user_currency_code = get_user_meta( get_current_user_id(), Currency_Settings::CURRENCY_CODE, true ); - if ( $user_currency_code ) { - $currency_code = $user_currency_code; - } - } - - if ( empty( $currency_code ) ) { - $cookie = filter_input( INPUT_COOKIE, self::CURRENCY_CODE_COOKIE, FILTER_SANITIZE_STRING ); - if ( $cookie ) { - $currency_code = $cookie; - } - } - - $enabled = $this->enabled_currencies(); - if ( isset( $enabled[ $currency_code ] ) ) { - return $currency_code; - } - - return $channel_default_code; - } - - /** - * @param string $currency_code - * @return bool - */ - public function set_currency_code( $currency_code ) { - $enabled = $this->enabled_currencies(); - if ( ! isset( $enabled[ $currency_code ] ) ) { - return false; - } - - $user_id = get_current_user_id(); - - if ( $user_id ) { - update_user_meta( $user_id, Currency_Settings::CURRENCY_CODE, $currency_code ); - } - - $this->set_currency_code_cookie( $currency_code ); - - return true; - } - - /** - * Set the cookie that contains the currency code - * - * @param string $currency_code - * - * @return void - */ - public function set_currency_code_cookie( $currency_code ) { - /** - * Filter how long the currency code cookie should persist - * - * @param int $lifetime The cookie lifespan in seconds - */ - $cookie_life = apply_filters( 'bigcommerce/currency/cookie_lifetime', 30 * DAY_IN_SECONDS ); - $secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ); - setcookie( self::CURRENCY_CODE_COOKIE, $currency_code, time() + $cookie_life, COOKIEPATH, COOKIE_DOMAIN, $secure ); - $_COOKIE[ self::CURRENCY_CODE_COOKIE ] = $currency_code; - } - - private function enabled_currencies() { - return get_option( Currency_Settings::ENABLED_CURRENCIES, [] ); - } - - public function get_channel_aware_currencies(): array { - $store_currencies = $this->enabled_currencies(); - if ( ! Store_Settings::is_msf_on() ) { - return $store_currencies; - } - - $channels = new Connections(); - $current = $channels->current(); - $channel_currencies_allowed = get_term_meta( $current->term_id, Currency_Settings::CHANNEL_ALLOWED_CURRENCY, true ); - - if ( empty( $channel_currencies_allowed ) ) { - return $store_currencies; - } - - $currencies = array_filter( $store_currencies, function( $currency ) use ( $channel_currencies_allowed ) { - return in_array( $currency['currency_code'], $channel_currencies_allowed ); - } ); - - if ( empty( $currencies ) ) { - return $store_currencies; - } - - return $currencies; - } + /** + * The name of the cookie used to store the currency code. + */ + const CURRENCY_CODE_COOKIE = 'wp-bigcommerce-currency-code'; + + /** + * Retrieves the current currency code. + * + * Determines the currency code based on user preferences, cookies, or channel-specific defaults. + * + * @return string The current currency code. + */ + public function get_currency_code() { + $default_currency_code = get_option( Currency_Settings::CURRENCY_CODE, 'USD' ); + $channels = new Connections(); + $current = $channels->current(); + $channel_default_code = get_term_meta( $current->term_id, Currency_Settings::CHANNEL_CURRENCY_CODE, true ); + if ( ! get_option( Currency_Settings::ENABLE_CURRENCY_SWITCHER, false ) && empty( $channel_default_code ) ) { + return $default_currency_code; + } elseif ( ! get_option( Currency_Settings::ENABLE_CURRENCY_SWITCHER, false ) && ! empty( $channel_default_code ) ) { + return $channel_default_code; + } + + $currency_code = ''; + if ( is_user_logged_in() ) { + $user_currency_code = get_user_meta( get_current_user_id(), Currency_Settings::CURRENCY_CODE, true ); + if ( $user_currency_code ) { + $currency_code = $user_currency_code; + } + } + + if ( empty( $currency_code ) ) { + $cookie = filter_input( INPUT_COOKIE, self::CURRENCY_CODE_COOKIE, FILTER_SANITIZE_STRING ); + if ( $cookie ) { + $currency_code = $cookie; + } + } + + $enabled = $this->enabled_currencies(); + if ( isset( $enabled[ $currency_code ] ) ) { + return $currency_code; + } + + return $channel_default_code; + } + + /** + * Sets the currency code for the current user and stores it in a cookie. + * + * @param string $currency_code The currency code to set. + * + * @return bool True if the currency code was successfully set; otherwise, false. + */ + public function set_currency_code( $currency_code ) { + $enabled = $this->enabled_currencies(); + if ( ! isset( $enabled[ $currency_code ] ) ) { + return false; + } + + $user_id = get_current_user_id(); + + if ( $user_id ) { + update_user_meta( $user_id, Currency_Settings::CURRENCY_CODE, $currency_code ); + } + + $this->set_currency_code_cookie( $currency_code ); + + return true; + } + + /** + * Sets a cookie to store the currency code. + * + * @param string $currency_code The currency code to store in the cookie. + * + * @return void + */ + public function set_currency_code_cookie( $currency_code ) { + /** + * Filters the lifetime of the currency code cookie. + * + * @param int $lifetime The cookie lifespan in seconds. + */ + $cookie_life = apply_filters( 'bigcommerce/currency/cookie_lifetime', 30 * DAY_IN_SECONDS ); + $secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ); + setcookie( self::CURRENCY_CODE_COOKIE, $currency_code, time() + $cookie_life, COOKIEPATH, COOKIE_DOMAIN, $secure ); + $_COOKIE[ self::CURRENCY_CODE_COOKIE ] = $currency_code; + } + + private function enabled_currencies() { + return get_option( Currency_Settings::ENABLED_CURRENCIES, [] ); + } + + /** + * Retrieves channel-aware currencies for the current store or channel. + * + * Filters the enabled currencies based on the current channel's allowed currencies. + * + * @return array The list of channel-aware currencies. + */ + public function get_channel_aware_currencies(): array { + $store_currencies = $this->enabled_currencies(); + if ( ! Store_Settings::is_msf_on() ) { + return $store_currencies; + } + + $channels = new Connections(); + $current = $channels->current(); + $channel_currencies_allowed = get_term_meta( $current->term_id, Currency_Settings::CHANNEL_ALLOWED_CURRENCY, true ); + + if ( empty( $channel_currencies_allowed ) ) { + return $store_currencies; + } + + $currencies = array_filter( $store_currencies, function( $currency ) use ( $channel_currencies_allowed ) { + return in_array( $currency['currency_code'], $channel_currencies_allowed ); + } ); + + if ( empty( $currencies ) ) { + return $store_currencies; + } + + return $currencies; + } } diff --git a/src/BigCommerce/Currency/Currency_Formatter.php b/src/BigCommerce/Currency/Currency_Formatter.php index c507c769..a056f701 100644 --- a/src/BigCommerce/Currency/Currency_Formatter.php +++ b/src/BigCommerce/Currency/Currency_Formatter.php @@ -3,14 +3,18 @@ namespace BigCommerce\Currency; - +/** + * Interface for formatting numeric values into currency strings. + * + * Provides a contract for implementing currency formatting functionality with a standardized method. + */ interface Currency_Formatter { - /** - * Format a number into a currency string - * - * @param string|int|float $value - * - * @return string The formatted currency value - */ - public function format( $value ); + /** + * Formats a numeric value into a currency string. + * + * @param string|int|float $value The numeric value to be formatted. + * + * @return string The formatted currency value. + */ + public function format( $value ); } \ No newline at end of file diff --git a/src/BigCommerce/Currency/Formatter_Factory.php b/src/BigCommerce/Currency/Formatter_Factory.php index 8c329abc..efadb261 100644 --- a/src/BigCommerce/Currency/Formatter_Factory.php +++ b/src/BigCommerce/Currency/Formatter_Factory.php @@ -5,62 +5,76 @@ use BigCommerce\Settings; +/** + * Factory class to create and manage currency formatters. + */ class Formatter_Factory { - private $formatters = []; - - public function get( $currency_code ) { - - if ( array_key_exists( $currency_code, $this->formatters ) ) { - return $this->formatters[ $currency_code ]; - } - - if ( $this->auto_format() ) { - $this->formatters[ $currency_code ] = $this->make_auto_formatter( $currency_code ); - - return $this->formatters[ $currency_code ]; - } - - $enabled = $this->enabled_currencies(); - if ( isset( $enabled[ $currency_code ] ) ) { - $this->formatters[ $currency_code ] = $this->make_configurable_formatter_from_currency( $enabled[ $currency_code ] ); - } else { - $this->formatters[ $currency_code ] = $this->make_configurable_formatter_from_options(); - } - - return $this->formatters[ $currency_code ]; - } - - private function auto_format() { - /** - * Filter whether to apply auto-formatting to currency using PHP's - * \NumberFormatter class from the intl extension. - * - * @param bool $auto_format Whether to auto-format - */ - return apply_filters( 'bigcommerce/settings/currency/auto-format', class_exists( '\NumberFormatter' ) ); - } - - private function enabled_currencies() { - return get_option( Settings\Sections\Currency::ENABLED_CURRENCIES, [] ); - } - - private function make_auto_formatter( $currency_code ) { - return new Intl_Formatter( $currency_code ); - } - - private function make_configurable_formatter_from_currency( $currency ) { - $symbol = $currency['token']; - $position = $currency['token_location']; - $decimals = $currency['decimal_places']; - - return new Configurable_Formatter( $symbol, $position, $decimals ); - } - - private function make_configurable_formatter_from_options() { - $symbol = get_option( Settings\Sections\Currency::CURRENCY_SYMBOL, '$' ); - $position = get_option( Settings\Sections\Currency::CURRENCY_SYMBOL_POSITION, Settings\Sections\Currency::POSITION_LEFT ); - $decimals = get_option( Settings\Sections\Currency::DECIMAL_UNITS, 2 ); - - return new Configurable_Formatter( $symbol, $position, $decimals ); - } + /** + * Cache of created currency formatters. + * + * @var array + */ + private $formatters = []; + + /** + * Retrieves a currency formatter for the given currency code. + * + * Creates a new formatter if one does not already exist for the currency code. + * + * @param string $currency_code The currency code for which to retrieve the formatter. + * + * @return Intl_Formatter|Configurable_Formatter The currency formatter. + */ + public function get( $currency_code ) { + if ( array_key_exists( $currency_code, $this->formatters ) ) { + return $this->formatters[ $currency_code ]; + } + + if ( $this->auto_format() ) { + $this->formatters[ $currency_code ] = $this->make_auto_formatter( $currency_code ); + return $this->formatters[ $currency_code ]; + } + + $enabled = $this->enabled_currencies(); + if ( isset( $enabled[ $currency_code ] ) ) { + $this->formatters[ $currency_code ] = $this->make_configurable_formatter_from_currency( $enabled[ $currency_code ] ); + } else { + $this->formatters[ $currency_code ] = $this->make_configurable_formatter_from_options(); + } + + return $this->formatters[ $currency_code ]; + } + + private function auto_format() { + /** + * Filter whether to apply auto-formatting to currencies. + * + * @param bool $auto_format Whether to enable auto-formatting. + */ + return apply_filters( 'bigcommerce/settings/currency/auto-format', class_exists( '\NumberFormatter' ) ); + } + + private function enabled_currencies() { + return get_option( Settings\Sections\Currency::ENABLED_CURRENCIES, [] ); + } + + private function make_auto_formatter( $currency_code ) { + return new Intl_Formatter( $currency_code ); + } + + private function make_configurable_formatter_from_currency( $currency ) { + $symbol = $currency['token']; + $position = $currency['token_location']; + $decimals = $currency['decimal_places']; + + return new Configurable_Formatter( $symbol, $position, $decimals ); + } + + private function make_configurable_formatter_from_options() { + $symbol = get_option( Settings\Sections\Currency::CURRENCY_SYMBOL, '$' ); + $position = get_option( Settings\Sections\Currency::CURRENCY_SYMBOL_POSITION, Settings\Sections\Currency::POSITION_LEFT ); + $decimals = get_option( Settings\Sections\Currency::DECIMAL_UNITS, 2 ); + + return new Configurable_Formatter( $symbol, $position, $decimals ); + } } diff --git a/src/BigCommerce/Currency/Intl_Formatter.php b/src/BigCommerce/Currency/Intl_Formatter.php index 53962f8a..01d1a9fa 100644 --- a/src/BigCommerce/Currency/Intl_Formatter.php +++ b/src/BigCommerce/Currency/Intl_Formatter.php @@ -3,23 +3,48 @@ namespace BigCommerce\Currency; - +/** + * Formatter class for currency values using PHP's intl extension. + */ class Intl_Formatter implements Currency_Formatter { - private $formatter; - private $currency; - - public function __construct( $currency ) { - $this->formatter = new \NumberFormatter( $this->get_locale(), \NumberFormatter::CURRENCY ); - $this->currency = $currency; - } - - private function get_locale() { - return \get_locale(); - } - - public function format( $value ) { - return $this->formatter->formatCurrency( $value, $this->currency ); - } - - + /** + * The NumberFormatter instance for formatting currency values. + * + * @var \NumberFormatter + */ + private $formatter; + + /** + * The currency code used for formatting. + * + * @var string + */ + private $currency; + + /** + * Initializes the Intl_Formatter with a specific currency code. + * + * @param string $currency The currency code (e.g., USD, EUR). + */ + public function __construct( $currency ) { + $this->formatter = new \NumberFormatter( $this->get_locale(), \NumberFormatter::CURRENCY ); + $this->currency = $currency; + } + + private function get_locale() { + return \get_locale(); + } + + /** + * Formats a numeric value as a currency string. + * + * @param float|int|string $value The value to format. + * + * @return string The formatted currency value. + */ + public function format( $value ) { + return $this->formatter->formatCurrency( $value, $this->currency ); + } + + } \ No newline at end of file diff --git a/src/BigCommerce/Currency/USD_Formatter.php b/src/BigCommerce/Currency/USD_Formatter.php index 92132cdc..4feec40c 100644 --- a/src/BigCommerce/Currency/USD_Formatter.php +++ b/src/BigCommerce/Currency/USD_Formatter.php @@ -3,9 +3,18 @@ namespace BigCommerce\Currency; - +/** + * Formatter class for currency values specifically in USD. + */ class USD_Formatter implements Currency_Formatter { - public function format( $value ) { - return sprintf( '$%s', number_format_i18n( $value, 2 ) ); - } + /** + * Formats a numeric value as a USD currency string. + * + * @param float|int|string $value The value to format. + * + * @return string The formatted currency value in USD. + */ + public function format( $value ) { + return sprintf( '$%s', number_format_i18n( $value, 2 ) ); + } } \ No newline at end of file diff --git a/src/BigCommerce/Currency/With_Currency.php b/src/BigCommerce/Currency/With_Currency.php index bb9d4cce..fb44a3fd 100644 --- a/src/BigCommerce/Currency/With_Currency.php +++ b/src/BigCommerce/Currency/With_Currency.php @@ -3,26 +3,30 @@ namespace BigCommerce\Currency; - +/** + * Provides currency formatting functionality for classes. + */ trait With_Currency { - /** - * @param float $value The currency value to format - * @param string $empty_value What to return if the value is empty. Pass `null` to format anyway. - * - * @return string - */ - protected function format_currency( $value, $empty_value = '' ) { - if ( ! (float) $value && isset( $empty_value ) ) { - return $empty_value; - } + /** + * Formats a numeric value as a currency string. + * + * @param float $value The currency value to format. + * @param string $empty_value The value to return if $value is empty. Pass `null` to format anyway. + * + * @return string The formatted currency string or the empty value. + */ + protected function format_currency( $value, $empty_value = '' ) { + if ( ! (float) $value && isset( $empty_value ) ) { + return $empty_value; + } - /** - * Format a price for the current currency and locale - * - * @param string $formatted The formatted currency string - * @param float $value The price to format - */ - return apply_filters( 'bigcommerce/currency/format', sprintf( '¤%0.2f', $value ), $value ); - } + /** + * Filters the formatted currency string for the current currency and locale. + * + * @param string $formatted The formatted currency string. + * @param float $value The currency value being formatted. + */ + return apply_filters( 'bigcommerce/currency/format', sprintf( '¤%0.2f', $value ), $value ); + } } \ No newline at end of file diff --git a/src/BigCommerce/Customizer/Controls/Multiple_Checkboxes.php b/src/BigCommerce/Customizer/Controls/Multiple_Checkboxes.php index 83f49451..bb1d290e 100644 --- a/src/BigCommerce/Customizer/Controls/Multiple_Checkboxes.php +++ b/src/BigCommerce/Customizer/Controls/Multiple_Checkboxes.php @@ -6,11 +6,24 @@ /** * Class Multiple_Checkboxes * - * A customizer control that renders as a list of checkboxes + * A customizer control that renders as a list of checkboxes. */ class Multiple_Checkboxes extends \WP_Customize_Control { - public $type = 'checkbox-multiple'; + /** + * The control type. + * + * @var string + */ + public $type = 'checkbox-multiple'; + /** + * Render the content of the control. + * + * Outputs the label, description, and checkboxes for the control along with a hidden field + * to store the selected values for the Customizer API. + * + * @return void + */ public function render_content() { if ( empty( $this->choices ) ) { return; diff --git a/src/BigCommerce/Customizer/Panels/Primary.php b/src/BigCommerce/Customizer/Panels/Primary.php index 62f29245..166bdf70 100644 --- a/src/BigCommerce/Customizer/Panels/Primary.php +++ b/src/BigCommerce/Customizer/Panels/Primary.php @@ -3,20 +3,32 @@ namespace BigCommerce\Customizer\Panels; - +/** + * Class Primary + * + * Represents the primary customizer panel for configuring the BigCommerce store. + */ class Primary { - const NAME = 'bigcommerce'; + /** + * The name of the panel used for identification. + * @var string + */ + const NAME = 'bigcommerce'; - /** - * @param \WP_Customize_Manager $wp_customize - * - * @return void - */ - public function register( $wp_customize ) { - $panel = new \WP_Customize_Panel( $wp_customize, self::NAME, [ - 'title' => __( 'BigCommerce', 'bigcommerce' ), - 'description' => __( 'Edit the appearance of your BigCommerce store', 'bigcommerce' ), - ] ); - $wp_customize->add_panel( $panel ); - } + /** + * Register the primary panel in the WordPress Customizer. + * + * Adds a new panel to the WordPress Customizer for editing the appearance of the BigCommerce store. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer manager instance. + * + * @return void + */ + public function register( $wp_customize ) { + $panel = new \WP_Customize_Panel( $wp_customize, self::NAME, [ + 'title' => __( 'BigCommerce', 'bigcommerce' ), + 'description' => __( 'Edit the appearance of your BigCommerce store', 'bigcommerce' ), + ] ); + $wp_customize->add_panel( $panel ); + } } \ No newline at end of file diff --git a/src/BigCommerce/Customizer/Sections/Banners.php b/src/BigCommerce/Customizer/Sections/Banners.php index bfad4e09..600cd96d 100644 --- a/src/BigCommerce/Customizer/Sections/Banners.php +++ b/src/BigCommerce/Customizer/Sections/Banners.php @@ -6,41 +6,54 @@ use BigCommerce\Customizer\Panels; +/** + * Represents the Customizer section for managing banner settings in the BigCommerce store. + */ class Banners { - const NAME = 'bigcommerce_banners'; - - const ENABLE_BANNERS = 'bigcommerce_enable_banners'; - - /** - * @param \WP_Customize_Manager $wp_customize - * - * @return void - */ - public function register( $wp_customize ) { - $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ - 'title' => __( 'Banners', 'bigcommerce' ), - 'panel' => Panels\Primary::NAME, - ] ) ); - - $this->enable_banners( $wp_customize ); - } - - private function enable_banners( \WP_Customize_Manager $wp_customize ) { - $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::ENABLE_BANNERS, [ - 'type' => 'option', - 'default' => 'no', - 'transport' => 'refresh', - ] ) ); - $wp_customize->add_control( self::ENABLE_BANNERS, [ - 'section' => self::NAME, - 'type' => 'radio', - 'description' => __( 'Enable Banners. ', 'bigcommerce' ), - 'label' => __( 'Banners', 'bigcommerce' ), - 'choices' => [ - 'yes' => __( 'Enabled', 'bigcommerce' ), - 'no' => __( 'Disabled', 'bigcommerce' ), - ], - ] ); - } - + /** + * The identifier for the banners section. + */ + const NAME = 'bigcommerce_banners'; + + /** + * The identifier for the "Enable Banners" setting. + */ + const ENABLE_BANNERS = 'bigcommerce_enable_banners'; + + /** + * Registers the banners section in the WordPress Customizer. + * + * Adds a new section for managing banners under the primary BigCommerce panel. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer manager instance. + * + * @return void + */ + public function register( $wp_customize ) { + $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ + 'title' => __( 'Banners', 'bigcommerce' ), + 'panel' => Panels\Primary::NAME, + ] ) ); + + $this->enable_banners( $wp_customize ); + } + + private function enable_banners( \WP_Customize_Manager $wp_customize ) { + $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::ENABLE_BANNERS, [ + 'type' => 'option', + 'default' => 'no', + 'transport' => 'refresh', + ] ) ); + $wp_customize->add_control( self::ENABLE_BANNERS, [ + 'section' => self::NAME, + 'type' => 'radio', + 'description' => __( 'Enable Banners.', 'bigcommerce' ), + 'label' => __( 'Banners', 'bigcommerce' ), + 'choices' => [ + 'yes' => __( 'Enabled', 'bigcommerce' ), + 'no' => __( 'Disabled', 'bigcommerce' ), + ], + ] ); + } + } \ No newline at end of file diff --git a/src/BigCommerce/Customizer/Sections/Buttons.php b/src/BigCommerce/Customizer/Sections/Buttons.php index 50197c6f..959055d1 100644 --- a/src/BigCommerce/Customizer/Sections/Buttons.php +++ b/src/BigCommerce/Customizer/Sections/Buttons.php @@ -6,21 +6,62 @@ use BigCommerce\Customizer\Panels; +/** + * A customizer section that handles button label settings for various BigCommerce buttons in the WordPress Customizer. + */ class Buttons { - const NAME = 'bigcommerce_buttons'; - - const ADD_TO_CART = 'bigcommerce_add_to_cart_button_label'; - const PREORDER_TO_CART = 'bigcommerce_preorder_add_to_cart_button_label'; - const BUY_NOW = 'bigcommerce_buy_now_button_label'; - const PREORDER_NOW = 'bigcommerce_preorder_now_button_label'; - const CHOOSE_OPTIONS = 'bigcommerce_choose_options_button_label'; - const VIEW_PRODUCT = 'bigcommerce_view_product_button_label'; - - /** - * @param \WP_Customize_Manager $wp_customize - * - * @return void - */ + /** + * The identifier for the buttons section. + * @var string + */ + const NAME = 'bigcommerce_buttons'; + + /** + * The setting for the "Add to Cart" button label. + * @var string + */ + const ADD_TO_CART = 'bigcommerce_add_to_cart_button_label'; + + /** + * The setting for the "Preorder Add to Cart" button label. + * @var string + */ + const PREORDER_TO_CART = 'bigcommerce_preorder_add_to_cart_button_label'; + + /** + * The setting for the "Buy Now" button label. + * @var string + */ + const BUY_NOW = 'bigcommerce_buy_now_button_label'; + + /** + * The setting for the "Preorder Now" button label. + * @var string + */ + const PREORDER_NOW = 'bigcommerce_preorder_now_button_label'; + + /** + * The setting for the "Choose Options" button label. + * @var string + */ + const CHOOSE_OPTIONS = 'bigcommerce_choose_options_button_label'; + + /** + * The setting for the "View Product" button label. + * @var string + */ + const VIEW_PRODUCT = 'bigcommerce_view_product_button_label'; + + /** + * Registers the buttons section and related controls in the WordPress Customizer. + * + * This method adds the buttons section and sets up controls for various button labels, + * such as "Add to Cart," "Buy Now," and others. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer manager instance. + * + * @return void + */ public function register( $wp_customize ) { $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ 'title' => __( 'Buttons', 'bigcommerce' ), diff --git a/src/BigCommerce/Customizer/Sections/Cart.php b/src/BigCommerce/Customizer/Sections/Cart.php index 7e8a32b6..e297ecae 100644 --- a/src/BigCommerce/Customizer/Sections/Cart.php +++ b/src/BigCommerce/Customizer/Sections/Cart.php @@ -4,20 +4,75 @@ use BigCommerce\Customizer\Panels; +/** + * Handles the customization options for the Cart section in the WordPress Customizer. + * Allows users to enable or disable the mini-cart, set the empty cart link destination, + * and control the visibility of shipping info and coupon codes in the cart. + * + * @package BigCommerce\Customizer\Sections + */ class Cart { + /** + * The unique identifier for the Cart section. + * + * @var string + */ const NAME = 'bigcommerce_cart'; + /** + * The setting key for enabling the mini-cart. + * + * @var string + */ const ENABLE_MINI_CART = 'bigcommerce_enable_mini_cart'; + + /** + * The setting key for the empty cart link destination. + * + * @var string + */ const EMPTY_CART_LINK = 'bigcommerce_empty_cart_link_destination'; + + /** + * The setting key for the text displayed in the empty cart link. + * + * @var string + */ const EMPTY_CART_LINK_TEXT = 'bigcommerce_empty_cart_link_destination_text'; + + /** + * The value for the homepage link destination. + * + * @var string + */ const LINK_HOME = 'home'; + + /** + * The value for the product catalog link destination. + * + * @var string + */ const LINK_CATALOG = 'catalog'; + + /** + * The setting key for enabling shipping info in the cart. + * + * @var string + */ const ENABLE_SHIPPING_INFO = 'bigcommerce_enable_shipping_info'; - const ENABLE_COUPON_CODE = 'bigcommerce_enable_coupon_code'; /** - * @param \WP_Customize_Manager $wp_customize + * The setting key for enabling the coupon code in the cart. * + * @var string + */ + const ENABLE_COUPON_CODE = 'bigcommerce_enable_coupon_code'; + + /** + * Registers settings and controls for Cart customization. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer manager instance. + * * @return void */ public function register( $wp_customize ) { diff --git a/src/BigCommerce/Customizer/Sections/Checkout.php b/src/BigCommerce/Customizer/Sections/Checkout.php index f5069839..e27a61c7 100644 --- a/src/BigCommerce/Customizer/Sections/Checkout.php +++ b/src/BigCommerce/Customizer/Sections/Checkout.php @@ -6,22 +6,82 @@ use BigCommerce\Customizer\Panels; +/** + * Handles the customization options for the Checkout section in the WordPress Customizer. + * Allows users to modify the colors of the embedded checkout page including background, text, + * link, and error colors. + * + * @package BigCommerce\Customizer\Sections + */ class Checkout { + /** + * The unique identifier for the Checkout section. + * + * @var string + */ const NAME = 'bigcommerce_checkout'; + /** + * The setting key for the background color in the checkout section. + * + * @var string + */ const BACKGROUND_COLOR = 'bigcommerce_checkout_background_color'; + + /** + * The setting key for the text color in the checkout section. + * + * @var string + */ const TEXT_COLOR = 'bigcommerce_checkout_text_color'; + + /** + * The setting key for the link color in the checkout section. + * + * @var string + */ const LINK_COLOR = 'bigcommerce_checkout_link_color'; + + /** + * The setting key for the error color in the checkout section. + * + * @var string + */ const ERROR_COLOR = 'bigcommerce_checkout_error_color'; + /** + * The default value for the black color. + * + * @var string + */ const COLOR_BLACK = '#000000'; + + /** + * The default value for the white color. + * + * @var string + */ const COLOR_WHITE = '#FFFFFF'; + + /** + * The default value for BigCommerce blue color. + * + * @var string + */ const COLOR_BC_BLUE = '#5273f4'; - const COLOR_BC_RED = '#ed1f00'; /** - * @param \WP_Customize_Manager $wp_customize + * The default value for BigCommerce red color. * + * @var string + */ + const COLOR_BC_RED = '#ed1f00'; + + /** + * Registers settings and controls for Checkout customization. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer manager instance. + * * @return void */ public function register( $wp_customize ) { diff --git a/src/BigCommerce/Customizer/Sections/Colors.php b/src/BigCommerce/Customizer/Sections/Colors.php index dd63b96b..458e2113 100644 --- a/src/BigCommerce/Customizer/Sections/Colors.php +++ b/src/BigCommerce/Customizer/Sections/Colors.php @@ -6,38 +6,164 @@ use BigCommerce\Customizer\Panels; +/** + * Handles the customization constants for colors and themes in the BigCommerce plugin. + */ class Colors { - const NAME = 'bigcommerce_colors'; - - const CSS = 'bigcommerce_use_css'; - - const CSS_FULL = 'default'; - const CSS_OFF = 'disabled'; - - const COLOR_BC_BLUE = '#5273f4'; - const COLOR_BC_GREEN = '#65c68c'; - const COLOR_BC_LIGHT_GREY = '#e0e3e9'; - const COLOR_BC_BLACK = '#34313f'; - const COLOR_BANNER_GREY = '#757575'; - const COLOR_WHITE = '#ffffff'; - const TEXT_DARK = 'dark'; - const TEXT_LIGHT = 'light'; - - const BUTTON_COLOR = 'bigcommerce_button_color'; - const BUTTON_TEXT = 'bigcommerce_button_text_color'; - const SALE_COLOR = 'bigcommerce_sale_color'; - const SALE_TEXT = 'bigcommerce_sale_text_color'; - const AVAILABILITY_COLOR = 'bigcommerce_availability_color'; - const CONDITION_COLOR = 'bigcommerce_condition_color'; - const CONDITION_TEXT = 'bigcommerce_condition_text_color'; - const BANNER_COLOR = 'bigcommerce_banner_color'; - const BANNER_TEXT = 'bigcommerce_banner_text_color'; - - /** - * @param \WP_Customize_Manager $wp_customize - * - * @return void - */ + /** + * Section name for the WordPress Customizer. + * + * @var string + */ + const NAME = 'bigcommerce_colors'; + + /** + * Setting for enabling or disabling plugin CSS. + * + * @var string + */ + const CSS = 'bigcommerce_use_css'; + + /** + * Use plugin styles for the theme. + * + * @var string + */ + const CSS_FULL = 'default'; + + /** + * Disable plugin styles and rely on custom CSS. + * + * @var string + */ + const CSS_OFF = 'disabled'; + + /** + * Default blue color for BigCommerce. + * + * @var string + */ + const COLOR_BC_BLUE = '#5273f4'; + + /** + * Default green color for success or positive indicators. + * + * @var string + */ + const COLOR_BC_GREEN = '#65c68c'; + + /** + * Light grey color for neutral elements. + * + * @var string + */ + const COLOR_BC_LIGHT_GREY = '#e0e3e9'; + + /** + * Black color for text or dark themes. + * + * @var string + */ + const COLOR_BC_BLACK = '#34313f'; + + /** + * Grey color for banners or muted elements. + * + * @var string + */ + const COLOR_BANNER_GREY = '#757575'; + + /** + * White color for backgrounds or light themes. + * + * @var string + */ + const COLOR_WHITE = '#ffffff'; + + /** + * Dark text option for contrast with light backgrounds. + * + * @var string + */ + const TEXT_DARK = 'dark'; + + /** + * Light text option for contrast with dark backgrounds. + * + * @var string + */ + const TEXT_LIGHT = 'light'; + + /** + * Setting for the button background color. + * + * @var string + */ + const BUTTON_COLOR = 'bigcommerce_button_color'; + + /** + * Setting for the button text color. + * + * @var string + */ + const BUTTON_TEXT = 'bigcommerce_button_text_color'; + + /** + * Setting for the sale price color. + * + * @var string + */ + const SALE_COLOR = 'bigcommerce_sale_color'; + + /** + * Setting for the sale icon text color. + * + * @var string + */ + const SALE_TEXT = 'bigcommerce_sale_text_color'; + + /** + * Setting for the product availability color. + * + * @var string + */ + const AVAILABILITY_COLOR = 'bigcommerce_availability_color'; + + /** + * Setting for the product condition color. + * + * @var string + */ + const CONDITION_COLOR = 'bigcommerce_condition_color'; + + /** + * Setting for the product condition text color. + * + * @var string + */ + const CONDITION_TEXT = 'bigcommerce_condition_text_color'; + + /** + * Setting for the banner background color. + * + * @var string + */ + const BANNER_COLOR = 'bigcommerce_banner_color'; + + /** + * Setting for the banner text color. + * + * @var string + */ + const BANNER_TEXT = 'bigcommerce_banner_text_color'; + + /** + * Registers the Colors section and related settings in the WordPress Customizer. + * + * @param \WP_Customize_Manager $wp_customize Instance of the WordPress Customizer. + * + * @return void + */ public function register( $wp_customize ) { $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ 'title' => __( 'Colors & Theme', 'bigcommerce' ), @@ -179,7 +305,7 @@ private function banners( \WP_Customize_Manager $wp_customize ) { ] ) ); $wp_customize->add_control( new \WP_Customize_Color_Control( $wp_customize, self::BANNER_COLOR, [ 'section' => self::NAME, - 'label' => __( 'Banner Backgound Color', 'bigcommerce' ), + 'label' => __( 'Banner Background Color', 'bigcommerce' ), ] ) ); $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::BANNER_TEXT, [ @@ -194,4 +320,4 @@ private function banners( \WP_Customize_Manager $wp_customize ) { ] ) ); } -} \ No newline at end of file +} diff --git a/src/BigCommerce/Customizer/Sections/Product_Archive.php b/src/BigCommerce/Customizer/Sections/Product_Archive.php index bf6b0e06..9f5255d9 100644 --- a/src/BigCommerce/Customizer/Sections/Product_Archive.php +++ b/src/BigCommerce/Customizer/Sections/Product_Archive.php @@ -8,43 +8,136 @@ use BigCommerce\Taxonomies\Brand\Brand; use BigCommerce\Taxonomies\Product_Category\Product_Category; +/** + * Customizer settings and controls for the Product Archive section. + * + * This class defines constants and methods to register and manage customizer + * options for the product catalog, including settings for sorting, filtering, + * slugs, and layout. + */ class Product_Archive { - const NAME = 'bigcommerce_product_archive'; - - const ARCHIVE_TITLE = 'bigcommerce_product_archive_title'; - const ARCHIVE_SLUG = 'bigcommerce_product_archive_slug'; - const ARCHIVE_DESCRIPTION = 'bigcommerce_product_archive_description'; - const SORT_OPTIONS = 'bigcommerce_product_archive_sort_options'; - const FILTER_OPTIONS = 'bigcommerce_product_archive_filter_options'; - - const CATEGORY_SLUG = 'bigcommerce_category_archive_slug'; - const BRAND_SLUG = 'bigcommerce_brand_archive_slug'; - - const SORT_FEATURED = 'featured'; - const SORT_DATE = 'date'; - const SORT_SALES = 'sales'; - const SORT_TITLE_ASC = 'title_asc'; - const SORT_TITLE_DESC = 'title_desc'; - const SORT_REVIEWS = 'reviews'; - const SORT_PRICE_ASC = 'price_asc'; - const SORT_PRICE_DESC = 'price_desc'; - const SORT_INVENTORY_COUNT = 'inventory_count'; - const SORT_SKU = 'sku'; + /** @var string The identifier for the Product Archive section in the customizer. */ + const NAME = 'bigcommerce_product_archive'; + + /** @var string Setting key for the product archive title. */ + const ARCHIVE_TITLE = 'bigcommerce_product_archive_title'; + + /** @var string Setting key for the product archive slug. */ + const ARCHIVE_SLUG = 'bigcommerce_product_archive_slug'; + + /** @var string Setting key for the product archive description. */ + const ARCHIVE_DESCRIPTION = 'bigcommerce_product_archive_description'; + + /** @var string Setting key for the available sorting options in the product archive. */ + const SORT_OPTIONS = 'bigcommerce_product_archive_sort_options'; + + /** @var string Setting key for the available filtering options in the product archive. */ + const FILTER_OPTIONS = 'bigcommerce_product_archive_filter_options'; + + /** @var string Setting key for the category archive slug. */ + const CATEGORY_SLUG = 'bigcommerce_category_archive_slug'; - const FILTER_CATEGORY = Product_Category::NAME; - const FILTER_BRAND = Brand::NAME; - const PER_PAGE_DEFAULT = 24; - const PER_PAGE = 'bigcommerce_products_per_page'; - const GRID_COLUMNS = 'bigcommerce_catalog_grid_columns'; - const QUICK_VIEW = 'bigcommerce_enable_quick_view'; - const SEARCH_FIELD = 'bigcommerce_catalog_enable_search_field'; - const GENERAL_INVENTORY = 'bigcommerce_general_inventory_settings'; + /** @var string Setting key for the brand archive slug. */ + const BRAND_SLUG = 'bigcommerce_brand_archive_slug'; /** - * @param \WP_Customize_Manager $wp_customize - * - * @return void + * Sort by featured products. + * @var string + */ + const SORT_FEATURED = 'featured'; + + /** + * Sort by date added (newest first). + * @var string + */ + const SORT_DATE = 'date'; + + /** + * Sort by sales performance. + * @var string + */ + const SORT_SALES = 'sales'; + + /** + * Sort by title (A-Z). + * @var string + */ + const SORT_TITLE_ASC = 'title_asc'; + + /** + * Sort by title (Z-A). + * @var string + */ + const SORT_TITLE_DESC = 'title_desc'; + + /** + * Sort by customer reviews. + * @var string + */ + const SORT_REVIEWS = 'reviews'; + + /** + * Sort by price (low to high). + * @var string + */ + const SORT_PRICE_ASC = 'price_asc'; + + /** + * Sort by price (high to low). + * @var string + */ + const SORT_PRICE_DESC = 'price_desc'; + + /** + * Sort by inventory count. + * @var string + */ + const SORT_INVENTORY_COUNT = 'inventory_count'; + + /** + * Sort by SKU. + * @var string + */ + const SORT_SKU = 'sku'; + + /** + * The filter key for product categories in the catalog. + * + * @var string */ + const FILTER_CATEGORY = Product_Category::NAME; + + /** + * The filter key for product brands in the catalog. + * + * @var string + */ + const FILTER_BRAND = Brand::NAME; + + /** @var int Default number of products per page. */ + const PER_PAGE_DEFAULT = 24; + + /** @var string Setting key for the number of products displayed per page. */ + const PER_PAGE = 'bigcommerce_products_per_page'; + + /** @var string Setting key for the number of grid columns in the product catalog. */ + const GRID_COLUMNS = 'bigcommerce_catalog_grid_columns'; + + /** @var string Setting key for enabling the Quick View feature in the product catalog. */ + const QUICK_VIEW = 'bigcommerce_enable_quick_view'; + + /** @var string Setting key for enabling the search field in the product catalog. */ + const SEARCH_FIELD = 'bigcommerce_catalog_enable_search_field'; + + /** @var string Setting key for respecting general inventory settings. */ + const GENERAL_INVENTORY = 'bigcommerce_general_inventory_settings'; + + /** + * Registers customizer settings and controls for the product archive section. + * + * @param \WP_Customize_Manager $wp_customize WordPress Customizer manager instance. + * @return void + */ public function register( $wp_customize ) { $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ 'title' => __( 'Product Catalog', 'bigcommerce' ), @@ -146,6 +239,11 @@ private function sorting( \WP_Customize_Manager $wp_customize ) { ] ) ); } + /** + * Retrieves the available sorting choices for the product catalog. + * + * @return array An associative array of sorting choices with keys and labels. + */ public static function sort_choices() { $choices = [ self::SORT_FEATURED => __( 'Featured', 'bigcommerce' ), @@ -168,6 +266,12 @@ public static function sort_choices() { return apply_filters( 'bigcommerce/product/archive/sort_options', $choices ); } + /** + * Sanitizes and validates the sorting choices. + * + * @param array|string $values The sorting choices input to sanitize. + * @return array Sanitized sorting choices. + */ public function sanitize_sort( $values ) { if ( empty( $values ) ) { return $values; @@ -198,6 +302,11 @@ private function filtering( \WP_Customize_Manager $wp_customize ) { ] ) ); } + /** + * Retrieves filtering choices for the BigCommerce catalog. + * + * @return array The filtering options available. + */ public static function filter_choices() { $choices = [ self::FILTER_CATEGORY => __( 'Categories', 'bigcommerce' ), @@ -212,6 +321,12 @@ public static function filter_choices() { return apply_filters( 'bigcommerce/product/archive/filter_options', $choices ); } + /** + * Sanitizes the provided filter values to ensure they match available choices. + * + * @param array|string $values The filter values to sanitize. + * @return array The sanitized filter values. + */ public function sanitize_filter( $values ) { if ( empty( $values ) ) { return $values; @@ -281,6 +396,11 @@ private function per_page( \WP_Customize_Manager $wp_customize ) { ] ) ); } + /** + * Gets the field description for display in the WordPress Customizer. + * + * @return string The description HTML or an empty string. + */ public function get_field_description() { if ( ! ( function_exists( 'et_setup_theme' ) || function_exists( 'et_framework_setup' ) ) ) { return ''; diff --git a/src/BigCommerce/Customizer/Sections/Product_Category.php b/src/BigCommerce/Customizer/Sections/Product_Category.php index 9b2f766a..46caa79b 100644 --- a/src/BigCommerce/Customizer/Sections/Product_Category.php +++ b/src/BigCommerce/Customizer/Sections/Product_Category.php @@ -5,78 +5,99 @@ use BigCommerce\Customizer\Panels; /** - * Class Product_Category + * Handles the customization of product category settings and controls. * * @package BigCommerce\Customizer\Sections */ class Product_Category { - const NAME = 'bigcommerce_product_categories'; - const CHILD_ITEM_SHOW = 'bigcommerce_show_child_items'; - const CATEGORIES_IS_VISIBLE = 'bigcommerce_categories_is_visible'; + /** + * The section name for product categories in the customizer. + * + * @var string + */ + const NAME = 'bigcommerce_product_categories'; - /** - * Register Product Category customize section and related controls - * - * @param \WP_Customize_Manager $wp_customize - * - * @return void - */ - public function register( $wp_customize ) { - $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ - 'title' => __( 'Product Category', 'bigcommerce' ), - 'panel' => Panels\Primary::NAME, - ] ) ); + /** + * The option key for showing child items in the navigation menu. + * + * @var string + */ + const CHILD_ITEM_SHOW = 'bigcommerce_show_child_items'; - $this->add_sub_categories_control( $wp_customize ); - $this->add_is_visible_control( $wp_customize ); - } + /** + * The option key for the "categories is visible" flag. + * + * @var string + */ + const CATEGORIES_IS_VISIBLE = 'bigcommerce_categories_is_visible'; - /** - * Register radio box control for categories is_visible flag - * - * @param \WP_Customize_Manager $wp_customize - */ - protected function add_is_visible_control( \WP_Customize_Manager $wp_customize ) { - $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::CATEGORIES_IS_VISIBLE, [ - 'type' => 'option', - 'default' => 'no', - 'transport' => 'refresh', - ] ) ); + /** + * Register Product Category customize section and related controls. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer instance. + * + * @return void + */ + public function register( $wp_customize ) { + $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ + 'title' => __( 'Product Category', 'bigcommerce' ), + 'panel' => Panels\Primary::NAME, + ] ) ); - $wp_customize->add_control(self::CATEGORIES_IS_VISIBLE, [ - 'section' => self::NAME, - 'type' => 'radio', - 'label' => __( 'Categories `is_visible` option', 'bigcommerce' ), - 'choices' => [ - 'yes' => __( 'Enable categories is_visible flag support', 'bigcommerce' ), - 'no' => __( 'Disable categories is_visible flag support', 'bigcommerce' ), - ], - 'description' => __( 'If enabled only categories marked as visible in Bigcommerce Dashboard will be displayed on the store', 'bigcommerce' ), - ] ); - } + $this->add_sub_categories_control( $wp_customize ); + $this->add_is_visible_control( $wp_customize ); + } - /** - * Register controls for child items in nav menu - * - * @param \WP_Customize_Manager $wp_customize - */ - protected function add_sub_categories_control( \WP_Customize_Manager $wp_customize ) { - $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::CHILD_ITEM_SHOW, [ - 'type' => 'option', - 'default' => 'no', - 'transport' => 'refresh', - ] ) ); + /** + * Register radio box control for categories "is visible" flag. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer instance. + * + * @return void + */ + protected function add_is_visible_control( \WP_Customize_Manager $wp_customize ) { + $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::CATEGORIES_IS_VISIBLE, [ + 'type' => 'option', + 'default' => 'no', + 'transport' => 'refresh', + ] ) ); - $wp_customize->add_control(self::CHILD_ITEM_SHOW, [ - 'section' => self::NAME, - 'type' => 'radio', - 'label' => __( 'Menus Sub-Categories', 'bigcommerce' ), - 'choices' => [ - 'yes' => __( 'Show Product Sub-Categories in Menu', 'bigcommerce' ), - 'no' => __( 'Hide Product Sub-Categories in Menu', 'bigcommerce' ), - ], - 'description' => __( 'Toggle the ability to displaying Sub-Categories in menu', 'bigcommerce' ), - ] ); - } + $wp_customize->add_control( self::CATEGORIES_IS_VISIBLE, [ + 'section' => self::NAME, + 'type' => 'radio', + 'label' => __( 'Categories `is_visible` option', 'bigcommerce' ), + 'choices' => [ + 'yes' => __( 'Enable categories is_visible flag support', 'bigcommerce' ), + 'no' => __( 'Disable categories is_visible flag support', 'bigcommerce' ), + ], + 'description' => __( 'If enabled, only categories marked as visible in the BigCommerce Dashboard will be displayed on the store.', 'bigcommerce' ), + ] ); + } + + /** + * Register controls for showing child items in the navigation menu. + * + * @param \WP_Customize_Manager $wp_customize The WordPress Customizer instance. + * + * @return void + */ + protected function add_sub_categories_control( \WP_Customize_Manager $wp_customize ) { + $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::CHILD_ITEM_SHOW, [ + 'type' => 'option', + 'default' => 'no', + 'transport' => 'refresh', + ] ) ); + + $wp_customize->add_control( self::CHILD_ITEM_SHOW, [ + 'section' => self::NAME, + 'type' => 'radio', + 'label' => __( 'Menus Sub-Categories', 'bigcommerce' ), + 'choices' => [ + 'yes' => __( 'Show Product Sub-Categories in Menu', 'bigcommerce' ), + 'no' => __( 'Hide Product Sub-Categories in Menu', 'bigcommerce' ), + ], + 'description' => __( 'Toggle the ability to display sub-categories in the menu.', 'bigcommerce' ), + ] ); + } } diff --git a/src/BigCommerce/Customizer/Sections/Product_Single.php b/src/BigCommerce/Customizer/Sections/Product_Single.php index e727e794..70012560 100644 --- a/src/BigCommerce/Customizer/Sections/Product_Single.php +++ b/src/BigCommerce/Customizer/Sections/Product_Single.php @@ -6,30 +6,114 @@ use BigCommerce\Customizer\Panels; use BigCommerce\Settings\Sections\Import; +/** + * Handles settings and constants related to the single product page in the BigCommerce integration. + * It defines various constants used for customization of product display, such as meta descriptions, gallery settings, pricing, and more. + */ class Product_Single { + /** + * The name of the product single page. + * @var string + */ const NAME = 'bigcommerce_product_single'; - const RELATED_COUNT = 'bigcommerce_max_related_products'; - const DEFAULT_IMAGE = 'bigcommerce_default_image_id'; - const PRICE_DISPLAY = 'bigcommerce_default_price_display'; - const INVENTORY_DISPLAY = 'bigcommerce_inventory_display'; - const VARIANTS_DISABLED = 'bigcommerce_variants_disabled'; - const META_DESC_DISABLE = 'bigcommerce_meta_description_disabled'; - const GALLERY_SIZE = 'bigcommerce_gallery_image_size'; + /** + * The maximum number of related products to display. + * @var string + */ + const RELATED_COUNT = 'bigcommerce_max_related_products'; + + /** + * The default image ID for the product. + * @var string + */ + const DEFAULT_IMAGE = 'bigcommerce_default_image_id'; + + /** + * The default price display option for the product. + * @var string + */ + const PRICE_DISPLAY = 'bigcommerce_default_price_display'; + + /** + * The inventory display setting for the product. + * @var string + */ + const INVENTORY_DISPLAY = 'bigcommerce_inventory_display'; + + /** + * The setting for whether variants are disabled for the product. + * @var string + */ + const VARIANTS_DISABLED = 'bigcommerce_variants_disabled'; + + /** + * The setting for whether the meta description is disabled. + * @var string + */ + const META_DESC_DISABLE = 'bigcommerce_meta_description_disabled'; + + /** + * The image size for the product gallery. + * @var string + */ + const GALLERY_SIZE = 'bigcommerce_gallery_image_size'; + + /** + * The image size for the gallery when in headless mode. + * @var string + */ const HEADLESS_IMAGE_SIZE = 'bigcommerce_gallery_headless_image_size'; - const ENABLE_ZOOM = 'bigcommerce_enable_zoom'; - const ENABLE_PRICE_NONCE = 'bigcommerce_enable_price_nonce'; - const SIZE_DEFAULT = 'default'; - const SIZE_LARGE = 'large'; - const SIZE_ORIGINAL = 'original'; - const SIZE_CDN_STD = 'standard'; - const SIZE_CDN_THUMB = 'thumbnail'; /** - * @param \WP_Customize_Manager $wp_customize - * - * @return void + * The setting for enabling zoom functionality on product images. + * @var string + */ + const ENABLE_ZOOM = 'bigcommerce_enable_zoom'; + + /** + * The setting for enabling pricing nonce field. + * @var string + */ + const ENABLE_PRICE_NONCE = 'bigcommerce_enable_price_nonce'; + + /** + * The default image size. + * @var string + */ + const SIZE_DEFAULT = 'default'; + + /** + * The large image size. + * @var string + */ + const SIZE_LARGE = 'large'; + + /** + * The original image size. + * @var string */ + const SIZE_ORIGINAL = 'original'; + + /** + * The standard image size for the CDN. + * @var string + */ + const SIZE_CDN_STD = 'standard'; + + /** + * The thumbnail image size for the CDN. + * @var string + */ + const SIZE_CDN_THUMB = 'thumbnail'; + + /** + * Registers all customization options under the product single section. + * + * @param \WP_Customize_Manager $wp_customize The WordPress customizer instance. + * + * @return void + */ public function register( $wp_customize ) { $wp_customize->add_section( new \WP_Customize_Section( $wp_customize, self::NAME, [ 'title' => __( 'Product Single', 'bigcommerce' ), @@ -190,7 +274,13 @@ private function variants( \WP_Customize_Manager $wp_customize ) { ], ] ); } - + /** + * Adds the meta description display setting and control. + * + * @param \WP_Customize_Manager $wp_customize Customizer manager instance. + * + * @return void + */ protected function meta_description( \WP_Customize_Manager $wp_customize ) { $wp_customize->add_setting( new \WP_Customize_Setting( $wp_customize, self::META_DESC_DISABLE, [ 'type' => 'option', @@ -209,9 +299,12 @@ protected function meta_description( \WP_Customize_Manager $wp_customize ) { } /** - * Register pricing nonce option setting + * Registers the pricing nonce field option setting and control. + * Only enabled when the headless flag is set. * - * @param \WP_Customize_Manager $wp_customize + * @param \WP_Customize_Manager $wp_customize Customizer manager instance. + * + * @return void */ protected function pricing_nonce( \WP_Customize_Manager $wp_customize ): void { if ( ( int ) get_option( Import::HEADLESS_FLAG, 0 ) !== 1 ) { diff --git a/src/BigCommerce/Customizer/Styles.php b/src/BigCommerce/Customizer/Styles.php index cc456fed..a3c8e0ea 100644 --- a/src/BigCommerce/Customizer/Styles.php +++ b/src/BigCommerce/Customizer/Styles.php @@ -6,24 +6,43 @@ use BigCommerce\Customizer\Sections\Colors; +/** + * This class handles the customization of CSS styles for BigCommerce components. + * It loads and manipulates a CSS template file and outputs dynamic styles based on theme settings. + */ class Styles { + /** + * Path to the CSS template file. + * @var string + */ private $template_file; + /** + * The color black from the Colors class. + * @var string + */ private $black = Colors::COLOR_BC_BLACK; + + /** + * The color white. + * @var string + */ private $white = '#fff'; /** * Styles constructor. * - * @param string $template_file Path to the CSS template file + * @param string $template_file Path to the CSS template file. */ public function __construct( $template_file ) { $this->template_file = $template_file; } /** - * @return string + * Retrieves the styles by replacing CSS variables with values from the theme customization. + * + * @return string The generated CSS styles. */ public function get_styles() { if ( ! $this->using_plugin_css() ) { @@ -46,9 +65,9 @@ public function get_styles() { } /** - * Filters customizer styles css. + * Filters customizer styles CSS. * - * @param string $css styles. + * @param string $css The styles. */ $css = apply_filters( 'bigcommerce/css/customizer_styles', $template ); @@ -56,6 +75,8 @@ public function get_styles() { } /** + * Prints the generated styles within a `