From b93a7a23ad2f0eba5fd59171b8bf0e8a8364403c Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Thu, 10 Jul 2025 12:24:12 +0100 Subject: [PATCH 01/19] POC. Can you log data with monolog for WPGraphQL. Not production ready. --- plugins/wpgraphql-logging/.distignore | 36 + plugins/wpgraphql-logging/.docker/Dockerfile | 83 + .../wpgraphql-logging/.docker/init-docker.sh | 26 + plugins/wpgraphql-logging/.editorconfig | 18 + plugins/wpgraphql-logging/.env.dist | 65 + plugins/wpgraphql-logging/.gitignore | 57 + plugins/wpgraphql-logging/CHANGELOG.md | 4 + plugins/wpgraphql-logging/LICENSE | 339 + plugins/wpgraphql-logging/README.md | 20 + plugins/wpgraphql-logging/activation.php | 17 + plugins/wpgraphql-logging/assets/.gitkeep | 0 plugins/wpgraphql-logging/bin/_lib.sh | 46 + plugins/wpgraphql-logging/bin/build-docker.sh | 62 + .../wpgraphql-logging/bin/install-plugins.sh | 19 + .../wpgraphql-logging/bin/install-test-env.sh | 239 + .../bin/local/run-e2e-tests.sh | 23 + plugins/wpgraphql-logging/bin/local/run-qa.sh | 6 + .../bin/local/run-unit-tests.sh | 27 + .../bin/local/setup-docker-env.sh | 161 + .../wpgraphql-logging/bin/run-codeception.sh | 154 + .../bin/sync-package-version.sh | 59 + .../wpgraphql-logging/codeception.dist.yml | 103 + plugins/wpgraphql-logging/composer.json | 165 + plugins/wpgraphql-logging/composer.lock | 11377 ++++++++++++++++ plugins/wpgraphql-logging/deactivation.php | 18 + plugins/wpgraphql-logging/docker-compose.yml | 47 + plugins/wpgraphql-logging/docs/.gitkeep | 0 plugins/wpgraphql-logging/examples/.gitkeep | 0 plugins/wpgraphql-logging/package.json | 23 + .../ControlStructures/ElseKeywordSniff.php | 47 + .../phpcs/HWPStandard/ruleset.xml | 4 + plugins/wpgraphql-logging/phpstan.neon.dist | 33 + .../Rules/ClassConstantVarAnnotationRule.php | 41 + plugins/wpgraphql-logging/psalm.xml | 29 + plugins/wpgraphql-logging/readme.txt | 19 + plugins/wpgraphql-logging/src/Autoloader.php | 95 + .../src/Database/LoggingEntity.php | 163 + .../Handlers/WPGraphQLDatabaseHandler.php | 34 + .../src/Logging/WPGraphQLLoggingService.php | 125 + plugins/wpgraphql-logging/src/Plugin.php | 96 + .../wpgraphql-logging/tests/_envs/.gitkeep | 0 plugins/wpgraphql-logging/tests/bootstrap.php | 20 + .../tests/wpunit.suite.dist.yml | 12 + .../tests/wpunit/bootstrap.php | 7 + .../wpgraphql-logging/wpgraphql-logging.php | 143 + 45 files changed, 14062 insertions(+) create mode 100644 plugins/wpgraphql-logging/.distignore create mode 100644 plugins/wpgraphql-logging/.docker/Dockerfile create mode 100644 plugins/wpgraphql-logging/.docker/init-docker.sh create mode 100644 plugins/wpgraphql-logging/.editorconfig create mode 100644 plugins/wpgraphql-logging/.env.dist create mode 100644 plugins/wpgraphql-logging/.gitignore create mode 100644 plugins/wpgraphql-logging/CHANGELOG.md create mode 100644 plugins/wpgraphql-logging/LICENSE create mode 100644 plugins/wpgraphql-logging/README.md create mode 100644 plugins/wpgraphql-logging/activation.php create mode 100644 plugins/wpgraphql-logging/assets/.gitkeep create mode 100644 plugins/wpgraphql-logging/bin/_lib.sh create mode 100644 plugins/wpgraphql-logging/bin/build-docker.sh create mode 100644 plugins/wpgraphql-logging/bin/install-plugins.sh create mode 100644 plugins/wpgraphql-logging/bin/install-test-env.sh create mode 100755 plugins/wpgraphql-logging/bin/local/run-e2e-tests.sh create mode 100755 plugins/wpgraphql-logging/bin/local/run-qa.sh create mode 100755 plugins/wpgraphql-logging/bin/local/run-unit-tests.sh create mode 100644 plugins/wpgraphql-logging/bin/local/setup-docker-env.sh create mode 100755 plugins/wpgraphql-logging/bin/run-codeception.sh create mode 100755 plugins/wpgraphql-logging/bin/sync-package-version.sh create mode 100644 plugins/wpgraphql-logging/codeception.dist.yml create mode 100644 plugins/wpgraphql-logging/composer.json create mode 100644 plugins/wpgraphql-logging/composer.lock create mode 100644 plugins/wpgraphql-logging/deactivation.php create mode 100644 plugins/wpgraphql-logging/docker-compose.yml create mode 100644 plugins/wpgraphql-logging/docs/.gitkeep create mode 100644 plugins/wpgraphql-logging/examples/.gitkeep create mode 100644 plugins/wpgraphql-logging/package.json create mode 100644 plugins/wpgraphql-logging/phpcs/HWPStandard/Sniffs/ControlStructures/ElseKeywordSniff.php create mode 100644 plugins/wpgraphql-logging/phpcs/HWPStandard/ruleset.xml create mode 100644 plugins/wpgraphql-logging/phpstan.neon.dist create mode 100644 plugins/wpgraphql-logging/phpstan/Rules/ClassConstantVarAnnotationRule.php create mode 100644 plugins/wpgraphql-logging/psalm.xml create mode 100644 plugins/wpgraphql-logging/readme.txt create mode 100644 plugins/wpgraphql-logging/src/Autoloader.php create mode 100644 plugins/wpgraphql-logging/src/Database/LoggingEntity.php create mode 100644 plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php create mode 100644 plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php create mode 100644 plugins/wpgraphql-logging/src/Plugin.php create mode 100644 plugins/wpgraphql-logging/tests/_envs/.gitkeep create mode 100644 plugins/wpgraphql-logging/tests/bootstrap.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit.suite.dist.yml create mode 100644 plugins/wpgraphql-logging/tests/wpunit/bootstrap.php create mode 100644 plugins/wpgraphql-logging/wpgraphql-logging.php diff --git a/plugins/wpgraphql-logging/.distignore b/plugins/wpgraphql-logging/.distignore new file mode 100644 index 00000000..24deaa54 --- /dev/null +++ b/plugins/wpgraphql-logging/.distignore @@ -0,0 +1,36 @@ +/.devcontainer +/.git +/.github +/.idea +/.log +/.vscode +/.wordpress-org +/bin +/docker +/docker-output +/docs +/img +/phpstan +/plugin-build +/tests + +.coveralls.yml +.distignore +.dockerignore +.DS_Store +.env +.env.dist +.gitattributes +.gitignore +.phpcs.xml +.phpcs.xml.dist +.travis.yml +CHANGELOG.md +codeception.dist.yml +codeception.yml +composer.json +composer.lock +docker-compose.yml +phpstan.neon.dist +README.md +schema.graphql \ No newline at end of file diff --git a/plugins/wpgraphql-logging/.docker/Dockerfile b/plugins/wpgraphql-logging/.docker/Dockerfile new file mode 100644 index 00000000..1125f273 --- /dev/null +++ b/plugins/wpgraphql-logging/.docker/Dockerfile @@ -0,0 +1,83 @@ +############################################################################### +# Pre-configured WordPress Installation w/ WPGraphQL Logging Plugin +# For testing only, use in production not recommended. # +############################################################################### + +# Use build args to get the right wordpress + php image +ARG WP_VERSION +ARG PHP_VERSION + +FROM wordpress:${WP_VERSION:-6.8}-php${PHP_VERSION:-8.2} + +# Needed to specify the build args again after the FROM command. +ARG WP_VERSION +ARG PHP_VERSION + +# Save the build args for use by the runtime environment +ENV WP_VERSION=${WP_VERSION} +ENV PHP_VERSION=${PHP_VERSION} + +SHELL [ "/bin/bash", "-c" ] + +# Install required packages +RUN apt-get update && \ + apt-get -y install \ + git \ + ssh \ + tar \ + gzip \ + mariadb-client \ + net-tools + +# Needed for Codeception WPDB test integration. +RUN docker-php-ext-install pdo pdo_mysql + +# Install XDebug 3 +RUN if [[ $PHP_VERSION == 7* ]]; then pecl install xdebug-3.1.5; else pecl install xdebug; fi \ + && mkdir -p /usr/local/etc/php/conf.d/disabled \ + && echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/disabled/docker-php-ext-xdebug.ini \ + && echo "xdebug.mode=develop,debug,coverage" >> /usr/local/etc/php/conf.d/disabled/docker-php-ext-xdebug.ini \ + && echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/disabled/docker-php-ext-xdebug.ini \ + && echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/disabled/docker-php-ext-xdebug.ini \ + && echo "xdebug.client_port=9003" >> /usr/local/etc/php/conf.d/disabled/docker-php-ext-xdebug.ini \ + && echo "xdebug.max_nesting_level=512" >> /usr/local/etc/php/conf.d/disabled/docker-php-ext-xdebug.ini \ + ; + +# Set xdebug configuration off by default. Set USING_XDEBUG=1 in the runtime environment to enable it. +ENV USING_XDEBUG=0 + +# Install PCOV +# This is needed for Codeception / PHPUnit to track code coverage +RUN apt-get install zip unzip -y \ + && pecl install pcov + +# Install Dockerize +ENV DOCKERIZE_VERSION=v0.7.0 +RUN curl -L -O https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ + && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz + +# Install composer +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer +RUN chmod +x /usr/local/bin/composer + +# Install WP-CLI +RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \ + && chmod +x wp-cli.phar \ + && mv wp-cli.phar /usr/local/bin/wp + +# Install nvm, Node.js, and npm +ENV NVM_DIR=/usr/local/nvm +ENV NODE_VERSION=20 + +RUN mkdir -p $NVM_DIR +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash \ + && . $NVM_DIR/nvm.sh \ + && nvm install $NODE_VERSION \ + && nvm use $NODE_VERSION \ + && nvm alias default $NODE_VERSION \ + && npm install -g npm + +# Setup the container for testing +COPY init-docker.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/init-docker.sh diff --git a/plugins/wpgraphql-logging/.docker/init-docker.sh b/plugins/wpgraphql-logging/.docker/init-docker.sh new file mode 100644 index 00000000..7d09fd8e --- /dev/null +++ b/plugins/wpgraphql-logging/.docker/init-docker.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Exit if any command fails. +set -e + +# Wait for the database +dockerize -wait tcp://"${WORDPRESS_DB_HOST}":3306 -timeout 1m + +# Get the current user + +cd "$WORDPRESS_ROOT_DIR/wp-content/plugins/$PLUGIN_SLUG" + +# Load NVM +source $NVM_DIR/nvm.sh +nvm use $NODE_VERSION + +# Setup the test environment +chmod +x ./bin/install-test-env.sh + +bash -c "./bin/install-test-env.sh" + +echo "Setting permissions" +chmod -R 777 "$WORDPRESS_ROOT_DIR/wp-content/plugins/$PLUGIN_SLUG" + +# Go back to the root directory +cd "$WORDPRESS_ROOT_DIR" diff --git a/plugins/wpgraphql-logging/.editorconfig b/plugins/wpgraphql-logging/.editorconfig new file mode 100644 index 00000000..465c8289 --- /dev/null +++ b/plugins/wpgraphql-logging/.editorconfig @@ -0,0 +1,18 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +# WordPress Coding Standards +# https://make.wordpress.org/core/handbook/coding-standards/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab + + +[*.md] +trim_trailing_whitespace = false diff --git a/plugins/wpgraphql-logging/.env.dist b/plugins/wpgraphql-logging/.env.dist new file mode 100644 index 00000000..20707bc8 --- /dev/null +++ b/plugins/wpgraphql-logging/.env.dist @@ -0,0 +1,65 @@ +PLUGIN_SLUG=wpgraphql-logging + +# Configure these to match your existing testing environment or the one you want to create with Docker. +## Usually, these values should match the ones in the `wp-config.php` file. +## If using Local by Flywheel, you can `open AdminerEvo` and find the values in the URL: `http://localhost:{DB_PORT}/?username={DB_USER}&db={DB_NAME}` +## NOTE: Codeception may modify or the database during testing. If you want to preserve your local data, create a new database and use that for the `DB_NAME`. +DB_NAME=wordpress +# localhost creates issues with wp config create command +DB_HOST=127.0.0.1 +DB_USER=root +DB_PASSWORD=password +DB_PORT=3306 + +# The local path to the WordPress root directory, the one containing the wp-load.php file. +## This can be a relative path from the directory that contains the codeception.yml file, or an absolute path. +## If you are using Local by Flywheel, you can find the path in the Local by Flywheel app under the site's settings. +WORDPRESS_ROOT_DIR="/tmp/wordpress" + +# This table prefix used by the WordPress site, and in Acceptance tests. +WORDPRESS_TABLE_PREFIX=wp_ + +# The URL and domain of the WordPress site, and in Acceptance tests. +## If the port is in use, you can change it to a different port. +WORDPRESS_URL=http://localhost +WORDPRESS_DOMAIN=localhost +WORDPRESS_ADMIN_PATH=/wp-admin + +# The username and password of the administrator user of the WordPress site, and in Acceptance tests. +WORDPRESS_ADMIN_USER=admin +WORDPRESS_ADMIN_PASSWORD=password +WORDPRESS_ADMIN_EMAIL=admin@example.com + +# Tests will require a MySQL database to run. +# Do not use a database that contains important data! +WORDPRESS_DB_HOST=${DB_HOST} +WORDPRESS_DB_USER=${DB_USER} +WORDPRESS_DB_PASSWORD=${DB_PASSWORD} +WORDPRESS_DB_NAME=${DB_NAME} +WORDPRESS_DB_PORT=${DB_PORT} + +# WPUnit tests will use these variables instead. +# By default this is the same as WordPress +TEST_DB_HOST=${WORDPRESS_DB_HOST} +TEST_DB_USER=${WORDPRESS_DB_USER} +TEST_DB_PASSWORD=${WORDPRESS_DB_PASSWORD} +TEST_DB_NAME=${WORDPRESS_DB_NAME} +TEST_DB_PORT=${WORDPRESS_DB_PORT} +# The Integration suite will use this table prefix for the WordPress tables. +TEST_TABLE_PREFIX=test_ + +# The DSN used by Acceptance tests. +TEST_DB_DSN="mysql:host=${TEST_DB_HOST};port=${TEST_DB_PORT};dbname=${TEST_DB_NAME}" + +# The following variables are used to determine test behavior. + +# Include 3rd party plugins (e.g. WooCommerce) in the tests. +INCLUDE_EXTENSIONS=true +# Skips recreating the database before running the tests. +SKIP_DB_CREATE=false +# Skips configuring the WordPress installation +SKIP_WP_SETUP=false +# Skips cleanup after the test suite run. +SKIP_TESTS_CLEANUP=true +# The default Codeception suite to run. +SUITES=wpunit diff --git a/plugins/wpgraphql-logging/.gitignore b/plugins/wpgraphql-logging/.gitignore new file mode 100644 index 00000000..ab99ea50 --- /dev/null +++ b/plugins/wpgraphql-logging/.gitignore @@ -0,0 +1,57 @@ +# Hidden files +.DS_Store +Thumbs.db + +# IDE Files +.devcontainer/* +.devcontainer.json +.vscode +.idea + +# Environment variables for testing +.env +.env.* +!.env.dist + +# Ruleset Overrides +phpcs.xml +phpunit.xml +phpstan.neon + +# Directory to generate the dist zipfile +plugin-build + +# Composer auth +auth.json + +# Composer deps +vendor + +# NPM deps +node_modules + +# Generated Schema used in some tooling. Versioned Schema is uploaded as a Release artifact to Github. +schema.graphql + +# WP CLI config overrides +wp-cli.local.yml + +# Tests +*.sql +*.tar.gz +!tests +tests/*.suite.yml +coverage/* +build/ +.log/ +c3.php + +# Cache +phpcs-cache.json +tests/_support/ +tests/_output/ +tests/_generated/ +tests/_data/ + +# Playwright outputs +artifacts \ No newline at end of file diff --git a/plugins/wpgraphql-logging/CHANGELOG.md b/plugins/wpgraphql-logging/CHANGELOG.md new file mode 100644 index 00000000..4cae920c --- /dev/null +++ b/plugins/wpgraphql-logging/CHANGELOG.md @@ -0,0 +1,4 @@ +# WPGraphQL Logging + +## 0.0.1-beta +- Proof of concept. A plugin for logging data for WPGraphQL. diff --git a/plugins/wpgraphql-logging/LICENSE b/plugins/wpgraphql-logging/LICENSE new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/plugins/wpgraphql-logging/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/plugins/wpgraphql-logging/README.md b/plugins/wpgraphql-logging/README.md new file mode 100644 index 00000000..bbb2145b --- /dev/null +++ b/plugins/wpgraphql-logging/README.md @@ -0,0 +1,20 @@ +# WPGraphQL Logging + +A POC plugin for logging GraphQL requests using Monolog. + +* [Join the Headless WordPress community on Discord.](https://discord.gg/headless-wordpress-836253505944813629) +* [Documentation](#getting-started) + + +----- + +TODO + +----- + + + +> [!CAUTION] +> This plugin is currently is a POC and not production ready + +--- diff --git a/plugins/wpgraphql-logging/activation.php b/plugins/wpgraphql-logging/activation.php new file mode 100644 index 00000000..a9847faa --- /dev/null +++ b/plugins/wpgraphql-logging/activation.php @@ -0,0 +1,17 @@ +"$2" + elif [ $(which wget) ]; then + wget -nv -O "$2" "$1" + fi +} diff --git a/plugins/wpgraphql-logging/bin/build-docker.sh b/plugins/wpgraphql-logging/bin/build-docker.sh new file mode 100644 index 00000000..17a2b1b9 --- /dev/null +++ b/plugins/wpgraphql-logging/bin/build-docker.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -eu + +## +# Use this script through NPM scripts in the package.json, after installing the NPM and Composer Dependencies and updating the .env file. +## +print_usage_instructions() { + echo "Usage: ./build-docker.sh [OPTIONS]" + echo "Options:" + echo " -c Build without cache" + echo " -h Display this help message" + echo "" + echo "Example use:" + echo " npm run docker:build" + echo "" + echo " WP_VERSION=6.7 PHP_VERSION=8.2 npm run docker:build -- - c" + echo "" + echo " WP_VERSION=6.7 PHP_VERSION=8.2 bin/build-docker.sh -- c" + exit 1 +} + + +if [[ ! -f ".env" ]]; then + echo "No .env file was detected. .env.dist has been copied to .env" + echo "Open the .env file and enter values to match your local environment" + cp .env.dist .env +fi + +source .env + +while getopts ":ch" opt; do + case ${opt} in + c) + echo "Build with --no-cache" + BUILD_NO_CACHE=--no-cache + ;; + h) + print_usage_instructions + ;; + \?) + echo "Invalid flag: -$OPTARG" 1>&2 + exit 1 + ;; + *) + print_usage_instructions + ;; + esac +done + + +TAG=${TAG:-latest} +WP_VERSION=${WP_VERSION:-6.7} +PHP_VERSION=${PHP_VERSION:-8.2} + +BUILD_NO_CACHE=${BUILD_NO_CACHE:-} + +docker build $BUILD_NO_CACHE \ + -t "${PLUGIN_SLUG}:${TAG}-wp${WP_VERSION}-php${PHP_VERSION}" \ + --build-arg WP_VERSION="${WP_VERSION}" \ + --build-arg PHP_VERSION="${PHP_VERSION}" \ + ./.docker diff --git a/plugins/wpgraphql-logging/bin/install-plugins.sh b/plugins/wpgraphql-logging/bin/install-plugins.sh new file mode 100644 index 00000000..306debe6 --- /dev/null +++ b/plugins/wpgraphql-logging/bin/install-plugins.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Exit if any command fails. +set -e + +source ".env" + +# WPGraphQL +install_wpgraphql() { + if ! $( wp plugin is-installed wp-graphql --allow-root ); then + wp plugin install wp-graphql --allow-root + fi + wp plugin activate wp-graphql --allow-root +} + +# Run the install functions. +cd $WORDPRESS_ROOT_DIR + +install_wpgraphql diff --git a/plugins/wpgraphql-logging/bin/install-test-env.sh b/plugins/wpgraphql-logging/bin/install-test-env.sh new file mode 100644 index 00000000..d0da9ebc --- /dev/null +++ b/plugins/wpgraphql-logging/bin/install-test-env.sh @@ -0,0 +1,239 @@ +#!/usr/bin/env bash + +# Exit if any command fails. +set -e + +ORIGINAL_PATH=$(pwd) +BASEDIR=$(dirname "$0") + +# Include common environment variables and functions +source "${BASEDIR}/_lib.sh" + +# Common variables. +TMPDIR=${TMPDIR-/tmp} +TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//") + +WP_DEBUG=${WP_DEBUG:-true} +SCRIPT_DEBUG=${SCRIPT_DEBUG:-true} +WP_VERSION=${WP_VERSION:-"latest"} + +## +# Install the database. +## +install_db() { + if [ "${SKIP_DB_CREATE}" = "true" ]; then + return 0 + fi + + # parse DB_HOST for port or socket references + local PARTS=(${WORDPRESS_DB_HOST//\:/ }) + local DB_HOSTNAME=${PARTS[0]} + local DB_SOCK_OR_PORT=${PARTS[1]} + local EXTRA="" + + if ! [ -z $DB_HOSTNAME ]; then + if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then + EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" + elif ! [ -z $DB_SOCK_OR_PORT ]; then + EXTRA=" --socket=$DB_SOCK_OR_PORT" + elif ! [ -z $DB_HOSTNAME ]; then + EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" + fi + fi + + # create database + echo -e "$(status_message "Creating the database (if it does not exist)...")" + + RESULT=$(mysql -u $WORDPRESS_DB_USER --password="$WORDPRESS_DB_PASSWORD" --skip-column-names -e "SHOW DATABASES LIKE '$WORDPRESS_DB_NAME'"$EXTRA) + if [ "$RESULT" != $WORDPRESS_DB_NAME ]; then + mysqladmin create $WORDPRESS_DB_NAME --user="$WORDPRESS_DB_USER" --password="$WORDPRESS_DB_PASSWORD"$EXTRA + fi +} + +download() { + if [ $(which curl) ]; then + curl -s "$1" >"$2" + elif [ $(which wget) ]; then + wget -nv -O "$2" "$1" + fi +} + +install_wordpress() { + # Create the WordPress root directory if it doesn't exist. + echo -e "$(status_message "Switching to the WordPress root directory $WORDPRESS_ROOT_DIR")" + mkdir -p "$WORDPRESS_ROOT_DIR" + cd "$WORDPRESS_ROOT_DIR" || { echo -e "$(error_message "Failed to enter directory: $WORDPRESS_ROOT_DIR")"; exit 1; } + + # Download WordPress + if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then + mkdir -p $TMPDIR/wordpress-nightly + download https://wordpress.org/nightly-builds/wordpress-latest.zip $TMPDIR/wordpress-nightly/wordpress-nightly.zip + unzip -q $TMPDIR/wordpress-nightly/wordpress-nightly.zip -d $TMPDIR/wordpress-nightly/ + mv $TMPDIR/wordpress-nightly/wordpress/* $WORDPRESS_ROOT_DIR + else + if [ $WP_VERSION == 'latest' ]; then + local ARCHIVE_NAME='latest' + elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+ ]]; then + # https serves multiple offers, whereas http serves single. + download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + LATEST_VERSION=${WP_VERSION%??} + else + # otherwise, scan the releases and get the most up to date minor version of the major release + local VERSION_ESCAPED=$(echo $WP_VERSION | sed 's/\./\\\\./g') + LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1) + fi + if [[ -z "$LATEST_VERSION" ]]; then + local ARCHIVE_NAME="wordpress-$WP_VERSION" + else + local ARCHIVE_NAME="wordpress-$LATEST_VERSION" + fi + else + local ARCHIVE_NAME="wordpress-$WP_VERSION" + fi + download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz + tar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WORDPRESS_ROOT_DIR + fi +} + +configure_wordpress() { + if [ "${SKIP_WP_SETUP}" = "true" ]; then + echo -e "$(warning_message "Skipping WordPress setup...")" + return 0 + fi + + cd $WORDPRESS_ROOT_DIR + + # Create a wp-config.php file if it doesn't exist. + if [ ! -f "wp-config.php" ]; then + echo -e "$(status_message "Creating wp-config.php file...")" + wp config create --dbname="$WORDPRESS_DB_NAME" --dbuser="$WORDPRESS_DB_USER" --dbpass="$WORDPRESS_DB_PASSWORD" --dbhost="$WORDPRESS_DB_HOST" --dbprefix="$WORDPRESS_TABLE_PREFIX" --allow-root + fi + + # Install WordPress. + echo -e "$(status_message "Installing WordPress...")" + + SITE_TITLE=${WORDPRESS_SITE_TITLE:-"WPGraphQL Logging Tests"} + + wp core install --title="$SITE_TITLE" --admin_user="$WORDPRESS_ADMIN_USER" --admin_password="$WORDPRESS_ADMIN_PASSWORD" --admin_email="$WORDPRESS_ADMIN_EMAIL" --skip-email --url="$WORDPRESS_URL" --allow-root + + echo -e "$(status_message "Running WordPress version: $(wp core version --allow-root) at $(wp option get home --allow-root)")" +} + +setup_file_permissions() { + # Make sure the uploads and upgrade folders exist and we have permissions to add files. + echo -e "$(status_message "Ensuring that files can be uploaded...")" + + mkdir -p \ + wp-content/uploads \ + wp-content/upgrade + chmod 777 \ + wp-content \ + wp-content/plugins \ + wp-config.php \ + wp-settings.php \ + wp-content/uploads \ + wp-content/upgrade + + # Install a dummy favicon to avoid 404 errors. + echo -e "$(status_message "Installing a dummy favicon...")" + touch favicon.ico + chmod 767 favicon.ico +} + +setup_plugin() { + if [ "${SKIP_WP_SETUP}" = "true" ]; then + echo -e "$(warning_message "Skipping wpgraphql-Logging installation...")" + return 0 + fi + + # Add this repo as a plugin to the repo + if [ ! -d $WORDPRESS_ROOT_DIR/wp-content/plugins/wpgraphql-Logging ]; then + echo -e "$(status_message "Symlinking the plugin to the WordPress plugins directory...")" + + cd "$ORIGINAL_PATH" + ln -s "$(pwd)" "$WORDPRESS_ROOT_DIR/wp-content/plugins/$PLUGIN_SLUG" + fi + + cd "$ORIGINAL_PATH" + + # Install composer deps + echo -e "$(status_message "Installing Composer deps")" + composer install + + if [ -f "package.json" ]; then + # Install npm deps + echo -e "$(status_message "Installing NPM Deps")" + npm install --no-audit --no-fund --no-progress + + # Build the plugin + # npm run build + fi +} + +post_setup() { + # Ensure we are in the WordPress root directory. + cd "$WORDPRESS_ROOT_DIR" + + # Activate the plugin. + echo -e "$(status_message "Activating the plugin...")" + wp plugin activate "$PLUGIN_SLUG" --allow-root + + # Set pretty permalinks. + echo -e "$(status_message "Setting permalink structure...")" + wp rewrite structure '/%year%/%monthnum%/%postname%/' --hard --allow-root + wp rewrite flush --allow-root + + wp config set WP_DEBUG true --raw --allow-root + wp config set WP_DEBUG_LOG true --raw --allow-root + wp config set GRAPHQL_DEBUG true --raw --allow-root + + wp core update-db --allow-root + + # Disable Update Checks + echo -e "$(status_message "Disabling update checks...")" + wp config set WP_AUTO_UPDATE_CORE false --raw --type=constant --quiet --allow-root + wp config set AUTOMATIC_UPDATER_DISABLED true --raw --type=constant --quiet --allow-root + + # Export the db for codeception to use + SQLDUMP="$WORDPRESS_ROOT_DIR/wp-content/plugins/$PLUGIN_SLUG/tests/_data/dump.sql" + mkdir -p "$(dirname "$SQLDUMP")" + if [ ! -f "$SQLDUMP" ]; then + echo -e "$(status_message "Exporting test database dump...")" + + wp db export "$SQLDUMP" --allow-root + fi + + echo -e "$(status_message "Installed plugins")" + wp plugin list --allow-root +} + +## +# The main function to install the test environment. +## + +echo "Installing test environment for WordPress ${WP_VERSION}..." + +# Create the database if it doesn't exist. +install_db + +# If this is the test site, we reset the database so no posts/comments/etc. +# dirty up the tests. +if [ "$1" == '--reset-site' ]; then + echo -e "$(status_message "Resetting test database...")" + wp db reset --yes --quiet --allow-root +fi + +install_wordpress +configure_wordpress +setup_file_permissions + +# Plugins are in a separate script to keep things clean. +echo -e "$(status_message "Installing external plugins...")" +cd "$ORIGINAL_PATH" + +bash "$ORIGINAL_PATH/$BASEDIR/install-plugins.sh" + +setup_plugin +post_setup diff --git a/plugins/wpgraphql-logging/bin/local/run-e2e-tests.sh b/plugins/wpgraphql-logging/bin/local/run-e2e-tests.sh new file mode 100755 index 00000000..f0e260a8 --- /dev/null +++ b/plugins/wpgraphql-logging/bin/local/run-e2e-tests.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Run Playwright E2E tests for GitHub Actions + +set -e + +# Install dependencies if needed +npm ci + +# Install composer dependencies +composer install + +# Install Playwright browsers +npx playwright install --with-deps + +# Start wp-env +npm run wp-env start + +# Run Playwright tests +npm run test:e2e + +# Stop wp-env +npm run wp-env stop diff --git a/plugins/wpgraphql-logging/bin/local/run-qa.sh b/plugins/wpgraphql-logging/bin/local/run-qa.sh new file mode 100755 index 00000000..01449ba5 --- /dev/null +++ b/plugins/wpgraphql-logging/bin/local/run-qa.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Running PHP Code Quality Analysis locally +composer run check-cs +composer run phpstan +composer run php:psalm diff --git a/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh b/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh new file mode 100755 index 00000000..3742f9d8 --- /dev/null +++ b/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Running Unit Tests for the WPGraphQL Logging Plugin + +# Usage: +## - sh bin/local/run-unit-tests.sh +## - sh bin/local/run-unit-tests.sh coverage --coverage-html + +# Check if Docker is running +if ! docker info > /dev/null 2>&1; then + echo "Docker is not running. Please start Docker Desktop and try again." + open -a Docker + exit 1 +fi + +COVERAGE_ARG="" +COVERAGE_OUTPUT_ARG="" + +if [[ "$1" == "coverage" ]]; then + COVERAGE_ARG="-e COVERAGE=1" + shift + if [[ -n "$1" ]]; then + COVERAGE_OUTPUT_ARG="-e COVERAGE_OUTPUT=$1" + fi +fi + +docker exec $COVERAGE_ARG $COVERAGE_OUTPUT_ARG -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-Logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh diff --git a/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh b/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh new file mode 100644 index 00000000..1ae261e7 --- /dev/null +++ b/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e # Exit on any error + +echo "Setting up Docker environment..." + +# Copy environment file +if [ -f "bin/local/.env.local" ]; then + cp bin/local/.env.local .env + echo "✓ Environment file copied" +else + echo "❌ Error: bin/local/.env.local not found" + exit 1 +fi + +# Build and start containers +echo "Building and starting Docker containers..." +composer run docker:build +docker compose up -d + +# Wait for containers to be ready +echo "Waiting for containers to be ready..." +sleep 10 + +# Check if container is running +if ! docker ps | grep -q wpgraphql-logging-wordpress-1; then + echo "❌ Error: Container wpgraphql-logging-wordpress-1 is not running" + exit 1 +fi + +# Function to check if PHP extension is installed +check_extension() { + local extension=$1 + docker exec wpgraphql-logging-wordpress-1 php -m | grep -q "$extension" +} + +# Install coverage driver (prefer PCOV over XDebug for performance) +echo "Setting up code coverage driver..." + +if check_extension "pcov"; then + echo "✓ PCOV already installed and loaded" +elif check_extension "xdebug"; then + echo "✓ XDebug already installed and loaded" +else + echo "Checking if PCOV is installed but not enabled..." + + # Check if PCOV is installed via PECL but not enabled + if docker exec wpgraphql-logging-wordpress-1 pecl list | grep -q "pcov"; then + echo "PCOV is installed via PECL but not enabled. Enabling..." + docker exec wpgraphql-logging-wordpress-1 bash -c " + docker-php-ext-enable pcov && + echo 'pcov.enabled=1' >> /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini + " + + # Restart container to load the extension + echo "Restarting container to load PCOV..." + docker compose restart + sleep 10 + + if check_extension "pcov"; then + echo "✓ PCOV enabled successfully" + else + echo "❌ Failed to enable PCOV" + fi + else + echo "Installing PCOV for code coverage..." + docker exec wpgraphql-logging-wordpress-1 bash -c " + pecl install --force pcov 2>/dev/null || true && + docker-php-ext-enable pcov && + echo 'pcov.enabled=1' >> /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini + " + + # Restart container to load the extension + echo "Restarting container to load PCOV..." + docker compose restart + sleep 10 + + if check_extension "pcov"; then + echo "✓ PCOV installed and enabled successfully" + else + echo "⚠️ PCOV setup failed, trying XDebug..." + docker exec wpgraphql-logging-wordpress-1 bash -c " + pecl install --force xdebug 2>/dev/null || true && + docker-php-ext-enable xdebug && + echo 'xdebug.mode=coverage' >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini + " + + # Restart container to load the extension + echo "Restarting container to load XDebug..." + docker compose restart + sleep 10 + + if check_extension "xdebug"; then + echo "✓ XDebug installed and enabled successfully" + else + echo "❌ Failed to install both PCOV and XDebug" + exit 1 + fi + fi + fi +fi + +# Verify WordPress installation +echo "Checking WordPress installation..." +if docker exec wpgraphql-logging-wordpress-1 wp core is-installed --allow-root 2>/dev/null; then + echo "✓ WordPress is installed" +else + echo "Installing WordPress..." + docker exec wpgraphql-logging-wordpress-1 wp core install \ + --url=http://localhost \ + --title="Test Site" \ + --admin_user=admin \ + --admin_password=admin \ + --admin_email=admin@example.com \ + --allow-root + + if [ $? -eq 0 ]; then + echo "✓ WordPress installed successfully" + else + echo "❌ WordPress installation failed" + exit 1 + fi +fi + +# Install and activate the plugin if needed +echo "Checking plugin activation..." +if docker exec wpgraphql-logging-wordpress-1 wp plugin is-active wpgraphql-Logging --allow-root 2>/dev/null; then + echo "✓ Plugin is active" +else + echo "Activating plugin..." + docker exec wpgraphql-logging-wordpress-1 wp plugin activate wpgraphql-Logging --allow-root +fi + +# Verify coverage driver is working +echo "Verifying code coverage setup..." +if docker exec wpgraphql-logging-wordpress-1 php -r " + if (extension_loaded('pcov')) { + echo 'PCOV is available'; + exit(0); + } elseif (extension_loaded('xdebug')) { + echo 'XDebug is available'; + exit(0); + } else { + echo 'No coverage driver available'; + exit(1); + } +"; then + echo "✓ Code coverage driver is ready" +else + echo "❌ No code coverage driver available" + exit 1 +fi + +echo "" +echo "🎉 Docker environment setup complete!" +echo "" +echo "You can now run tests with:" +echo " docker exec -e COVERAGE=1 -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-Logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh" +echo "" +echo "Or without coverage:" +echo " docker exec -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-Logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh" diff --git a/plugins/wpgraphql-logging/bin/run-codeception.sh b/plugins/wpgraphql-logging/bin/run-codeception.sh new file mode 100755 index 00000000..b28eb7fe --- /dev/null +++ b/plugins/wpgraphql-logging/bin/run-codeception.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash + +ORIGINAL_PATH=$(pwd) +BASEDIR=$(dirname "$0") +PROJECT_DIR="$WORDPRESS_ROOT_DIR/wp-content/plugins/$PLUGIN_SLUG" + + +source "${BASEDIR}/_lib.sh" + +echo -e "$(status_message "WordPress: ${WP_VERSION} PHP: ${PHP_VERSION}")" + +## +# Set up before running tests. +## +setup_before() { + cd "$PROJECT_DIR" + + # Download c3 for testing. + if [ ! -f "c3.php" ]; then + echo "Downloading Codeception's c3.php" + curl -L 'https://raw.github.com/Codeception/c3/2.0/c3.php' > "c3.php" + fi + + # Set output permission + echo "Setting Codeception output directory permissions" + chmod 777 -R tests/_output +} + +## +# Run tests. +## +run_tests() { + if [[ -n "$DEBUG" ]]; then + local debug="--debug" + fi + + if [[ -n "$COVERAGE" ]]; then + if [[ -n "$COVERAGE_OUTPUT" ]]; then + local coverage="--coverage --coverage-xml $COVERAGE_OUTPUT" + else + local coverage="--coverage --coverage-xml $suites-coverage.xml" + fi + fi + + # If maintenance mode is active, de-activate it + if $(wp maintenance-mode is-active --allow-root); then + echo "Deactivating maintenance mode" + wp maintenance-mode deactivate --allow-root + fi + + echo "Running Unit and Integration tests" + cd "$PROJECT_DIR" + + # IMPORTANT: Build Codeception classes before running tests + echo "Building Codeception test classes" + vendor/bin/codecept build -c codeception.dist.yml + + if [ $? -ne 0 ]; then + echo "Error: Codeception build failed" + exit 1 + fi + + XDEBUG_MODE=coverage vendor/bin/codecept run -c codeception.dist.yml ${suites} ${coverage:-} ${debug:-} ${debug:-} + if [ $? -ne 0 ]; then + echo "Error: Codeception tests failed with exit code $?" + exit 1 + fi + + # Check code coverage if coverage was requested + if [[ -n "$COVERAGE" ]]; then + + if [[ -n "$COVERAGE_OUTPUT" ]]; then + coverage_percent=$(grep -oP '(\d+\.\d+)%' "tests/_output/coverage/index.html" | head -1 | tr -d '%') + else + coverage_percent=$(grep -oP 'line-rate="(\d+\.\d+)"' "tests/_output/coverage.xml" | head -1 | grep -oP '\d+\.\d+') + # Convert to percent + if [[ -n "$coverage_percent" ]]; then + coverage_percent=$(awk "BEGIN { printf \"%.2f\", $coverage_percent * 100 }") + fi + fi + if [[ -z "$coverage_percent" ]]; then + echo "Warning: Could not determine code coverage percentage." + exit 1 + fi + + echo "Code coverage percentage found: $coverage_percent" + + + required_coverage=$(grep 'min_coverage:' codeception.dist.yml | awk '{print $2}') + + if [[ -z "$required_coverage" ]]; then + echo "No min_coverage found in codeception.dist.yml. Defaulting to 80%" + required_coverage=80 + fi + + coverage_int=${coverage_percent%.*} + if (( coverage_int < required_coverage )); then + echo -e "\033[0;31mError: Code coverage is ${coverage_percent}%, which is below the required ${required_coverage}%.\033[0m" + exit 1 + else + echo -e "\033[0;32mCode coverage is ${coverage_percent}% (required: ${required_coverage}%)\033[0m" + fi + + fi + +} + +## +# Clean up after running tests. +## +cleanup_after() { + cd "$PROJECT_DIR" + + # Remove c3.php if it exists and cleanup is not skipped + if [ -f "c3.php" ] && [ "$SKIP_TESTS_CLEANUP" != "true" ]; then + echo "Removing Codeception's c3.php" + rm "c3.php" + fi + + # Disable XDebug or PCOV if they were enabled for code coverage + if [[ "$COVERAGE" == '1' ]]; then + if [[ "$USING_XDEBUG" == '1' ]]; then + echo "Disabling XDebug 3" + rm /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini + else98 + echo "Disabling pcov/clobber" + docker-php-ext-disable pcov + sed -i '/pcov.enabled=1/d' /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini + sed -i '/pcov.directory=${PROJECT_DIR}/d' /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini + fi + fi + + # Set output permission back to default + echo "Resetting Codeception output directory permissions" + chmod 777 -R tests/_output +} + +# Prepare to run tests. +echo "Setting up for Codeception tests" +setup_before + +run_tests + +# Clean up after running tests. +echo "Cleaning up after Codeception tests" +cleanup_after + +# Check results and exit accordingly. +if [ -f "tests/_output/failed" ]; then + echo "Codeception tests failed." + exit 1 +else + echo "Codeception tests completed successfully!" +fi diff --git a/plugins/wpgraphql-logging/bin/sync-package-version.sh b/plugins/wpgraphql-logging/bin/sync-package-version.sh new file mode 100755 index 00000000..e5bbed5b --- /dev/null +++ b/plugins/wpgraphql-logging/bin/sync-package-version.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Exit on any error +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Get the version from package.json +VERSION=$(node -p "require('./package.json').version") + +if [ -z "$VERSION" ]; then + echo -e "${RED}Error: Could not read version from package.json${NC}" + exit 1 +fi + +echo -e "${YELLOW}Syncing version ${VERSION} across all files...${NC}" + +# Update composer.json +if [ -f "composer.json" ]; then + echo "Updating composer.json..." + # Use sed to preserve original formatting (tabs/spaces) + sed -i.bak -E "s/(\"version\":[[:space:]]*\")[^\"]*(\",?)/\1$VERSION\2/" composer.json && rm composer.json.bak + echo -e "${GREEN}✓ Updated composer.json${NC}" +else + echo -e "${YELLOW}⚠ composer.json not found${NC}" +fi + +# Update readme.txt (WordPress style) +if [ -f "readme.txt" ]; then + echo "Updating readme.txt..." + sed -i.bak -E "s/(Stable tag:|Version:)[[:space:]]*[0-9]+\.[0-9]+\.[0-9]+/\1 $VERSION/g" readme.txt && rm readme.txt.bak + echo -e "${GREEN}✓ Updated readme.txt${NC}" +else + echo -e "${YELLOW}⚠ readme.txt not found${NC}" +fi + +# Update wpgraphql-logging.php +PLUGIN_FILE="wpgraphql-logging.php" + +if [ -f "$PLUGIN_FILE" ]; then + echo "Updating main plugin file: $PLUGIN_FILE..." + + # Update WordPress plugin header version (handles beta versions) + sed -i.bak -E "s/(\* Version:[[:space:]]*)[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?/\1$VERSION/g" "$PLUGIN_FILE" && rm "${PLUGIN_FILE}.bak" + + # Update WPGRAPHQL_LOGGING_VERSION define statement + sed -i.bak -E "s/(define\([[:space:]]*['\"]WPGRAPHQL_LOGGING_VERSION['\"][[:space:]]*,[[:space:]]*['\"])[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?(['\"][[:space:]]*\))/\1$VERSION\3/g" "$PLUGIN_FILE" && rm "${PLUGIN_FILE}.bak" + + echo -e "${GREEN}✓ Updated $PLUGIN_FILE${NC}" +else + echo -e "${YELLOW}⚠ $PLUGIN_FILE not found${NC}" +fi + +echo -e "${GREEN}✅ Version sync complete! All files updated to version ${VERSION}${NC}" +echo -e "${YELLOW}Files will be staged by the workflow's 'git add .' command${NC}"`` diff --git a/plugins/wpgraphql-logging/codeception.dist.yml b/plugins/wpgraphql-logging/codeception.dist.yml new file mode 100644 index 00000000..81f76e6c --- /dev/null +++ b/plugins/wpgraphql-logging/codeception.dist.yml @@ -0,0 +1,103 @@ +paths: + tests: tests + output: tests/_output + data: tests/_data + support: tests/_support + envs: tests/_envs +actor_suffix: Tester +params: + - .env +settings: + colors: true + memory_limit: 1024M +extensions: + enabled: + - Codeception\Extension\RunFailed + commands: + - lucatume\WPBrowser\Command\DbExport + - lucatume\WPBrowser\Command\DbImport + - lucatume\WPBrowser\Command\DevInfo + - lucatume\WPBrowser\Command\DevRestart + - lucatume\WPBrowser\Command\DevStart + - lucatume\WPBrowser\Command\DevStop + - lucatume\WPBrowser\Command\GenerateWPAjax + - lucatume\WPBrowser\Command\GenerateWPCanonical + - lucatume\WPBrowser\Command\GenerateWPRestApi + - lucatume\WPBrowser\Command\GenerateWPRestController + - lucatume\WPBrowser\Command\GenerateWPRestPostTypeController + - lucatume\WPBrowser\Command\GenerateWPUnit + - lucatume\WPBrowser\Command\GenerateWPXMLRPC + - lucatume\WPBrowser\Command\MonkeyCacheClear + - lucatume\WPBrowser\Command\MonkeyCachePath + - lucatume\WPBrowser\Command\RunAll + - lucatume\WPBrowser\Command\RunOriginal +exclude: + - src/Templates + - src/Templates/* +coverage: + enabled: true + remote: false + c3_url: "%WORDPRESS_URL%/wp-content/plugins/wpgraphql-logging/wpgraphql-logging.php" + include: + - src/* + - /activation.php + - /deactivation.php + exclude: + - /bin/* + - /docs/* + - /node_modules/* + - /packages/* + - /tests/* + - /vendor/* + - /src/Templates/* + show_only_summary: true + min_coverage: 10 #TODO change +modules: + config: + REST: + depends: lucatume\WPBrowser\Module\WPBrowser + url: "%WORDPRESS_URL%" + lucatume\WPBrowser\Module\WPFilesystem: + wpRootFolder: '%WORDPRESS_ROOT_DIR%' + themes: '/wp-content/themes' + plugins: '/wp-content/plugins' + mu-plugins: '/wp-content/mu-plugins' + uploads: '/wp-content/uploads' + lucatume\WPBrowser\Module\WPBrowser: + url: '%WORDPRESS_URL%' + adminUsername: '%WORDPRESS_ADMIN_USER%' + adminPassword: '%WORDPRESS_ADMIN_PASSWORD%' + adminPath: '/wp-admin' + headers: + X_WPBROWSER_REQUEST: 1 + X_TEST_REQUEST: 1 + X_APM_REQUEST: 1 + connect_timeout: 3 + cookies: false + lucatume\WPBrowser\Module\WPDb: + dsn: "%TEST_DB_DSN%" + user: "%TEST_DB_USER%" + password: "%TEST_DB_PASSWORD%" + populator: 'mysql -u $user -p$password -h $host $dbname < $dump' + dump: 'tests/_data/dump.sql' + populate: true + cleanup: true + waitlock: 0 + url: "%WORDPRESS_URL%" + urlReplacement: true + tablePrefix: "%WORDPRESS_TABLE_PREFIX%" + lucatume\WPBrowser\Module\WPLoader: + wpRootFolder: "%WORDPRESS_ROOT_DIR%" + dbName: "%TEST_DB_NAME%" + dbHost: "%TEST_DB_HOST%" + dbUser: "%TEST_DB_USER%" + dbPassword: "%TEST_DB_PASSWORD%" + tablePrefix: "%TEST_TABLE_PREFIX%" + domain: "%WORDPRESS_DOMAIN%" + adminEmail: "%WORDPRESS_ADMIN_EMAIL%" + title: 'Test' + plugins: + - wpgraphql-logging/wpgraphql-logging.php + activatePlugins: + - wpgraphql-logging/wpgraphql-logging.php + configFile: 'tests/_data/config.php' diff --git a/plugins/wpgraphql-logging/composer.json b/plugins/wpgraphql-logging/composer.json new file mode 100644 index 00000000..d436cd03 --- /dev/null +++ b/plugins/wpgraphql-logging/composer.json @@ -0,0 +1,165 @@ +{ + "name": "wpengine/wpgraphql-logging", + "type": "wordpress-plugin", + "description": "A POC plugin for logging WPGraphQL queries.", + "license": "GPL-2.0", + "version": "0.0.1", + "authors": [ + { + "name": "WP Engine Headless OSS Development Team", + "email": "headless-oss@wpengine.com", + "homepage": "https://wpengine.com/" + } + ], + "keywords": [ + "package", + "dependency", + "autoload", + "headless", + "wordpress", + "plugin", + "wpgraphql", + "performance", + "graphql", + "logging", + "wpgraphql-logging", + "monolog" + ], + "require": { + "php": "^7.4 || ^8.0", + "monolog/monolog": "^2.10" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "require-dev": { + "10up/wp_mock": "^1.1", + "automattic/vipwpcs": "^3.0", + "codeception/lib-innerbrowser": "^1.0", + "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-rest": "^2.0", + "codeception/module-webdriver": "^1.0", + "codeception/util-universalframework": "^1.0", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "humanmade/psalm-plugin-wordpress": "^3.1", + "johnpbloch/wordpress-core": "^6.8", + "lucatume/wp-browser": "^3.5", + "mockery/mockery": "^1.5", + "phpcompatibility/php-compatibility": "dev-develop as 9.99.99", + "phpcompatibility/phpcompatibility-wp": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "slevomat/coding-standard": "^8.0", + "szepeviktor/phpstan-wordpress": "^2.0", + "wp-cli/wp-cli-bundle": "^2.8.1", + "wp-graphql/wp-graphql-testcase": "^3.0.1" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + }, + "optimize-autoloader": true, + "platform": { + "php": "7.4" + }, + "preferred-install": "dist", + "sort-packages": true + }, + "extra": { + "phpstan": { + "includes": [ + "phpstan/rules.neon" + ] + } + }, + "archive": { + "name": "wpgraphql-logging", + "exclude": [ + "/.DS_Store", + "/.docker/", + "/.env.dist", + "/ACTIONS_AND_FILTERS.md", + "/TESTING.md", + "/Thumbs.db", + "/artifacts", + "/auth.json", + "/bin", + "/c3.php", + "/codeception.dist.yml", + "/docker", + "/docker-compose.yml", + "/docs", + "/examples", + "/node_modules", + "/package-lock.json", + "/package.json", + "/phpcs", + "/phpcs-cache.json", + "/phpcs.xml", + "/phpstan", + "/phpstan.neon.dist", + "/plugin-build", + "/psalm.xml", + "/screenshots", + "/tests", + "!vendor", + "!vendor-prefixed" + ] + }, + "autoload": { + "psr-4": { + "WPGraphQL\\Logging\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "WPGraphQL\\Logging\\Unit\\": "tests/unit/", + "WPGraphQL\\Logging\\Functional\\": "tests/functional/", + "WPGraphQL\\Logging\\Integration\\": "tests/integration/", + "WPGraphQL\\Logging\\PHPStan\\": "phpstan/", + "HWPStandard\\": "phpcs/HWPStandard" + } + }, + "scripts": { + "install-test-env": "bash bin/install-test-env.sh", + "delete-vendor-files": "rm -rf composer.lock vendor src/vendor-prefixed/*", + "docker:build": "bash bin/build-docker.sh", + "docker:start": "@docker:build && @docker:up", + "docker:stop": "docker compose down --volumes", + "docker:up": " sh -c 'composer docker:stop' && docker compose --env-file .env up --detach", + "lint": "vendor/bin/phpcs", + "phpcs-i": [ + "php ./vendor/bin/phpcs -i" + ], + "check-cs": [ + "php ./vendor/bin/phpcs" + ], + "fix-cs": [ + "php ./vendor/bin/phpcbf" + ], + "phpstan": [ + "vendor/bin/phpstan analyze --ansi --memory-limit=1G" + ], + "php:psalm": "psalm", + "php:psalm:info": "psalm --show-info=true", + "php:psalm:fix": "psalm --alter", + "qa": "sh bin/local/run-qa.sh", + "test": [ + "sh bin/local/run-unit-tests.sh coverage", + "sh bin/local/run-e2e-tests.sh" + ], + "test:unit:coverage": "sh bin/local/run-unit-tests.sh coverage", + "test:unit:coverage-html": "sh bin/local/run-unit-tests.sh coverage --coverage-html", + "test:e2e": "sh bin/local/run-e2e-tests.sh" + }, + "support": { + "docs": "https://github.com/wpengine/hwptoolkit/tree/main/docs", + "email": "headless-oss@wpengine.com", + "forum": "https://github.com/wpengine/hwptoolkit/discussions", + "issues": "https://github.com/wpengine/hwptoolkit/issues", + "security": "https://github.com/wpengine/hwptoolkit/blob/main/SECURITY.md" + } +} diff --git a/plugins/wpgraphql-logging/composer.lock b/plugins/wpgraphql-logging/composer.lock new file mode 100644 index 00000000..8aa2b41d --- /dev/null +++ b/plugins/wpgraphql-logging/composer.lock @@ -0,0 +1,11377 @@ +{ + "_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": "68a7287de858f7c3a959e784310ef04d", + "packages": [ + { + "name": "monolog/monolog", + "version": "2.10.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "5cf826f2991858b54d5c3809bee745560a1042a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5cf826f2991858b54d5c3809bee745560a1042a7", + "reference": "5cf826f2991858b54d5c3809bee745560a1042a7", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.38 || ^9.6.19", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.10.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2024-11-12T12:43:37+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" + } + ], + "packages-dev": [ + { + "name": "10up/wp_mock", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/10up/wp_mock.git", + "reference": "f25b5895ed31bf5e7036fe0c666664364ae011c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/10up/wp_mock/zipball/f25b5895ed31bf5e7036fe0c666664364ae011c2", + "reference": "f25b5895ed31bf5e7036fe0c666664364ae011c2", + "shasum": "" + }, + "require": { + "antecedent/patchwork": "^2.1", + "mockery/mockery": "^1.6", + "php": ">=7.4 < 9", + "phpunit/phpunit": "^9.6" + }, + "require-dev": { + "behat/behat": "^v3.11.0", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "friendsofphp/php-cs-fixer": "^3.4", + "php-coveralls/php-coveralls": "^v2.7", + "php-stubs/wordpress-globals": "^0.2", + "php-stubs/wordpress-stubs": "^6.3", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "sebastian/comparator": "^4.0.8", + "sempro/phpunit-pretty-print": "^1.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "WP_Mock\\": "./php/WP_Mock" + }, + "classmap": [ + "php/WP_Mock.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "A mocking library to take the pain out of unit testing for WordPress", + "support": { + "issues": "https://github.com/10up/wp_mock/issues", + "source": "https://github.com/10up/wp_mock/tree/1.1.0" + }, + "time": "2025-03-12T00:36:13+00:00" + }, + { + "name": "amphp/amp", + "version": "v2.6.4", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "react/promise": "^2", + "vimeo/psalm": "^3.12" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T18:52:26+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.8.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" + }, + "type": "library", + "autoload": { + "files": [ + "lib/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-13T18:00:56+00:00" + }, + { + "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": "automattic/vipwpcs", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/Automattic/VIP-Coding-Standards.git", + "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/2b1d206d81b74ed999023cffd924f862ff2753c8", + "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsextra": "^1.2.1", + "phpcsstandards/phpcsutils": "^1.0.11", + "sirbrillig/phpcs-variable-analysis": "^2.11.18", + "squizlabs/php_codesniffer": "^3.9.2", + "wp-coding-standards/wpcs": "^3.1.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^9", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7 || ^8 || ^9" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", + "keywords": [ + "phpcs", + "standards", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", + "source": "https://github.com/Automattic/VIP-Coding-Standards", + "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" + }, + "time": "2024-05-10T20:31:09+00:00" + }, + { + "name": "behat/gherkin", + "version": "v4.10.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "cbb83c4c435dd8d05a161f2a5ae322e61b2f4db6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/cbb83c4c435dd8d05a161f2a5ae322e61b2f4db6", + "reference": "cbb83c4c435dd8d05a161f2a5ae322e61b2f4db6", + "shasum": "" + }, + "require": { + "php": "~7.2|~8.0" + }, + "require-dev": { + "cucumber/cucumber": "dev-gherkin-24.1.0", + "phpunit/phpunit": "~8|~9", + "symfony/yaml": "~3|~4|~5|~6|~7" + }, + "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.10.0" + }, + "time": "2024-10-19T14:46:06+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-rest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-rest.git", + "reference": "ee4ea06cd8a5057f24f37f8bf25b6815ddc77840" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-rest/zipball/ee4ea06cd8a5057f24f37f8bf25b6815ddc77840", + "reference": "ee4ea06cd8a5057f24f37f8bf25b6815ddc77840", + "shasum": "" + }, + "require": { + "codeception/codeception": "^4.1", + "ext-dom": "*", + "ext-json": "*", + "justinrainbow/json-schema": "~5.2.9", + "php": "^7.4 | ^8.0", + "softcreatr/jsonpath": "^0.5 | ^0.7 | ^0.8" + }, + "require-dev": { + "codeception/lib-innerbrowser": "^2.0", + "codeception/stub": "^4.0", + "codeception/util-universalframework": "^1.0" + }, + "suggest": { + "aws/aws-sdk-php": "For using AWS Auth" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gintautas Miselis" + } + ], + "description": "REST module for Codeception", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception", + "rest" + ], + "support": { + "issues": "https://github.com/Codeception/module-rest/issues", + "source": "https://github.com/Codeception/module-rest/tree/2.0.3" + }, + "time": "2023-03-10T19:23:22+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" + }, + "abandoned": true, + "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.7", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "d665d22c417056996c59019579f1967dfe5c1e82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/d665d22c417056996c59019579f1967dfe5c1e82", + "reference": "d665d22c417056996c59019579f1967dfe5c1e82", + "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.7" + }, + "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": "2025-05-26T15:08:54+00:00" + }, + { + "name": "composer/class-map-generator", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/composer/class-map-generator.git", + "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/134b705ddb0025d397d8318a75825fe3c9d1da34", + "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34", + "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.6.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2025-03-24T13:50:44+00:00" + }, + { + "name": "composer/composer", + "version": "2.7.7", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "291942978f39435cf904d33739f98d7d4eca7b23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/291942978f39435cf904d33739f98d7d4eca7b23", + "reference": "291942978f39435cf904d33739f98d7d4eca7b23", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "composer/class-map-generator": "^1.3.3", + "composer/metadata-minifier": "^1.0", + "composer/pcre": "^2.1 || ^3.1", + "composer/semver": "^3.3", + "composer/spdx-licenses": "^1.5.7", + "composer/xdebug-handler": "^2.0.2 || ^3.0.3", + "justinrainbow/json-schema": "^5.2.11", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "react/promise": "^2.8 || ^3", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.2", + "seld/signal-handler": "^2.0", + "symfony/console": "^5.4.11 || ^6.0.11 || ^7", + "symfony/filesystem": "^5.4 || ^6.0 || ^7", + "symfony/finder": "^5.4 || ^6.0 || ^7", + "symfony/polyfill-php73": "^1.24", + "symfony/polyfill-php80": "^1.24", + "symfony/polyfill-php81": "^1.24", + "symfony/process": "^5.4 || ^6.0 || ^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.11.0", + "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.1 || ^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.7-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.7.7" + }, + "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-06-10T20:11:12+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": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/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.9", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "edf364cefe8c43501e21e88110aac10b284c3c9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/edf364cefe8c43501e21e88110aac10b284c3c9f", + "reference": "edf364cefe8c43501e21e88110aac10b284c3c9f", + "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": "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.9" + }, + "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": "2025-05-12T21:07:07+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": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "6e0fa428497bf560152ee73ffbb8af5c6a56b0dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/6e0fa428497bf560152ee73ffbb8af5c6a56b0dd", + "reference": "6e0fa428497bf560152ee73ffbb8af5c6a56b0dd", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.2", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "^2.2", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-06-27T17:24:01+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "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.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^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/1.5.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:15:36+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": "felixfbecker/advanced-json-rpc", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "php": "^7.1 || ^8.0", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + }, + "time": "2021-06-11T22:34:44+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.3", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/a9e113dbc7d849e35b8776da39edaf4313b7b6c9", + "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.3" + }, + "time": "2024-04-30T00:40:11+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-08-06T10:04:20+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.12.1", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/Languages.git", + "reference": "0b0b0851c55168e1dfb14305735c64019732b5f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/Languages/zipball/0b0b0851c55168e1dfb14305735c64019732b5f1", + "reference": "0b0b0851c55168e1dfb14305735c64019732b5f1", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4" + }, + "bin": [ + "bin/export-plural-rules", + "bin/import-cldr-data" + ], + "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.12.1" + }, + "funding": [ + { + "url": "https://paypal.me/mlocati", + "type": "custom" + }, + { + "url": "https://github.com/mlocati", + "type": "github" + } + ], + "time": "2025-03-19T11:14:02+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "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.3" + }, + "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": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "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.2.0" + }, + "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": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "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.1" + }, + "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": "2025-03-27T12:30:47+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "humanmade/psalm-plugin-wordpress", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/psalm/psalm-plugin-wordpress.git", + "reference": "3f4689ad5264eee7b37121053cec810a3754f7e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/psalm/psalm-plugin-wordpress/zipball/3f4689ad5264eee7b37121053cec810a3754f7e4", + "reference": "3f4689ad5264eee7b37121053cec810a3754f7e4", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "php-stubs/wordpress-globals": "^0.2.0", + "php-stubs/wordpress-stubs": "^6.0", + "php-stubs/wp-cli-stubs": "^2.7", + "vimeo/psalm": "^5 || ^6", + "wp-hooks/wordpress-core": "^1.3.0" + }, + "require-dev": { + "humanmade/coding-standards": "^1.2", + "phpunit/phpunit": "^9.0", + "psalm/plugin-phpunit": "^0.18.4" + }, + "type": "psalm-plugin", + "extra": { + "psalm": { + "pluginClass": "PsalmWordPress\\Plugin" + } + }, + "autoload": { + "psr-4": { + "PsalmWordPress\\": [ + "." + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "kkmuffme", + "role": "Maintainer" + }, + { + "name": "Joe Hoyle", + "role": "Creator" + } + ], + "description": "WordPress stubs and plugin for Psalm static analysis.", + "support": { + "issues": "https://github.com/psalm/psalm-plugin-wordpress/issues", + "source": "https://github.com/psalm/psalm-plugin-wordpress" + }, + "time": "2024-04-01T10:36:11+00:00" + }, + { + "name": "ifsnop/mysqldump-php", + "version": "v2.12", + "source": { + "type": "git", + "url": "https://github.com/ifsnop/mysqldump-php.git", + "reference": "2d3a43fc0c49f23bf7dee392b0dd1f8c799f89d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ifsnop/mysqldump-php/zipball/2d3a43fc0c49f23bf7dee392b0dd1f8c799f89d3", + "reference": "2d3a43fc0c49f23bf7dee392b0dd1f8c799f89d3", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.8.36", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ifsnop\\": "src/Ifsnop/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-or-later" + ], + "authors": [ + { + "name": "Diego Torres", + "homepage": "https://github.com/ifsnop", + "role": "Developer" + } + ], + "description": "PHP version of mysqldump cli that comes with MySQL", + "homepage": "https://github.com/ifsnop/mysqldump-php", + "keywords": [ + "PHP7", + "database", + "hhvm", + "mariadb", + "mysql", + "mysql-backup", + "mysqldump", + "pdo", + "php", + "php5", + "sql" + ], + "support": { + "issues": "https://github.com/ifsnop/mysqldump-php/issues", + "source": "https://github.com/ifsnop/mysqldump-php/tree/v2.12" + }, + "time": "2023-04-12T07:43:14+00:00" + }, + { + "name": "johnpbloch/wordpress-core", + "version": "6.8.1", + "source": { + "type": "git", + "url": "https://github.com/johnpbloch/wordpress-core.git", + "reference": "702c3bda87abb47ae43f90c7b8868cf0b7dff1e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/702c3bda87abb47ae43f90c7b8868cf0b7dff1e2", + "reference": "702c3bda87abb47ae43f90c7b8868cf0b7dff1e2", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2.24" + }, + "provide": { + "wordpress/core-implementation": "6.8.1" + }, + "type": "wordpress-core", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "WordPress Community", + "homepage": "https://wordpress.org/about/" + } + ], + "description": "WordPress is open source software you can use to create a beautiful website, blog, or app.", + "homepage": "https://wordpress.org/", + "keywords": [ + "blog", + "cms", + "wordpress" + ], + "support": { + "forum": "https://wordpress.org/support/", + "irc": "irc://irc.freenode.net/wordpress", + "issues": "https://core.trac.wordpress.org/", + "source": "https://core.trac.wordpress.org/browser", + "wiki": "https://codex.wordpress.org/" + }, + "time": "2025-04-30T16:52:49+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "v5.2.13", + "source": { + "type": "git", + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793", + "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "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", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "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/v5.2.13" + }, + "time": "2023-09-26T02:20:38+00:00" + }, + { + "name": "lucatume/wp-browser", + "version": "3.7.13", + "source": { + "type": "git", + "url": "https://github.com/lucatume/wp-browser.git", + "reference": "b08d668b44d4a840189b5cb3ba690aa56f5b4f3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lucatume/wp-browser/zipball/b08d668b44d4a840189b5cb3ba690aa56f5b4f3f", + "reference": "b08d668b44d4a840189b5cb3ba690aa56f5b4f3f", + "shasum": "" + }, + "require": { + "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", + "composer-runtime-api": "^2.2", + "ext-curl": "*", + "ext-fileinfo": "*", + "ext-json": "*", + "ext-mysqli": "*", + "ext-pdo": "*", + "ext-zip": "*", + "ifsnop/mysqldump-php": "^2.12", + "php": ">=7.1 <8.0", + "symfony/filesystem": ">=3.4.47 <7.0", + "symfony/process": ">=3.4.47 <7.0", + "vlucas/phpdotenv": "^4.3" + }, + "require-dev": { + "gumlet/php-image-resize": "^1.6", + "lucatume/codeception-snapshot-assertions": "^0.4", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan-symfony": "^0.12.44", + "squizlabs/php_codesniffer": "^3.7", + "szepeviktor/phpstan-wordpress": "^0.7" + }, + "suggest": { + "ext-pdo_sqlite": "For SQLite database support.", + "ext-sqlite3": "For SQLite database support." + }, + "type": "library", + "extra": { + "_hash": "484f861f69198089cab0e642f27e5653" + }, + "autoload": { + "files": [ + "src/version-4-aliases.php", + "src/Deprecated/deprecated-functions.php", + "src/functions.php", + "src/shim.php" + ], + "psr-4": { + "Hautelook\\Phpass\\": "includes/Hautelook/Phpass", + "lucatume\\WPBrowser\\": [ + "src/", + "src/Deprecated" + ], + "lucatume\\WPBrowser\\Opis\\Closure\\": "includes/opis/closure/src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "theAverageDev (Luca Tumedei)", + "email": "luca@theaveragedev.com", + "homepage": "https://theaveragedev.com", + "role": "Developer" + } + ], + "description": "A set of Codeception modules to test WordPress projects.", + "homepage": "https://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.7.13" + }, + "funding": [ + { + "url": "https://github.com/lucatume", + "type": "github" + } + ], + "time": "2025-06-20T08:50:06+00:00" + }, + { + "name": "mck89/peast", + "version": "v1.17.2", + "source": { + "type": "git", + "url": "https://github.com/mck89/peast.git", + "reference": "465810689c477fbba17f4f949b75e4d0bdab13ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mck89/peast/zipball/465810689c477fbba17f4f949b75e4d0bdab13ea", + "reference": "465810689c477fbba17f4f949b75e4d0bdab13ea", + "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.17.2-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.17.2" + }, + "time": "2025-07-01T09:30:45+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", + "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.13.3" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-07-05T12:25:42+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": "netresearch/jsonmapper", + "version": "v4.5.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8e76efb98ee8b6afc54687045e1b8dba55ac76e5", + "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.5.0" + }, + "time": "2024-09-08T10:13:13+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": "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-extended/polyfill-php80-str-utils", + "version": "1.3.7", + "source": { + "type": "git", + "url": "https://gitlab.com/php-extended/polyfill-php80-str-utils.git", + "reference": "0749426252e3e27c526fda939e8d3ff050bf907b" + }, + "dist": { + "type": "zip", + "url": "https://gitlab.com/api/v4/projects/php-extended%2Fpolyfill-php80-str-utils/repository/archive.zip?sha=0749426252e3e27c526fda939e8d3ff050bf907b", + "reference": "0749426252e3e27c526fda939e8d3ff050bf907b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "php-extended/placeholder-phpunit": "^9" + }, + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "PhpExtended\\Polyfill\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anastaszor", + "homepage": "https://gitlab.com/Anastaszor", + "role": "developer" + } + ], + "description": "A php implementation of string functions introduced in php8 and above", + "homepage": "https://gitlab.com/php-extended/polyfill-str-utils", + "keywords": [ + "implementation", + "php", + "polyfill", + "str", + "string_ends_with", + "string_starts_with", + "utils" + ], + "support": { + "issues": "https://gitlab.com/php-extended/polyfill-str-utils/issues", + "source": "https://gitlab.com/php-extended/polyfill-str-utils" + }, + "abandoned": "php >= 8.0", + "time": "2024-03-31T13:28:10+00:00" + }, + { + "name": "php-stubs/wordpress-globals", + "version": "v0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wordpress-globals.git", + "reference": "748a1fb2ae8fda94844bd0545935095dbf404b32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wordpress-globals/zipball/748a1fb2ae8fda94844bd0545935095dbf404b32", + "reference": "748a1fb2ae8fda94844bd0545935095dbf404b32", + "shasum": "" + }, + "require-dev": { + "php": "~7.1" + }, + "suggest": { + "php-stubs/wordpress-stubs": "Up-to-date WordPress function and class declaration stubs", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Global variables and global constants from WordPress core.", + "homepage": "https://github.com/php-stubs/wordpress-globals", + "keywords": [ + "PHPStan", + "constants", + "globals", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/php-stubs/wordpress-globals/issues", + "source": "https://github.com/php-stubs/wordpress-globals/tree/master" + }, + "time": "2020-01-13T06:12:59+00:00" + }, + { + "name": "php-stubs/wordpress-stubs", + "version": "v6.8.1", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wordpress-stubs.git", + "reference": "92e444847d94f7c30f88c60004648f507688acd5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/92e444847d94f7c30f88c60004648f507688acd5", + "reference": "92e444847d94f7c30f88c60004648f507688acd5", + "shasum": "" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "5.6.1" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "nikic/php-parser": "^5.4", + "php": "^7.4 || ^8.0", + "php-stubs/generator": "^0.8.3", + "phpdocumentor/reflection-docblock": "^5.4.1", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^9.5", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" + }, + "suggest": { + "paragonie/sodium_compat": "Pure PHP implementation of libsodium", + "symfony/polyfill-php80": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WordPress function and class declaration stubs for static analysis.", + "homepage": "https://github.com/php-stubs/wordpress-stubs", + "keywords": [ + "PHPStan", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/php-stubs/wordpress-stubs/issues", + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.8.1" + }, + "time": "2025-05-02T12:33:34+00:00" + }, + { + "name": "php-stubs/wp-cli-stubs", + "version": "v2.12.0", + "source": { + "type": "git", + "url": "https://github.com/php-stubs/wp-cli-stubs.git", + "reference": "af16401e299a3fd2229bd0fa9a037638a4174a9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-stubs/wp-cli-stubs/zipball/af16401e299a3fd2229bd0fa9a037638a4174a9d", + "reference": "af16401e299a3fd2229bd0fa9a037638a4174a9d", + "shasum": "" + }, + "require": { + "php-stubs/wordpress-stubs": "^4.7 || ^5.0 || ^6.0" + }, + "require-dev": { + "php": "~7.3 || ~8.0", + "php-stubs/generator": "^0.8.0" + }, + "suggest": { + "symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WP-CLI function and class declaration stubs for static analysis.", + "homepage": "https://github.com/php-stubs/wp-cli-stubs", + "keywords": [ + "PHPStan", + "static analysis", + "wordpress", + "wp-cli" + ], + "support": { + "issues": "https://github.com/php-stubs/wp-cli-stubs/issues", + "source": "https://github.com/php-stubs/wp-cli-stubs/tree/v2.12.0" + }, + "time": "2025-06-10T09:58: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": "phpcompatibility/php-compatibility", + "version": "dev-develop", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "5e207bcca923a6afd5a8084427cb43a37bf306d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/5e207bcca923a6afd5a8084427cb43a37bf306d3", + "reference": "5e207bcca923a6afd5a8084427cb43a37bf306d3", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.0" + }, + "replace": { + "wimg/php-compatibility": "*" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.1.3", + "phpcsstandards/phpcsdevtools": "^1.2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4 || ^10.1.0", + "yoast/phpunit-polyfills": "^1.0.5 || ^2.0.0" + }, + "suggest": { + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "default-branch": true, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev", + "dev-develop": "10.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "https://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibility/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" + }, + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-07-06T15:59:37+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "1.3.3", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-04-24T21:30:46+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-wp", + "version": "2.1.7", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "5bfbbfbabb3df2b9a83e601de9153e4a7111962c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/5bfbbfbabb3df2b9a83e601de9153e4a7111962c", + "reference": "5bfbbfbabb3df2b9a83e601de9153e4a7111962c", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/phpcompatibility-paragonie": "^1.0", + "squizlabs/php_codesniffer": "^3.3" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "phpcs", + "standards", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-05-12T16:38:37+00:00" + }, + { + "name": "phpcsstandards/phpcsextra", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "fa4b8d051e278072928e32d817456a7fdb57b6ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/fa4b8d051e278072928e32d817456a7fdb57b6ca", + "reference": "fa4b8d051e278072928e32d817456a7fdb57b6ca", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.0 || ^4.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" + } + ], + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-06-14T07:40:39+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "65355670ac17c34cd235cf9d3ceae1b9252c4dad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/65355670ac17c34cd235cf9d3ceae1b9252c4dad", + "reference": "65355670ac17c34cd235cf9d3ceae1b9252c4dad", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.13.0 || ^4.0" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-06-12T04:32:33+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.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", + "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.2" + }, + "time": "2025-04-13T19:20:35+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": "phpoption/phpoption", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "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 || ^10.5.28" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:41:07+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "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.1.0" + }, + "time": "2025-02-19T13:28:12+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.17", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-05-21T20:55:28+00:00" + }, + { + "name": "phpstan/phpstan-strict-rules", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.0.4" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Extra strict and opinionated rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.4" + }, + "time": "2025-03-18T11:42:40+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.23", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.5.0 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.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.23" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-05-02T06:40:34+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/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": "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": "sirbrillig/phpcs-variable-analysis", + "version": "v2.12.0", + "source": { + "type": "git", + "url": "https://github.com/sirbrillig/phpcs-variable-analysis.git", + "reference": "4debf5383d9ade705e0a25121f16c3fecaf433a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/4debf5383d9ade705e0a25121f16c3fecaf433a7", + "reference": "4debf5383d9ade705e0a25121f16c3fecaf433a7", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "squizlabs/php_codesniffer": "^3.5.6" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", + "phpcsstandards/phpcsdevcs": "^1.1", + "phpstan/phpstan": "^1.7", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0 || ^10.5.32 || ^11.3.3", + "vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "VariableAnalysis\\": "VariableAnalysis/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Sam Graham", + "email": "php-codesniffer-variableanalysis@illusori.co.uk" + }, + { + "name": "Payton Swick", + "email": "payton@foolord.com" + } + ], + "description": "A PHPCS sniff to detect problems with variables.", + "keywords": [ + "phpcs", + "static analysis" + ], + "support": { + "issues": "https://github.com/sirbrillig/phpcs-variable-analysis/issues", + "source": "https://github.com/sirbrillig/phpcs-variable-analysis", + "wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki" + }, + "time": "2025-03-17T16:17:38+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "8.19.1", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "458d665acd49009efebd7e0cb385d71ae9ac3220" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/458d665acd49009efebd7e0cb385d71ae9ac3220", + "reference": "458d665acd49009efebd7e0cb385d71ae9ac3220", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^2.1.0", + "squizlabs/php_codesniffer": "^3.13.0" + }, + "require-dev": { + "phing/phing": "3.0.1", + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpstan/phpstan-phpunit": "2.0.6", + "phpstan/phpstan-strict-rules": "2.0.4", + "phpunit/phpunit": "9.6.8|10.5.45|11.4.4|11.5.21|12.1.3" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.19.1" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2025-06-09T17:53:57+00:00" + }, + { + "name": "softcreatr/jsonpath", + "version": "0.7.6", + "source": { + "type": "git", + "url": "https://github.com/SoftCreatR/JSONPath.git", + "reference": "e04c02cb78bcc242c69d17dac5b29436bf3e1076" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/e04c02cb78bcc242c69d17dac5b29436bf3e1076", + "reference": "e04c02cb78bcc242c69d17dac5b29436bf3e1076", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.1,<8.0" + }, + "replace": { + "flow/jsonpath": "*" + }, + "require-dev": { + "phpunit/phpunit": ">=7.0", + "roave/security-advisories": "dev-latest", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Flow\\JSONPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Frank", + "email": "stephen@flowsa.com", + "homepage": "https://prismaticbytes.com", + "role": "Developer" + }, + { + "name": "Sascha Greuel", + "email": "hello@1-2.dev", + "homepage": "https://1-2.dev", + "role": "Developer" + } + ], + "description": "JSONPath implementation for parsing, searching and flattening arrays", + "support": { + "email": "hello@1-2.dev", + "forum": "https://github.com/SoftCreatR/JSONPath/discussions", + "issues": "https://github.com/SoftCreatR/JSONPath/issues", + "source": "https://github.com/SoftCreatR/JSONPath" + }, + "funding": [ + { + "url": "https://ecologi.com/softcreatr?r=61212ab3fc69b8eb8a2014f4", + "type": "custom" + }, + { + "url": "https://github.com/softcreatr", + "type": "github" + } + ], + "time": "2022-09-27T09:27:12+00:00" + }, + { + "name": "spatie/array-to-xml", + "version": "2.17.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/array-to-xml.git", + "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", + "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^7.4|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "pestphp/pest": "^1.21", + "phpunit/phpunit": "^9.0", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ArrayToXml\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://freek.dev", + "role": "Developer" + } + ], + "description": "Convert an array to xml", + "homepage": "https://github.com/spatie/array-to-xml", + "keywords": [ + "array", + "convert", + "xml" + ], + "support": { + "source": "https://github.com/spatie/array-to-xml/tree/2.17.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2022-12-26T08:22:07+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.13.2", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "5b5e3821314f947dd040c70f7992a64eac89025c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5b5e3821314f947dd040c70f7992a64eac89025c", + "reference": "5b5e3821314f947dd040c70f7992a64eac89025c", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-06-17T22:17:01+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/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/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/deprecation-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" + }, + "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": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", + "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.4" + }, + "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/filesystem", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "57c8294ed37d4a055b77057827c67f9558c95c54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54", + "reference": "57c8294ed37d4a055b77057827c67f9558c95c54", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/process": "^5.4|^6.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.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/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.32.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.32.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.32.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.32.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.32.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.32.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.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "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.32.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-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.32.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.32.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.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "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.32.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": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.32.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.32.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": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "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/v2.5.4" + }, + "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/string", + "version": "v5.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\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/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-10T20:33:58+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": "szepeviktor/phpstan-wordpress", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/szepeviktor/phpstan-wordpress.git", + "reference": "963887b04c21fe7ac78e61c1351f8b00fff9f8f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/963887b04c21fe7ac78e61c1351f8b00fff9f8f8", + "reference": "963887b04c21fe7ac78e61c1351f8b00fff9f8f8", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "php-stubs/wordpress-stubs": "^6.6.2", + "phpstan/phpstan": "^2.0" + }, + "require-dev": { + "composer/composer": "^2.1.14", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.0", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0", + "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" + }, + "suggest": { + "swissspidy/phpstan-no-private": "Detect usage of internal core functions, classes and methods" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "SzepeViktor\\PHPStan\\WordPress\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "WordPress extensions for PHPStan", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/szepeviktor/phpstan-wordpress/issues", + "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v2.0.2" + }, + "time": "2025-02-12T18:43:37+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": "vimeo/psalm", + "version": "5.26.1", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", + "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer-runtime-api": "^2", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/advanced-json-rpc": "^3.1", + "felixfbecker/language-server-protocol": "^1.5.2", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.17", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "spatie/array-to-xml": "^2.17.0 || ^3.0", + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" + }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "amphp/phpunit-util": "^2.0", + "bamarni/composer-bin-plugin": "^1.4", + "brianium/paratest": "^6.9", + "ext-curl": "*", + "mockery/mockery": "^1.5", + "nunomaduro/mock-final-classes": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpdoc-parser": "^1.6", + "phpunit/phpunit": "^9.6", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.6", + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "project", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev", + "dev-3.x": "3.x-dev", + "dev-4.x": "4.x-dev", + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psalm\\": "src/Psalm/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php", + "static analysis" + ], + "support": { + "docs": "https://psalm.dev/docs", + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm" + }, + "time": "2024-09-08T18:53:08+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v4.3.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "67a491df68208bef8c37092db11fa3885008efcf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/67a491df68208bef8c37092db11fa3885008efcf", + "reference": "67a491df68208bef8c37092db11fa3885008efcf", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "phpoption/phpoption": "^1.7.3", + "symfony/polyfill-ctype": "^1.17" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-filter": "*", + "ext-pcre": "*", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.30" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator.", + "ext-pcre": "Required to use most of the library." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "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/v4.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2022-10-16T00:51:09+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" + }, + { + "name": "wp-cli/cache-command", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/cache-command.git", + "reference": "14f76b0bc8f9fa0a680e9c70e18fcf627774d055" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/cache-command/zipball/14f76b0bc8f9fa0a680e9c70e18fcf627774d055", + "reference": "14f76b0bc8f9fa0a680e9c70e18fcf627774d055", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "cache", + "cache add", + "cache decr", + "cache delete", + "cache flush", + "cache flush-group", + "cache get", + "cache incr", + "cache patch", + "cache pluck", + "cache replace", + "cache set", + "cache supports", + "cache type", + "transient", + "transient delete", + "transient get", + "transient list", + "transient patch", + "transient pluck", + "transient set", + "transient type" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.2.0" + }, + "time": "2025-05-06T01:43:20+00:00" + }, + { + "name": "wp-cli/checksum-command", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/checksum-command.git", + "reference": "39992dbd66835f8d5c2cc5bfeacf9d2c450cbafe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/39992dbd66835f8d5c2cc5bfeacf9d2c450cbafe", + "reference": "39992dbd66835f8d5c2cc5bfeacf9d2c450cbafe", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "core verify-checksums", + "plugin verify-checksums" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.1" + }, + "time": "2025-04-10T11:02:20+00:00" + }, + { + "name": "wp-cli/config-command", + "version": "v2.3.8", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/config-command.git", + "reference": "994b3dc9e8284fc978366920d5c5ae0dde3a004e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/config-command/zipball/994b3dc9e8284fc978366920d5c5ae0dde3a004e", + "reference": "994b3dc9e8284fc978366920d5c5ae0dde3a004e", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12", + "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": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.8" + }, + "time": "2025-04-11T09:37:43+00:00" + }, + { + "name": "wp-cli/core-command", + "version": "v2.1.21", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/core-command.git", + "reference": "f157fb37dae1d13fe7318452f932917161e83e53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/core-command/zipball/f157fb37dae1d13fe7318452f932917161e83e53", + "reference": "f157fb37dae1d13fe7318452f932917161e83e53", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4 || ^2 || ^3", + "wp-cli/wp-cli": "^2.12" + }, + "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": "^5" + }, + "type": "wp-cli-package", + "extra": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.21" + }, + "time": "2025-07-08T17:31:39+00:00" + }, + { + "name": "wp-cli/cron-command", + "version": "v2.3.2", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/cron-command.git", + "reference": "6f450028a75ebd275f12cad62959a0709bf3e7c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/cron-command/zipball/6f450028a75ebd275f12cad62959a0709bf3e7c1", + "reference": "6f450028a75ebd275f12cad62959a0709bf3e7c1", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "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": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.2" + }, + "time": "2025-04-02T11:55:20+00:00" + }, + { + "name": "wp-cli/db-command", + "version": "v2.1.3", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/db-command.git", + "reference": "f857c91454d7092fa672bc388512a51752d9264a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/db-command/zipball/f857c91454d7092fa672bc388512a51752d9264a", + "reference": "f857c91454d7092fa672bc388512a51752d9264a", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.3" + }, + "time": "2025-04-10T11:02:04+00:00" + }, + { + "name": "wp-cli/embed-command", + "version": "v2.0.18", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/embed-command.git", + "reference": "52f59a1dacf1d4a1c68fd685f27909e1f493816b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/embed-command/zipball/52f59a1dacf1d4a1c68fd685f27909e1f493816b", + "reference": "52f59a1dacf1d4a1c68fd685f27909e1f493816b", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.18" + }, + "time": "2025-04-10T11:01:32+00:00" + }, + { + "name": "wp-cli/entity-command", + "version": "v2.8.4", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/entity-command.git", + "reference": "213611f8ab619ca137d983e9b987f7fbf1ac21d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/213611f8ab619ca137d983e9b987f7fbf1ac21d4", + "reference": "213611f8ab619ca137d983e9b987f7fbf1ac21d4", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "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": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.4" + }, + "time": "2025-05-06T16:12:49+00:00" + }, + { + "name": "wp-cli/eval-command", + "version": "v2.2.6", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/eval-command.git", + "reference": "20ec428a7b9bc604fab0bd33ee8fa20662650455" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/eval-command/zipball/20ec428a7b9bc604fab0bd33ee8fa20662650455", + "reference": "20ec428a7b9bc604fab0bd33ee8fa20662650455", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "eval", + "eval-file" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.6" + }, + "time": "2024-11-24T17:28:06+00:00" + }, + { + "name": "wp-cli/export-command", + "version": "v2.1.14", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/export-command.git", + "reference": "2af32bf12c1bccd6561a215dbbafc2f272647ee8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/export-command/zipball/2af32bf12c1bccd6561a215dbbafc2f272647ee8", + "reference": "2af32bf12c1bccd6561a215dbbafc2f272647ee8", + "shasum": "" + }, + "require": { + "nb/oxymel": "~0.1.0", + "wp-cli/wp-cli": "^2.12" + }, + "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": { + "bundled": true, + "commands": [ + "export" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.14" + }, + "time": "2025-04-02T15:29:08+00:00" + }, + { + "name": "wp-cli/extension-command", + "version": "v2.1.24", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/extension-command.git", + "reference": "d21a2f504ac43a86b6b08697669b5b0844748133" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/d21a2f504ac43a86b6b08697669b5b0844748133", + "reference": "d21a2f504ac43a86b6b08697669b5b0844748133", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4 || ^2 || ^3", + "wp-cli/wp-cli": "^2.12" + }, + "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.3.7" + }, + "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.24" + }, + "time": "2025-05-06T19:17:53+00:00" + }, + { + "name": "wp-cli/i18n-command", + "version": "v2.6.5", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/i18n-command.git", + "reference": "5e73d417398993625331a9f69f6c2ef60f234070" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/5e73d417398993625331a9f69f6c2ef60f234070", + "reference": "5e73d417398993625331a9f69f6c2ef60f234070", + "shasum": "" + }, + "require": { + "eftec/bladeone": "3.52", + "gettext/gettext": "^4.8", + "mck89/peast": "^1.13.11", + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/scaffold-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4.3.9" + }, + "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.5" + }, + "time": "2025-04-25T21:49:29+00:00" + }, + { + "name": "wp-cli/import-command", + "version": "v2.0.14", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/import-command.git", + "reference": "b2c48f3e51683e825738df62bf8ccc7004c5f0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/import-command/zipball/b2c48f3e51683e825738df62bf8ccc7004c5f0f9", + "reference": "b2c48f3e51683e825738df62bf8ccc7004c5f0f9", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "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": { + "bundled": true, + "commands": [ + "import" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.14" + }, + "time": "2025-04-02T16:47:25+00:00" + }, + { + "name": "wp-cli/language-command", + "version": "v2.0.24", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/language-command.git", + "reference": "1f1ca0ce3ee6cc46edfe06ee093cf3a57a131a18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/language-command/zipball/1f1ca0ce3ee6cc46edfe06ee093cf3a57a131a18", + "reference": "1f1ca0ce3ee6cc46edfe06ee093cf3a57a131a18", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "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": "^5" + }, + "type": "wp-cli-package", + "extra": { + "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" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.24" + }, + "time": "2025-07-08T17:50:14+00:00" + }, + { + "name": "wp-cli/maintenance-mode-command", + "version": "v2.1.3", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/maintenance-mode-command.git", + "reference": "b947e094e00b7b68c6376ec9bd03303515864062" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/maintenance-mode-command/zipball/b947e094e00b7b68c6376ec9bd03303515864062", + "reference": "b947e094e00b7b68c6376ec9bd03303515864062", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "maintenance-mode", + "maintenance-mode activate", + "maintenance-mode deactivate", + "maintenance-mode status", + "maintenance-mode is-active" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.3" + }, + "time": "2024-11-24T17:26:30+00:00" + }, + { + "name": "wp-cli/media-command", + "version": "v2.2.2", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/media-command.git", + "reference": "a810ea0e68473fce6a234e67c6c5f19bb820a753" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/media-command/zipball/a810ea0e68473fce6a234e67c6c5f19bb820a753", + "reference": "a810ea0e68473fce6a234e67c6c5f19bb820a753", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "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": { + "bundled": true, + "commands": [ + "media", + "media import", + "media regenerate", + "media image-size" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.2" + }, + "time": "2025-04-11T09:28:29+00:00" + }, + { + "name": "wp-cli/mustache", + "version": "v2.14.99", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/mustache.php.git", + "reference": "ca23b97ac35fbe01c160549eb634396183d04a59" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/mustache.php/zipball/ca23b97ac35fbe01c160549eb634396183d04a59", + "reference": "ca23b97ac35fbe01c160549eb634396183d04a59", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "replace": { + "mustache/mustache": "^2.14.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.19.3", + "yoast/phpunit-polyfills": "^2.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": { + "source": "https://github.com/wp-cli/mustache.php/tree/v2.14.99" + }, + "time": "2025-05-06T16:15:37+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.6.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/package-command.git", + "reference": "682d8c6bb30c782c3b09c015478c7cbe1cc727a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/package-command/zipball/682d8c6bb30c782c3b09c015478c7cbe1cc727a9", + "reference": "682d8c6bb30c782c3b09c015478c7cbe1cc727a9", + "shasum": "" + }, + "require": { + "composer/composer": "^2.2.25", + "ext-json": "*", + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/scaffold-command": "^1 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "package", + "package browse", + "package install", + "package list", + "package update", + "package uninstall" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.6.0" + }, + "time": "2025-04-11T09:28:45+00:00" + }, + { + "name": "wp-cli/php-cli-tools", + "version": "v0.12.5", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/php-cli-tools.git", + "reference": "34b83b4f700df8a4ec3fd17bf7e7e7d8ca5f28da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/34b83b4f700df8a4ec3fd17bf7e7e7d8ca5f28da", + "reference": "34b83b4f700df8a4ec3fd17bf7e7e7d8ca5f28da", + "shasum": "" + }, + "require": { + "php": ">= 5.6.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.12.5" + }, + "time": "2025-03-26T16:13:46+00:00" + }, + { + "name": "wp-cli/process", + "version": "v5.9.99", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/process.git", + "reference": "f0aec5ca26a702d3157e3a19982b662521ac2b81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/process/zipball/f0aec5ca26a702d3157e3a19982b662521ac2b81", + "reference": "f0aec5ca26a702d3157e3a19982b662521ac2b81", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "replace": { + "symfony/process": "^5.4.47" + }, + "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": "Symfony Process Component", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/wp-cli/process/tree/v5.9.99" + }, + "time": "2025-05-06T21:26:50+00:00" + }, + { + "name": "wp-cli/rewrite-command", + "version": "v2.0.15", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/rewrite-command.git", + "reference": "277ec689b7c268680ff429f52558508622c9b34c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/rewrite-command/zipball/277ec689b7c268680ff429f52558508622c9b34c", + "reference": "277ec689b7c268680ff429f52558508622c9b34c", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "rewrite", + "rewrite flush", + "rewrite list", + "rewrite structure" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.15" + }, + "time": "2025-04-02T12:09:09+00:00" + }, + { + "name": "wp-cli/role-command", + "version": "v2.0.16", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/role-command.git", + "reference": "ed57fb5436b4d47954b07e56c734d19deb4fc491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/role-command/zipball/ed57fb5436b4d47954b07e56c734d19deb4fc491", + "reference": "ed57fb5436b4d47954b07e56c734d19deb4fc491", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "role", + "role create", + "role delete", + "role exists", + "role list", + "role reset", + "cap", + "cap add", + "cap list", + "cap remove" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.16" + }, + "time": "2025-04-02T12:24:15+00:00" + }, + { + "name": "wp-cli/scaffold-command", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/scaffold-command.git", + "reference": "b4238ea12e768b3f15d10339a53a8642f82e1d2b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/scaffold-command/zipball/b4238ea12e768b3f15d10339a53a8642f82e1d2b", + "reference": "b4238ea12e768b3f15d10339a53a8642f82e1d2b", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "scaffold", + "scaffold underscores", + "scaffold block", + "scaffold child-theme", + "scaffold plugin", + "scaffold plugin-tests", + "scaffold post-type", + "scaffold taxonomy", + "scaffold theme-tests" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.5.0" + }, + "time": "2025-04-11T09:29:34+00:00" + }, + { + "name": "wp-cli/search-replace-command", + "version": "v2.1.8", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/search-replace-command.git", + "reference": "65397a7bfdd5ba2cff26f3ab03ef0bcb916c0057" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/65397a7bfdd5ba2cff26f3ab03ef0bcb916c0057", + "reference": "65397a7bfdd5ba2cff26f3ab03ef0bcb916c0057", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "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": { + "bundled": true, + "commands": [ + "search-replace" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.8" + }, + "time": "2025-04-02T13:07:50+00:00" + }, + { + "name": "wp-cli/server-command", + "version": "v2.0.15", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/server-command.git", + "reference": "80a9243f94e0ac073f9bfdb516d2ac7e1fa01a71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/server-command/zipball/80a9243f94e0ac073f9bfdb516d2ac7e1fa01a71", + "reference": "80a9243f94e0ac073f9bfdb516d2ac7e1fa01a71", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/entity-command": "^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "server" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.15" + }, + "time": "2025-04-10T11:03:13+00:00" + }, + { + "name": "wp-cli/shell-command", + "version": "v2.0.16", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/shell-command.git", + "reference": "3af53a9f4b240e03e77e815b2ee10f229f1aa591" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/shell-command/zipball/3af53a9f4b240e03e77e815b2ee10f229f1aa591", + "reference": "3af53a9f4b240e03e77e815b2ee10f229f1aa591", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "shell" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.16" + }, + "time": "2025-04-11T09:39:33+00:00" + }, + { + "name": "wp-cli/super-admin-command", + "version": "v2.0.16", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/super-admin-command.git", + "reference": "54ac063c384743ee414806d42cb8c61c6aa1fa8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/super-admin-command/zipball/54ac063c384743ee414806d42cb8c61c6aa1fa8e", + "reference": "54ac063c384743ee414806d42cb8c61c6aa1fa8e", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/entity-command": "^1.3 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "super-admin", + "super-admin add", + "super-admin list", + "super-admin remove" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.16" + }, + "time": "2025-04-02T13:07:32+00:00" + }, + { + "name": "wp-cli/widget-command", + "version": "v2.1.12", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/widget-command.git", + "reference": "73084053f7b32d92583e44d870b81f287beea6a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/widget-command/zipball/73084053f7b32d92583e44d870b81f287beea6a9", + "reference": "73084053f7b32d92583e44d870b81f287beea6a9", + "shasum": "" + }, + "require": { + "wp-cli/wp-cli": "^2.12" + }, + "require-dev": { + "wp-cli/extension-command": "^1.2 || ^2", + "wp-cli/wp-cli-tests": "^4" + }, + "type": "wp-cli-package", + "extra": { + "bundled": true, + "commands": [ + "widget", + "widget add", + "widget deactivate", + "widget delete", + "widget list", + "widget move", + "widget reset", + "widget update", + "sidebar", + "sidebar list" + ], + "branch-alias": { + "dev-main": "2.x-dev" + } + }, + "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.12" + }, + "time": "2025-04-11T09:29:37+00:00" + }, + { + "name": "wp-cli/wp-cli", + "version": "v2.12.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/wp-cli.git", + "reference": "03d30d4138d12b4bffd8b507b82e56e129e0523f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/03d30d4138d12b4bffd8b507b82e56e129e0523f", + "reference": "03d30d4138d12b4bffd8b507b82e56e129e0523f", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": "^5.6 || ^7.0 || ^8.0", + "symfony/finder": ">2.7", + "wp-cli/mustache": "^2.14.99", + "wp-cli/mustangostang-spyc": "^0.6.3", + "wp-cli/php-cli-tools": "~0.12.4" + }, + "require-dev": { + "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.3.10" + }, + "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.12.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": "2025-05-07T01:16:12+00:00" + }, + { + "name": "wp-cli/wp-cli-bundle", + "version": "v2.12.0", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/wp-cli-bundle.git", + "reference": "d639a3dab65f4b935b21c61ea3662bf3258a03a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-cli-bundle/zipball/d639a3dab65f4b935b21c61ea3662bf3258a03a5", + "reference": "d639a3dab65f4b935b21c61ea3662bf3258a03a5", + "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/process": "5.9.99", + "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.12" + }, + "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.12.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": "2025-05-07T02:15:53+00:00" + }, + { + "name": "wp-cli/wp-config-transformer", + "version": "v1.4.2", + "source": { + "type": "git", + "url": "https://github.com/wp-cli/wp-config-transformer.git", + "reference": "b78cab1159b43eb5ee097e2cfafe5eab573d2a8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-cli/wp-config-transformer/zipball/b78cab1159b43eb5ee097e2cfafe5eab573d2a8a", + "reference": "b78cab1159b43eb5ee097e2cfafe5eab573d2a8a", + "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.2" + }, + "time": "2025-03-31T08:37:05+00:00" + }, + { + "name": "wp-coding-standards/wpcs", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", + "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/9333efcbff231f10dfd9c56bb7b65818b4733ca7", + "reference": "9333efcbff231f10dfd9c56bb7b65818b4733ca7", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", + "php": ">=5.4", + "phpcsstandards/phpcsextra": "^1.2.1", + "phpcsstandards/phpcsutils": "^1.0.10", + "squizlabs/php_codesniffer": "^3.9.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^9.0", + "phpcsstandards/phpcsdevtools": "^1.2.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "suggest": { + "ext-iconv": "For improved results", + "ext-mbstring": "For improved results" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", + "keywords": [ + "phpcs", + "standards", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", + "source": "https://github.com/WordPress/WordPress-Coding-Standards", + "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" + }, + "funding": [ + { + "url": "https://opencollective.com/php_codesniffer", + "type": "custom" + } + ], + "time": "2024-03-25T16:39:00+00:00" + }, + { + "name": "wp-graphql/wp-graphql-testcase", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/wp-graphql/wp-graphql-testcase.git", + "reference": "572d4c51e9a0a33ec1b99970155fe005f468f4ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-graphql/wp-graphql-testcase/zipball/572d4c51e9a0a33ec1b99970155fe005f468f4ec", + "reference": "572d4c51e9a0a33ec1b99970155fe005f468f4ec", + "shasum": "" + }, + "require": { + "php-extended/polyfill-php80-str-utils": "^1.3" + }, + "require-dev": { + "automattic/vipwpcs": "^2.3", + "composer/installers": "^1.9", + "johnpbloch/wordpress": "^6.1", + "php-coveralls/php-coveralls": "2.4.3", + "squizlabs/php_codesniffer": "^3.5", + "wp-coding-standards/wpcs": "^2.3", + "wpackagist-plugin/wp-graphql": "^1.26" + }, + "suggest": { + "codeception/module-asserts": "Needed for \\Tests\\WPGraphQL\\TestCase\\WPGraphQLTestcase to work.", + "codeception/util-universalframework": "Needed for \\Tests\\WPGraphQL\\TestCase\\WPGraphQLTestcase to work.", + "guzzlehttp/guzzle": "Needed for \\Tests\\WPGraphQL\\Codeception\\Module\\WPGraphQL to work.", + "lucatume/wp-browser": "Needed for \\Tests\\WPGraphQL\\TestCase\\WPGraphQLTestcase to work.", + "phpunit/phpunit": "Needed for \\Tests\\WPGraphQL\\TestCase\\WPGraphQLUnitTestcase to work.", + "wp-phpunit/wp-phpunit": "Needed for \\Tests\\WPGraphQL\\TestCase\\WPGraphQLUnitTestcase to work.", + "yoast/phpunit-polyfills": "Needed for \\Tests\\WPGraphQL\\TestCase\\WPGraphQLUnitTestcase to work." + }, + "type": "library", + "extra": { + "installer-paths": { + "local/public/wp-content/plugins/{$name}/": [ + "type:wordpress-plugin" + ] + }, + "wordpress-install-dir": "local/public" + }, + "autoload": { + "psr-4": { + "Tests\\WPGraphQL\\": "src/" + }, + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Geoff Taylor", + "email": "geoffrey.taylor@outlook.com" + } + ], + "description": "Codeception module for WPGraphQL API testing", + "support": { + "issues": "https://github.com/wp-graphql/wp-graphql-testcase/issues", + "source": "https://github.com/wp-graphql/wp-graphql-testcase/tree/v3.4.0" + }, + "time": "2024-08-08T18:48:14+00:00" + }, + { + "name": "wp-hooks/wordpress-core", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/wp-hooks/wordpress-core-hooks.git", + "reference": "127af21a918a52bcead7ce9b743b17b5d64eb148" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wp-hooks/wordpress-core-hooks/zipball/127af21a918a52bcead7ce9b743b17b5d64eb148", + "reference": "127af21a918a52bcead7ce9b743b17b5d64eb148", + "shasum": "" + }, + "replace": { + "johnbillion/wp-hooks": "*" + }, + "require-dev": { + "erusev/parsedown": "1.8.0-beta-7", + "oomphinc/composer-installers-extender": "^2", + "roots/wordpress-core-installer": "^1.0.0", + "roots/wordpress-full": "6.8", + "wp-hooks/generator": "1.0.0" + }, + "type": "library", + "extra": { + "wp-hooks": { + "ignore-files": [ + "wp-admin/includes/deprecated.php", + "wp-admin/includes/ms-deprecated.php", + "wp-content/", + "wp-includes/deprecated.php", + "wp-includes/ID3/", + "wp-includes/ms-deprecated.php", + "wp-includes/pomo/", + "wp-includes/random_compat/", + "wp-includes/Requests/", + "wp-includes/SimplePie/", + "wp-includes/sodium_compat/", + "wp-includes/Text/" + ], + "ignore-hooks": [ + "load-categories.php", + "load-edit-link-categories.php", + "load-edit-tags.php", + "load-page-new.php", + "load-page.php", + "option_enable_xmlrpc", + "edit_post_{$field}", + "pre_post_{$field}", + "post_{$field}", + "pre_option_enable_xmlrpc", + "$page_hook", + "$hook", + "$hook_name" + ] + }, + "wordpress-install-dir": "vendor/wordpress/wordpress" + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-or-later" + ], + "authors": [ + { + "name": "John Blackbourn", + "homepage": "https://johnblackbourn.com/" + } + ], + "description": "All the actions and filters from WordPress core in machine-readable JSON format.", + "support": { + "issues": "https://github.com/wp-hooks/wordpress-core-hooks/issues", + "source": "https://github.com/wp-hooks/wordpress-core-hooks/tree/1.10.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/johnbillion", + "type": "github" + } + ], + "time": "2025-04-16T22:20:41+00:00" + } + ], + "aliases": [ + { + "package": "phpcompatibility/php-compatibility", + "version": "dev-develop", + "alias": "9.99.99", + "alias_normalized": "9.99.99.0" + } + ], + "minimum-stability": "dev", + "stability-flags": { + "phpcompatibility/php-compatibility": 20 + }, + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^7.4 || ^8.0" + }, + "platform-dev": {}, + "platform-overrides": { + "php": "7.4" + }, + "plugin-api-version": "2.6.0" +} diff --git a/plugins/wpgraphql-logging/deactivation.php b/plugins/wpgraphql-logging/deactivation.php new file mode 100644 index 00000000..d76049c8 --- /dev/null +++ b/plugins/wpgraphql-logging/deactivation.php @@ -0,0 +1,18 @@ +getTokens(); + $token = $tokens[$stackPtr]; + + if ($token['code'] === T_ELSE) { + $warning = 'Usage of "else" detected; consider refactoring to avoid else branches'; + $phpcsFile->addWarning($warning, $stackPtr, 'ElseDetected'); + + return; + } + + if ($token['code'] === T_ELSEIF) { + $warning = 'Usage of "elseif" detected; consider refactoring to avoid else branches'; + $phpcsFile->addWarning($warning, $stackPtr, 'ElseIfDetected'); + } + } +} diff --git a/plugins/wpgraphql-logging/phpcs/HWPStandard/ruleset.xml b/plugins/wpgraphql-logging/phpcs/HWPStandard/ruleset.xml new file mode 100644 index 00000000..89470394 --- /dev/null +++ b/plugins/wpgraphql-logging/phpcs/HWPStandard/ruleset.xml @@ -0,0 +1,4 @@ + + + HWP custom coding standard. + diff --git a/plugins/wpgraphql-logging/phpstan.neon.dist b/plugins/wpgraphql-logging/phpstan.neon.dist new file mode 100644 index 00000000..994f339a --- /dev/null +++ b/plugins/wpgraphql-logging/phpstan.neon.dist @@ -0,0 +1,33 @@ +includes: + - vendor/szepeviktor/phpstan-wordpress/extension.neon + - vendor/phpstan/phpstan-strict-rules/rules.neon + +services: + - + class: WPGraphQL\Logging\PHPStan\Rules\ClassConstantVarAnnotationRule + tags: [phpstan.rules.rule] + +parameters: + # Analysis Rules + treatPhpDocTypesAsCertain: false + inferPrivatePropertyTypeFromConstructor: true + checkExplicitMixedMissingReturn: true + checkMissingTypehints: true + checkFunctionNameCase: true + checkInternalClassCaseSensitivity: true + checkTooWideReturnTypesInProtectedAndPublicMethods: true + polluteScopeWithAlwaysIterableForeach: false + polluteScopeWithLoopInitialAssignments: false + reportAlwaysTrueInLastCondition: true + reportStaticMethodSignatures: true + reportWrongPhpDocTypeInVarTag: true + + # Configuration + level: 8 + phpVersion: + min: 70400 + max: 80400 + paths: + - wpgraphql-logging.php + - src/ + diff --git a/plugins/wpgraphql-logging/phpstan/Rules/ClassConstantVarAnnotationRule.php b/plugins/wpgraphql-logging/phpstan/Rules/ClassConstantVarAnnotationRule.php new file mode 100644 index 00000000..464f934e --- /dev/null +++ b/plugins/wpgraphql-logging/phpstan/Rules/ClassConstantVarAnnotationRule.php @@ -0,0 +1,41 @@ + + */ +class ClassConstantVarAnnotationRule implements Rule +{ + public function getNodeType(): string + { + return Node\Stmt\ClassConst::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $docComment = $node->getDocComment(); + if (!$docComment instanceof Doc) { + return [ + RuleErrorBuilder::message('Class constant must have a @var annotation in its docblock.')->build(), + ]; + } + + $docText = $docComment->getText(); + if (!preg_match('/@var\s+\S+/', $docText)) { + return [ + RuleErrorBuilder::message('Class constant docblock must contain a non-empty @var annotation.')->build(), + ]; + } + + return []; + } +} diff --git a/plugins/wpgraphql-logging/psalm.xml b/plugins/wpgraphql-logging/psalm.xml new file mode 100644 index 00000000..de65e558 --- /dev/null +++ b/plugins/wpgraphql-logging/psalm.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/wpgraphql-logging/readme.txt b/plugins/wpgraphql-logging/readme.txt new file mode 100644 index 00000000..4bcde764 --- /dev/null +++ b/plugins/wpgraphql-logging/readme.txt @@ -0,0 +1,19 @@ +=== WPGraphQL Logging === +Contributors: wpengine +Tags: GraphQL, Headless, WPGraphQL, React, Rest +Requires at least: 6.0 +Tested up to: 6.8,1 +Requires PHP: 7.4 +Requires WPGraphQL: 1.8.0 +Stable tag: 0.0.1 +License: GPL-2.0 +License URI: https://www.gnu.org/licenses/gpl-2.0.html + +== Description == + +A plugin for analyzing and measuring the performance of WPGraphQL queries in your headless application. + +== Upgrade Notice == +== Frequently Asked Questions == +== Screenshots == +== Changelog == diff --git a/plugins/wpgraphql-logging/src/Autoloader.php b/plugins/wpgraphql-logging/src/Autoloader.php new file mode 100644 index 00000000..3cb293cc --- /dev/null +++ b/plugins/wpgraphql-logging/src/Autoloader.php @@ -0,0 +1,95 @@ + +
+

+ +

+
+ get_row( $wpdb->prepare( "SELECT * FROM $table WHERE id = %d", $id ), ARRAY_A ); + if ( ! $row ) { + return null; + } + $entity = new self(); + $entity->setId( (int) $row['id'] ); + $entity->setLevel( $row['level'] ); + $entity->setLevelName( $row['level_name'] ); + $entity->setMessage( $row['message'] ); + $entity->setContext( $row['context'] ); + $entity->setExtra( $row['extra'] ); + $entity->setFormatted( $row['formatted'] ); + $entity->setDatetime( $row['datetime'] ); + $entity->setChannel( $row['channel'] ); + + return $entity; + } + + public function write(): void { + // @TODO some type of try/catch or error handling here. + global $wpdb; + $table = self::getTableName(); + $data = [ + 'level' => $this->getLevel(), + 'level_name' => $this->getLevelName(), + 'message' => $this->getMessage(), + 'context' => wp_json_encode($this->getContext()), + 'extra' => wp_json_encode($this->getExtra()), + 'formatted' => $this->getFormatted(), + 'datetime' => $this->getDatetime(), + 'channel' => $this->getChannel(), + ]; + + + if ( isset( $this->id ) ) { + $wpdb->update( $table, $data, [ 'id' => $this->id ] ); + } else { + $wpdb->insert( $table, $data ); + $this->setId( (int) $wpdb->insert_id ); + } + } + + public function getLevel(): int { + return $this->level; + } + + public function setLevel( int $level ): void { + $this->level = $level; + } + + public function getLevelName(): string { + return $this->level_name; + } + + public function setLevelName( string $level_name ): void { + $this->level_name = $level_name; + } + + public function getMessage(): string { + return $this->message; + } + + public function setMessage( string $message ): void { + $this->message = $message; + } + + public function getContext(): array { + return $this->context; + } + + public function setContext( array $context ): void { + $this->context = $context; + } + + public function getExtra(): array { + return $this->extra; + } + + public function setExtra( array $extra ): void { + $this->extra = $extra; + } + + public function getFormatted(): ?string { + return $this->formatted; + } + + public function setFormatted( ?string $formatted ): void { + $this->formatted = $formatted; + } + + public function getDatetime(): DateTimeImmutable { + return $this->datetime; + } + + public function setDatetime( DateTimeImmutable $datetime ): void { + $this->datetime = $datetime; + } + + public function getChannel(): ?string { + return $this->channel; + } + + public function setChannel( ?string $channel ): void { + $this->channel = $channel; + } + + public function getId(): int { + return $this->id; + } + + public function setId( int $id ): void { + $this->id = $id; + } + + public static function getTableName(): string { + global $wpdb; + + return $wpdb->prefix . 'wpgraphql_logging'; + } + + /** + * @TODO POC + * + * This is probably not the best way to do this, but it works for now. + */ + public static function get_schema(): string { + return ' + CREATE TABLE ' . self::getTableName() . " ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + level INT NOT NULL, + level_name VARCHAR(50) NOT NULL, + message TEXT NOT NULL, + context JSON NULL, + extra JSON NULL, + formatted TEXT NULL, + datetime DATETIME NOT NULL, + channel VARCHAR(100) NULL + ) {$GLOBALS['wpdb']->get_charset_collate()}; + "; + } +} diff --git a/plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php b/plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php new file mode 100644 index 00000000..3675d120 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php @@ -0,0 +1,34 @@ +setMessage( $record['message'] ?? ''); + $entity->setContext( $record['context'] ?? [] ); + $entity->setLevel( $record['level'] ?? Logger::INFO ); + $entity->setLevelName( $record['level_name'] ?? 'INFO' ); + $entity->setChannel( $record['channel'] ?? 'wpgraphql_logging' ); + $entity->setDatetime( $record['datetime'] ?? new \DateTimeImmutable()); + $entity->setExtra( $record['extra'] ?? [] ); + $entity->setFormatted( $record['formatted'] ?? '' ); + $entity->write(); + } +} diff --git a/plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php b/plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php new file mode 100644 index 00000000..5e20c1fb --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php @@ -0,0 +1,125 @@ +setup(); + } + + return self::$instance; + } + + /** + * @TODO POC + * + * This is POC on how to log to monolog. This isn't the finished product and should have different services + */ + protected function setup(): void { + // Setup handlers + $this->setup_handlers(); + $this->setup_logging_events(); + } + + /** + * Setup the logging handlers. + * + * @TODO POC - Refactor this to use a service container or similar pattern. + * + * @return vpod + */ + protected function setup_handlers(): void { + + // Create the database handler + $logger = new Logger( 'wpgraphql_logging' ); + $dbHandler = new WPGraphQLDatabaseHandler( Logger::DEBUG ); + + // Optional: Set a custom formatter + $formatter = new LineFormatter( + "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n", + 'Y-m-d H:i:s' + ); + $dbHandler->setFormatter( $formatter ); + + // Add the handler to the logger + $logger->pushHandler( $dbHandler ); + + $this->logger = $logger; + } + + protected function setup_logging_events(): void { + add_action( 'do_graphql_request', [ $this, 'log_pre_request' ], 10, 3 ); + add_action( 'graphql_process_http_request_response', [ $this, 'log_post_request' ], 10, 5 ); + // @TODO POC - Add more events here + // @TODO somehow group these? + } + + public function log_pre_request( $query, $variables, $operation_name ): void { + $this->start_time = microtime( true ); + $this->start_memory = memory_get_usage( true ); + + // Log the incoming request + $this->logger->info( 'Request', [ + 'query' => $query, + 'time' => $this->start_time, + 'memory_usage' => $this->start_memory, + 'variables' => $variables, + 'operation_name' => $operation_name, + 'user_id' => get_current_user_id() + ] ); + } + + public function log_post_request( $response, $result, string $operation_name, string $query, array $variables ) { + $time = microtime( true ); + $memory = memory_get_usage( true ); + + // Log the incoming request + $this->logger->info( 'Response', [ + 'query' => $query, + 'time' => $time, + 'memory_usage' => $memory, + 'variables' => $variables, + 'operation_name' => $operation_name, + 'user_id' => get_current_user_id() + ] ); + } +} diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php new file mode 100644 index 00000000..e5d1142d --- /dev/null +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -0,0 +1,96 @@ +setup(); + } + + /** + * Fire off init action. + * + * @param \WPGraphQL\Logging\Plugin $instance the instance of the plugin class. + */ + do_action( 'wpgraphql_logging_init', self::$instance ); + + return self::$instance; + } + + /** + * Initialize the plugin admin, frontend & api functionality. + */ + public function setup(): void { + + // @TODO POC + // Might be better to move to a hooks class + add_action( 'wpgraphql_logging_activate', [ $this, 'setup_database' ], 1, 0 ); + + WPGraphQLLoggingService::init(); + } + + /** + * Setups the database for the plugin. + */ + public function setup_database(): void { + $database = new LoggingEntity(); + $schema = $database->get_schema(); + global $wpdb; + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + dbDelta( $schema ); + } + + /** + * Throw error on object clone. + * The whole idea of the singleton design pattern is that there is a single object + * therefore, we don't want the object to be cloned. + * + * @codeCoverageIgnore + * + * @return void + */ + public function __clone() { + // Cloning instances of the class is forbidden. + _doing_it_wrong( __METHOD__, 'The plugin Plugin class should not be cloned.', '0.0.1' ); + } + + /** + * Disable unserializing of the class. + * + * @codeCoverageIgnore + */ + public function __wakeup(): void { + // De-serializing instances of the class is forbidden. + _doing_it_wrong( __METHOD__, 'De-serializing instances of the plugin Main class is not allowed.', '0.0.1' ); + } +} diff --git a/plugins/wpgraphql-logging/tests/_envs/.gitkeep b/plugins/wpgraphql-logging/tests/_envs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/plugins/wpgraphql-logging/tests/bootstrap.php b/plugins/wpgraphql-logging/tests/bootstrap.php new file mode 100644 index 00000000..08a6b684 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/bootstrap.php @@ -0,0 +1,20 @@ + +
+

+ +

+
+ Date: Tue, 22 Jul 2025 14:27:05 +0100 Subject: [PATCH 02/19] Created branch off POC. Tidied up. Added QA and unit tests setup to the plugin. Upgraded Monolog to version 3 and also upgraded other dev dependencies. --- plugins/wpgraphql-logging/README.md | 4 +- plugins/wpgraphql-logging/TESTING.md | 238 ++ plugins/wpgraphql-logging/bin/build-docker.sh | 6 +- .../wpgraphql-logging/bin/install-test-env.sh | 4 +- .../bin/local/run-unit-tests.sh | 2 +- .../bin/local/setup-docker-env.sh | 13 +- .../wpgraphql-logging/codeception.dist.yml | 4 +- plugins/wpgraphql-logging/composer.json | 27 +- plugins/wpgraphql-logging/composer.lock | 2311 +++++++++-------- plugins/wpgraphql-logging/readme.txt | 12 +- .../src/Database/LoggingEntity.php | 163 -- .../Handlers/WPGraphQLDatabaseHandler.php | 34 - .../src/Logging/WPGraphQLLoggingService.php | 125 - plugins/wpgraphql-logging/src/Plugin.php | 21 +- .../tests/wpunit/Core/ActivationTest.php | 36 + .../tests/wpunit/Core/AutoloaderTest.php | 123 + .../tests/wpunit/Core/DeactivationTest.php | 37 + .../tests/wpunit/Core/PluginTest.php | 69 + .../wpgraphql-logging/wpgraphql-logging.php | 10 +- 19 files changed, 1827 insertions(+), 1412 deletions(-) create mode 100644 plugins/wpgraphql-logging/TESTING.md delete mode 100644 plugins/wpgraphql-logging/src/Database/LoggingEntity.php delete mode 100644 plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php delete mode 100644 plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Core/AutoloaderTest.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Core/DeactivationTest.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php diff --git a/plugins/wpgraphql-logging/README.md b/plugins/wpgraphql-logging/README.md index bbb2145b..33c22eee 100644 --- a/plugins/wpgraphql-logging/README.md +++ b/plugins/wpgraphql-logging/README.md @@ -1,6 +1,6 @@ # WPGraphQL Logging -A POC plugin for logging GraphQL requests using Monolog. +A WPGraphQL logging plugin that provides visibility into request lifecycle to help quickly identify and resolve bottlenecks in your headless WordPress application. * [Join the Headless WordPress community on Discord.](https://discord.gg/headless-wordpress-836253505944813629) * [Documentation](#getting-started) @@ -15,6 +15,6 @@ TODO > [!CAUTION] -> This plugin is currently is a POC and not production ready +> This plugin is currently a POC and not production ready yet. --- diff --git a/plugins/wpgraphql-logging/TESTING.md b/plugins/wpgraphql-logging/TESTING.md new file mode 100644 index 00000000..27a0330d --- /dev/null +++ b/plugins/wpgraphql-logging/TESTING.md @@ -0,0 +1,238 @@ +# Testing WPGraphQL Logging + +## Table of Contents + +- [Overview](#overview) + - [Directory Structure](#directory-structure) + - [Technologies](#technologies) +- [Usage](#usage) + - [Running Tests](#running-tests) + - [GitHub Actions](#github-actions) +- [Setup Tests Locally](#setup-tests-locally) + - [Prerequisites](#prerequisites) + - [Docker Setup](#docker-setup) + - [What the Setup Script Does](#what-the-setup-script-does) + - [Running Tests Locally](#running-tests-locally) +- [Troubleshooting](#troubleshooting) +- [Contributing](#contributing) + +--- + +## Overview + +HWP Previews comes with automated tests for unit, integration, and acceptance (E2E) scenarios to ensure code quality and functionality. + +### Directory Structure + +A list of related files and directories for testing: + +```text +bin/ +├── install-test-env.sh # Set up test WP environment +├── run-codeception.sh # Run Codeception tests +├── run-e2e.sh # Run E2E (Playwright) tests +├── run-coverage.sh # Generate coverage reports +└── local/ + ├── setup-docker-env.sh # Setup Docker environment + ├── run-unit-tests.sh # Run unit tests in Docker with Codeception + ├── run-e2e-tests.sh # Run e2e tests in Docker with Playwright + ├── run-qa.sh # Run php code quality checks with PHPStan, Psalm and PHPCS + ├── run-wpunit.sh # Run WPUnit tests in Docker + └── run-functional.sh # Run functional tests in Docker + +tests/ +├── _data/ # Test data (e.g. DB dumps) +├── _envs/ # Environment configs +├── _output/ # Test output (logs, coverage) +├── _support/ # Helper classes, modules +├── wpunit/ # WPUnit (WordPress-aware unit/integration) test cases +├── wpunit.suite.dist.yml +└── wpunit/ + └── bootstrap.php # Bootstrap for WPUnit tests + +.env.dist # Example environment variables for testing +codeception.dist.yml # Main Codeception config +``` + +### Technologies + +We use the following technologies to run our tests: + +- [Codeception](https://codeception.com/) - PHP testing framework +- [WPBrowser](https://wpbrowser.wptestkit.dev/) - WordPress-specific testing tools +- [WPUnit](https://github.com/lipemat/wp-unit) - WordPress unit testing +- [Docker](https://www.docker.com/) - Containerized testing environment +- [Composer](https://getcomposer.org/) - PHP dependency management +- [Playwright](https://playwright.dev/) - End-to-end testing framework +- [npm](https://www.npmjs.com/) - JavaScript package manager + +--- + +## Usage + +The plugin includes the following test suites: + +1. **WP Unit Tests** – Unit and Integration Tests +2. **E2E Tests** – Acceptance tests using Playwright + +### Running Tests + +| Command | Description | +|------------------------------------------|----------------------------------------------------------| +| `composer run test:unit:coverage` | Run WPUnit (unit/integration) tests with coverage report | +| `composer run test:unit:coverage-html` | Generate an HTML code coverage report | +| `composer run test:e2e` | Run end-to-end (E2E) acceptance tests | +| `composer run test` | Run all available test suites | + +### GitHub Actions + +Automated testing runs on every pull request via GitHub Actions for a modified plugin: + +| Workflow | Description | Status | +|-------------------------|---------------------------------------------|--------| +| **Code Quality** | Runs static analysis and linting checks | [View Workflow](../../actions/workflows/code-quality.yml) | +| **E2E Tests** | Runs Playwright end-to-end acceptance tests | [View Workflow](../../actions/workflows/e2e.yml) | +| **Codeception (WPUnit)** | Runs unit and integration tests | [View Workflow](../../actions/workflows/codeception.yml) | + + +>[!IMPORTANT] +> Test coverage for WP Unit Tests is **95%**. Any new code will require tests to be added in order to pass CI checks. This is set in [text](codeception.dist.yml) in the parameter `min_coverage`. + +--- + +## Setup Tests Locally + +### Prerequisites + +- Docker and Docker Compose installed and running +- Composer installed +- Node.js and npm installed (for E2E tests) +- Terminal/command line access + +### Docker Setup + +>[!NOTE] +> You need Docker running locally before setting up tests. Alternatively, you can copy `.env.dist` to `.env` and update the database details to point to your local database. However, this will make database changes, so we recommend using the Docker setup instead. + +To set up your local Docker environment, run: + +```shell +sh bin/local/setup-docker-env.sh +``` + +This script will automatically handle the complete Docker environment setup process. + +### What the Setup Script Does + +The setup script performs the following operations: + +#### 1. Environment Verification +- ✅ Checks that Docker is running +- ✅ Verifies required files exist + +#### 2. Configuration Setup +- 📁 Copies `bin/local/.env.local` to `.env` + - Uses local development configuration (different from `.env.dist`) + - Sets appropriate database credentials and WordPress settings + +#### 3. Docker Container Management +- 🐳 Runs `composer run docker:build` + - Executes `sh bin/build-docker.sh` to create the Docker container + - Builds WordPress environment with PHP 8.2 +- 🚀 Runs `docker compose up -d` to start the container in detached mode + - Creates container named `wpgraphql-logging-wordpress-1` + - Sets up WordPress with test database + +#### 4. Code Coverage Setup +- 🔧 Installs and configures PCOV extension (preferred for performance) +- 🔄 Falls back to XDebug if PCOV installation fails +- ⚙️ Configures coverage settings automatically +- 🔄 Restarts container to ensure extensions are loaded + +#### 5. WordPress Installation +- 📝 Installs WordPress if not already present +- 🔌 Activates the plugin automatically +- ✅ Verifies the installation is working correctly + +### Running Tests Locally + +Once setup is complete, you can run tests using Composer: + +<[!NOTE] +< Ensure the docker container is running before executing tests. You can run `composer run docker:start` to start it. + +```shell +# Run unit tests with coverage +composer run test:unit:coverage + +# Run all tests +composer run test + +# Run E2E tests +composer run test:e2e +``` + +For a full list of available test commands, see the [Usage](#usage) section above. + +--- + +## Troubleshooting + +### Container Issues + +```shell +# Check container status +docker ps | grep wpgraph-logging + +# Restart containers if needed +docker compose restart + +# View container logs +docker compose logs wpgraph-logging-wordpress-1 +``` + +### Permission Issues + +```shell +# Fix test output permissions +docker exec wpgraphql-logging-wordpress-1 chmod 777 -R tests/_output +``` + +### Coverage Driver Issues + +```shell +# Check which coverage driver is available +docker exec wpgraphql-logging-wordpress-1 php -m | grep -E "(pcov|xdebug)" + +# Re-run setup if coverage isn't working +sh bin/local/setup-docker-env.sh +``` + +### WordPress Database Issues + +```shell +# Reinstall WordPress +docker exec wpgraphql-logging-wordpress-1 wp core install \ + --url=http://localhost \ + --title="Test Site" \ + --admin_user=admin \ + --admin_password=admin \ + --admin_email=admin@example.com \ + --allow-root +``` + +### Clean Up Environment + +```shell +# Stop containers +docker compose down + +# Remove containers and volumes (complete cleanup) +docker compose down -v +``` + +--- + +## Contributing + +If you feel like something is missing or you want to add tests or testing documentation, we encourage you to contribute! Please check out our [Contributing Guide](https://github.com/wpengine/hwptoolkit/blob/main/CONTRIBUTING.md) for more details. diff --git a/plugins/wpgraphql-logging/bin/build-docker.sh b/plugins/wpgraphql-logging/bin/build-docker.sh index 17a2b1b9..f106db39 100644 --- a/plugins/wpgraphql-logging/bin/build-docker.sh +++ b/plugins/wpgraphql-logging/bin/build-docker.sh @@ -14,9 +14,9 @@ print_usage_instructions() { echo "Example use:" echo " npm run docker:build" echo "" - echo " WP_VERSION=6.7 PHP_VERSION=8.2 npm run docker:build -- - c" + echo " WP_VERSION=6.8 PHP_VERSION=8.2 npm run docker:build -- - c" echo "" - echo " WP_VERSION=6.7 PHP_VERSION=8.2 bin/build-docker.sh -- c" + echo " WP_VERSION=6.8 PHP_VERSION=8.2 bin/build-docker.sh -- c" exit 1 } @@ -50,7 +50,7 @@ done TAG=${TAG:-latest} -WP_VERSION=${WP_VERSION:-6.7} +WP_VERSION=${WP_VERSION:-6.8} PHP_VERSION=${PHP_VERSION:-8.2} BUILD_NO_CACHE=${BUILD_NO_CACHE:-} diff --git a/plugins/wpgraphql-logging/bin/install-test-env.sh b/plugins/wpgraphql-logging/bin/install-test-env.sh index d0da9ebc..0c8d1e01 100644 --- a/plugins/wpgraphql-logging/bin/install-test-env.sh +++ b/plugins/wpgraphql-logging/bin/install-test-env.sh @@ -144,12 +144,12 @@ setup_file_permissions() { setup_plugin() { if [ "${SKIP_WP_SETUP}" = "true" ]; then - echo -e "$(warning_message "Skipping wpgraphql-Logging installation...")" + echo -e "$(warning_message "Skipping wpgraphql-logging installation...")" return 0 fi # Add this repo as a plugin to the repo - if [ ! -d $WORDPRESS_ROOT_DIR/wp-content/plugins/wpgraphql-Logging ]; then + if [ ! -d $WORDPRESS_ROOT_DIR/wp-content/plugins/wpgraphql-logging ]; then echo -e "$(status_message "Symlinking the plugin to the WordPress plugins directory...")" cd "$ORIGINAL_PATH" diff --git a/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh b/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh index 3742f9d8..749926fa 100755 --- a/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh +++ b/plugins/wpgraphql-logging/bin/local/run-unit-tests.sh @@ -24,4 +24,4 @@ if [[ "$1" == "coverage" ]]; then fi fi -docker exec $COVERAGE_ARG $COVERAGE_OUTPUT_ARG -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-Logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh +docker exec $COVERAGE_ARG $COVERAGE_OUTPUT_ARG -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh diff --git a/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh b/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh index 1ae261e7..3c0bddba 100644 --- a/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh +++ b/plugins/wpgraphql-logging/bin/local/setup-docker-env.sh @@ -114,6 +114,9 @@ else --admin_email=admin@example.com \ --allow-root + # Install WP-GraphQL plugin via WP-CLI + docker exec wpgraphql-logging-wordpress-1 wp plugin install wp-graphql --activate --allow-root + if [ $? -eq 0 ]; then echo "✓ WordPress installed successfully" else @@ -124,11 +127,13 @@ fi # Install and activate the plugin if needed echo "Checking plugin activation..." -if docker exec wpgraphql-logging-wordpress-1 wp plugin is-active wpgraphql-Logging --allow-root 2>/dev/null; then +if docker exec wpgraphql-logging-wordpress-1 wp plugin is-active wpgraphql-logging --allow-root 2>/dev/null; then echo "✓ Plugin is active" else echo "Activating plugin..." - docker exec wpgraphql-logging-wordpress-1 wp plugin activate wpgraphql-Logging --allow-root + # Install WP-GraphQL plugin via WP-CLI + docker exec wpgraphql-logging-wordpress-1 wp plugin install wp-graphql --activate --allow-root + docker exec wpgraphql-logging-wordpress-1 wp plugin activate wpgraphql-logging --allow-root fi # Verify coverage driver is working @@ -155,7 +160,7 @@ echo "" echo "🎉 Docker environment setup complete!" echo "" echo "You can now run tests with:" -echo " docker exec -e COVERAGE=1 -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-Logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh" +echo " docker exec -e COVERAGE=1 -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh" echo "" echo "Or without coverage:" -echo " docker exec -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-Logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh" +echo " docker exec -e SUITES=wpunit -w /var/www/html/wp-content/plugins/wpgraphql-logging wpgraphql-logging-wordpress-1 bin/run-codeception.sh" diff --git a/plugins/wpgraphql-logging/codeception.dist.yml b/plugins/wpgraphql-logging/codeception.dist.yml index 81f76e6c..b96fa262 100644 --- a/plugins/wpgraphql-logging/codeception.dist.yml +++ b/plugins/wpgraphql-logging/codeception.dist.yml @@ -51,7 +51,7 @@ coverage: - /vendor/* - /src/Templates/* show_only_summary: true - min_coverage: 10 #TODO change + min_coverage: 90 modules: config: REST: @@ -97,7 +97,9 @@ modules: adminEmail: "%WORDPRESS_ADMIN_EMAIL%" title: 'Test' plugins: + - wp-graphql/wp-graphql.php - wpgraphql-logging/wpgraphql-logging.php activatePlugins: + - wp-graphql/wp-graphql.php - wpgraphql-logging/wpgraphql-logging.php configFile: 'tests/_data/config.php' diff --git a/plugins/wpgraphql-logging/composer.json b/plugins/wpgraphql-logging/composer.json index d436cd03..57469607 100644 --- a/plugins/wpgraphql-logging/composer.json +++ b/plugins/wpgraphql-logging/composer.json @@ -1,7 +1,7 @@ { "name": "wpengine/wpgraphql-logging", "type": "wordpress-plugin", - "description": "A POC plugin for logging WPGraphQL queries.", + "description": "A plugin for logging WPGraphQL request lifecycle tp help with debugging and performance analysis for WPGraphQL queries.", "license": "GPL-2.0", "version": "0.0.1", "authors": [ @@ -26,27 +26,26 @@ "monolog" ], "require": { - "php": "^7.4 || ^8.0", - "monolog/monolog": "^2.10" + "php": "^8.1", + "monolog/monolog": "^3.9" }, "minimum-stability": "dev", "prefer-stable": true, "require-dev": { - "10up/wp_mock": "^1.1", "automattic/vipwpcs": "^3.0", - "codeception/lib-innerbrowser": "^1.0", - "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-rest": "^2.0", - "codeception/module-webdriver": "^1.0", + "codeception/lib-innerbrowser": "^4.0", + "codeception/module-asserts": "^3.0", + "codeception/module-cli": "^2.0", + "codeception/module-db": "^3.0", + "codeception/module-filesystem": "^3.0", + "codeception/module-phpbrowser": "^3.0", + "codeception/module-rest": "^3.0", + "codeception/module-webdriver": "^4.0", "codeception/util-universalframework": "^1.0", "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "humanmade/psalm-plugin-wordpress": "^3.1", "johnpbloch/wordpress-core": "^6.8", - "lucatume/wp-browser": "^3.5", + "lucatume/wp-browser": "^4.0", "mockery/mockery": "^1.5", "phpcompatibility/php-compatibility": "dev-develop as 9.99.99", "phpcompatibility/phpcompatibility-wp": "^2.0", @@ -63,7 +62,7 @@ }, "optimize-autoloader": true, "platform": { - "php": "7.4" + "php": "8.1" }, "preferred-install": "dist", "sort-packages": true diff --git a/plugins/wpgraphql-logging/composer.lock b/plugins/wpgraphql-logging/composer.lock index 8aa2b41d..14ff86bb 100644 --- a/plugins/wpgraphql-logging/composer.lock +++ b/plugins/wpgraphql-logging/composer.lock @@ -4,46 +4,47 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "68a7287de858f7c3a959e784310ef04d", + "content-hash": "247dce5261ceda43f94d7a8ce68deafd", "packages": [ { "name": "monolog/monolog", - "version": "2.10.0", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "5cf826f2991858b54d5c3809bee745560a1042a7" + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5cf826f2991858b54d5c3809bee745560a1042a7", - "reference": "5cf826f2991858b54d5c3809bee745560a1042a7", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", "shasum": "" }, "require": { - "php": ">=7.2", - "psr/log": "^1.0.1 || ^2.0 || ^3.0" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + "psr/log-implementation": "3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "aws/aws-sdk-php": "^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", - "guzzlehttp/guzzle": "^7.4", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpspec/prophecy": "^1.15", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.5.38 || ^9.6.19", - "predis/predis": "^1.1 || ^2.0", - "rollbar/rollbar": "^1.3 || ^2 || ^3", - "ruflin/elastica": "^7", - "swiftmailer/swiftmailer": "^5.3|^6.0", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -66,7 +67,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -94,7 +95,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.10.0" + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" }, "funding": [ { @@ -106,34 +107,34 @@ "type": "tidelift" } ], - "time": "2024-11-12T12:43:37+00:00" + "time": "2025-03-24T10:02:05+00:00" }, { "name": "psr/log", - "version": "1.1.4", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -154,66 +155,12 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2024-09-11T13:17:53+00:00" } ], "packages-dev": [ - { - "name": "10up/wp_mock", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/10up/wp_mock.git", - "reference": "f25b5895ed31bf5e7036fe0c666664364ae011c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/10up/wp_mock/zipball/f25b5895ed31bf5e7036fe0c666664364ae011c2", - "reference": "f25b5895ed31bf5e7036fe0c666664364ae011c2", - "shasum": "" - }, - "require": { - "antecedent/patchwork": "^2.1", - "mockery/mockery": "^1.6", - "php": ">=7.4 < 9", - "phpunit/phpunit": "^9.6" - }, - "require-dev": { - "behat/behat": "^v3.11.0", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7", - "friendsofphp/php-cs-fixer": "^3.4", - "php-coveralls/php-coveralls": "^v2.7", - "php-stubs/wordpress-globals": "^0.2", - "php-stubs/wordpress-stubs": "^6.3", - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "sebastian/comparator": "^4.0.8", - "sempro/phpunit-pretty-print": "^1.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "WP_Mock\\": "./php/WP_Mock" - }, - "classmap": [ - "php/WP_Mock.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "A mocking library to take the pain out of unit testing for WordPress", - "support": { - "issues": "https://github.com/10up/wp_mock/issues", - "source": "https://github.com/10up/wp_mock/tree/1.1.0" - }, - "time": "2025-03-12T00:36:13+00:00" - }, { "name": "amphp/amp", "version": "v2.6.4", @@ -374,54 +321,6 @@ ], "time": "2024-04-13T18:00:56+00:00" }, - { - "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": "automattic/vipwpcs", "version": "3.0.1", @@ -478,25 +377,31 @@ }, { "name": "behat/gherkin", - "version": "v4.10.0", + "version": "v4.14.0", "source": { "type": "git", "url": "https://github.com/Behat/Gherkin.git", - "reference": "cbb83c4c435dd8d05a161f2a5ae322e61b2f4db6" + "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/cbb83c4c435dd8d05a161f2a5ae322e61b2f4db6", - "reference": "cbb83c4c435dd8d05a161f2a5ae322e61b2f4db6", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", + "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", "shasum": "" }, "require": { - "php": "~7.2|~8.0" + "composer-runtime-api": "^2.2", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*" }, "require-dev": { - "cucumber/cucumber": "dev-gherkin-24.1.0", - "phpunit/phpunit": "~8|~9", - "symfony/yaml": "~3|~4|~5|~6|~7" + "cucumber/gherkin-monorepo": "dev-gherkin-v32.1.1", + "friendsofphp/php-cs-fixer": "^3.65", + "mikey179/vfsstream": "^1.6", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpunit/phpunit": "^10.5", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "symfony/yaml": "If you want to parse features, represented in YAML files" @@ -508,8 +413,8 @@ } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" + "psr-4": { + "Behat\\Gherkin\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -520,11 +425,11 @@ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "homepage": "https://everzet.com" } ], "description": "Gherkin DSL parser for PHP", - "homepage": "http://behat.org/", + "homepage": "https://behat.org/", "keywords": [ "BDD", "Behat", @@ -535,66 +440,86 @@ ], "support": { "issues": "https://github.com/Behat/Gherkin/issues", - "source": "https://github.com/Behat/Gherkin/tree/v4.10.0" + "source": "https://github.com/Behat/Gherkin/tree/v4.14.0" }, - "time": "2024-10-19T14:46:06+00:00" + "time": "2025-05-23T15:06:40+00:00" }, { "name": "codeception/codeception", - "version": "4.2.2", + "version": "5.2.2", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474" + "reference": "7d5e5b8736ee8eb9a3f08323a65fd7935270c8d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/b88014f3348c93f3df99dc6d0967b0dbfa804474", - "reference": "b88014f3348c93f3df99dc6d0967b0dbfa804474", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/7d5e5b8736ee8eb9a3f08323a65fd7935270c8d1", + "reference": "7d5e5b8736ee8eb9a3f08323a65fd7935270c8d1", "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", + "behat/gherkin": "^4.12", + "codeception/lib-asserts": "^2.0", + "codeception/stub": "^4.1", "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", + "php": "^8.1", + "phpunit/php-code-coverage": "^9.2 || ^10.0 || ^11.0 || ^12.0", + "phpunit/php-text-template": "^2.0 || ^3.0 || ^4.0 || ^5.0", + "phpunit/php-timer": "^5.0.3 || ^6.0 || ^7.0 || ^8.0", + "phpunit/phpunit": "^9.5.20 || ^10.0 || ^11.0 || ^12.0", + "psy/psysh": "^0.11.2 || ^0.12", + "sebastian/comparator": "^4.0.5 || ^5.0 || ^6.0 || ^7.0", + "sebastian/diff": "^4.0.3 || ^5.0 || ^6.0 || ^7.0", + "symfony/console": ">=5.4.24 <8.0", + "symfony/css-selector": ">=5.4.24 <8.0", + "symfony/event-dispatcher": ">=5.4.24 <8.0", + "symfony/finder": ">=5.4.24 <8.0", + "symfony/var-dumper": ">=5.4.24 <8.0", + "symfony/yaml": ">=5.4.24 <8.0" + }, + "conflict": { + "codeception/lib-innerbrowser": "<3.1.3", + "codeception/module-filesystem": "<3.0", + "codeception/module-phpbrowser": "<2.5" + }, + "replace": { + "codeception/phpunit-wrapper": "*" + }, + "require-dev": { + "codeception/lib-innerbrowser": "*@dev", + "codeception/lib-web": "*@dev", + "codeception/module-asserts": "*@dev", + "codeception/module-cli": "*@dev", + "codeception/module-db": "*@dev", + "codeception/module-filesystem": "*@dev", + "codeception/module-phpbrowser": "*@dev", "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" + "ext-simplexml": "*", + "jetbrains/phpstorm-attributes": "^1.0", + "symfony/dotenv": ">=5.4.24 <8.0", + "symfony/process": ">=5.4.24 <8.0", + "vlucas/phpdotenv": "^5.1" }, "suggest": { "codeception/specify": "BDD-style code blocks", "codeception/verify": "BDD-style assertions", - "hoa/console": "For interactive console functionality", + "ext-simplexml": "For loading params from XML files", "stecman/symfony-console-completion": "For BASH autocompletion", - "symfony/phpunit-bridge": "For phpunit-bridge support" + "symfony/dotenv": "For loading params from .env files", + "symfony/phpunit-bridge": "For phpunit-bridge support", + "vlucas/phpdotenv": "For loading params from .env files" }, "bin": [ "codecept" ], "type": "library", "extra": { - "branch-alias": [] + "branch-alias": { + "dev-main": "5.2.x-dev" + } }, "autoload": { "files": [ @@ -603,7 +528,10 @@ "psr-4": { "Codeception\\": "src/Codeception", "Codeception\\Extension\\": "ext" - } + }, + "classmap": [ + "src/PHPUnit/TestCase.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -612,8 +540,8 @@ "authors": [ { "name": "Michael Bodnarchuk", - "email": "davert@mail.ua", - "homepage": "https://codegyre.com" + "email": "davert.ua@gmail.com", + "homepage": "https://codeception.com" } ], "description": "BDD-style testing framework", @@ -627,7 +555,7 @@ ], "support": { "issues": "https://github.com/Codeception/Codeception/issues", - "source": "https://github.com/Codeception/Codeception/tree/4.2.2" + "source": "https://github.com/Codeception/Codeception/tree/5.2.2" }, "funding": [ { @@ -635,26 +563,26 @@ "type": "open_collective" } ], - "time": "2022-08-13T13:28:25+00:00" + "time": "2025-05-07T12:48:28+00:00" }, { "name": "codeception/lib-asserts", - "version": "1.13.2", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/Codeception/lib-asserts.git", - "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6" + "reference": "06750a60af3ebc66faab4313981accec1be4eefc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/184231d5eab66bc69afd6b9429344d80c67a33b6", - "reference": "184231d5eab66bc69afd6b9429344d80c67a33b6", + "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/06750a60af3ebc66faab4313981accec1be4eefc", + "reference": "06750a60af3ebc66faab4313981accec1be4eefc", "shasum": "" }, "require": { - "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3 | ^9.0", + "codeception/phpunit-wrapper": "^7.7.1 | ^8.0.3 | ^9.0", "ext-dom": "*", - "php": ">=5.6.0 <9.0" + "php": "^7.4 | ^8.0" }, "type": "library", "autoload": { @@ -687,38 +615,37 @@ ], "support": { "issues": "https://github.com/Codeception/lib-asserts/issues", - "source": "https://github.com/Codeception/lib-asserts/tree/1.13.2" + "source": "https://github.com/Codeception/lib-asserts/tree/2.2.0" }, - "time": "2020-10-21T16:26:20+00:00" + "time": "2025-03-10T20:41:33+00:00" }, { "name": "codeception/lib-innerbrowser", - "version": "1.5.1", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/Codeception/lib-innerbrowser.git", - "reference": "31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2" + "reference": "74476dd019ec7900b26b7dca91a42fdcb04e549f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2", - "reference": "31b4b56ad53c3464fcb2c0a14d55a51a201bd3c2", + "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/74476dd019ec7900b26b7dca91a42fdcb04e549f", + "reference": "74476dd019ec7900b26b7dca91a42fdcb04e549f", "shasum": "" }, "require": { - "codeception/codeception": "4.*@dev", + "codeception/codeception": "^5.0.8", + "codeception/lib-web": "^1.0.1", "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" + "php": "^8.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "symfony/browser-kit": "^4.4.24 || ^5.4 || ^6.0 || ^7.0", + "symfony/dom-crawler": "^4.4.30 || ^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "codeception/util-universalframework": "dev-master" + "codeception/util-universalframework": "^1.0" }, "type": "library", "autoload": { @@ -734,7 +661,7 @@ { "name": "Michael Bodnarchuk", "email": "davert@mail.ua", - "homepage": "http://codegyre.com" + "homepage": "https://codegyre.com" }, { "name": "Gintautas Miselis" @@ -747,31 +674,133 @@ ], "support": { "issues": "https://github.com/Codeception/lib-innerbrowser/issues", - "source": "https://github.com/Codeception/lib-innerbrowser/tree/1.5.1" + "source": "https://github.com/Codeception/lib-innerbrowser/tree/4.0.6" }, - "time": "2021-08-30T15:21:42+00:00" + "time": "2025-02-14T07:02:48+00:00" + }, + { + "name": "codeception/lib-web", + "version": "1.0.7", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-web.git", + "reference": "1444ccc9b1d6721f3ced8703c8f4a9041b80df93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-web/zipball/1444ccc9b1d6721f3ced8703c8f4a9041b80df93", + "reference": "1444ccc9b1d6721f3ced8703c8f4a9041b80df93", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "guzzlehttp/psr7": "^2.0", + "php": "^8.1", + "phpunit/phpunit": "^9.5 | ^10.0 | ^11.0 | ^12", + "symfony/css-selector": ">=4.4.24 <8.0" + }, + "conflict": { + "codeception/codeception": "<5.0.0-alpha3" + }, + "require-dev": { + "php-webdriver/webdriver": "^1.12" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gintautas Miselis" + } + ], + "description": "Library containing files used by module-webdriver and lib-innerbrowser or module-phpbrowser", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-web/issues", + "source": "https://github.com/Codeception/lib-web/tree/1.0.7" + }, + "time": "2025-02-09T12:05:55+00:00" + }, + { + "name": "codeception/lib-xml", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-xml.git", + "reference": "ba49213e60807e3612513f404a5c93aec63f4c72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-xml/zipball/ba49213e60807e3612513f404a5c93aec63f4c72", + "reference": "ba49213e60807e3612513f404a5c93aec63f4c72", + "shasum": "" + }, + "require": { + "codeception/lib-web": "^1.0.6", + "ext-dom": "*", + "php": "^8.0", + "symfony/css-selector": ">=4.4.24 <8.0" + }, + "conflict": { + "codeception/codeception": "<5.0.0-alpha3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gintautas Miselis" + } + ], + "description": "Files used by module-rest and module-soap", + "homepage": "https://codeception.com/", + "keywords": [ + "codeception" + ], + "support": { + "issues": "https://github.com/Codeception/lib-xml/issues", + "source": "https://github.com/Codeception/lib-xml/tree/1.0.3" + }, + "time": "2024-02-06T21:00:41+00:00" }, { "name": "codeception/module-asserts", - "version": "1.3.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/Codeception/module-asserts.git", - "reference": "59374f2fef0cabb9e8ddb53277e85cdca74328de" + "reference": "c58281f3d741599c81676bcb92996cf1e22d9ffd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-asserts/zipball/59374f2fef0cabb9e8ddb53277e85cdca74328de", - "reference": "59374f2fef0cabb9e8ddb53277e85cdca74328de", + "url": "https://api.github.com/repos/Codeception/module-asserts/zipball/c58281f3d741599c81676bcb92996cf1e22d9ffd", + "reference": "c58281f3d741599c81676bcb92996cf1e22d9ffd", "shasum": "" }, "require": { "codeception/codeception": "*@dev", - "codeception/lib-asserts": "^1.13.1", - "php": ">=5.6.0 <9.0" + "codeception/lib-asserts": "^2.0", + "php": "^8.1" }, "conflict": { - "codeception/codeception": "<4.0" + "codeception/codeception": "<5.0" }, "type": "library", "autoload": { @@ -804,27 +833,28 @@ ], "support": { "issues": "https://github.com/Codeception/module-asserts/issues", - "source": "https://github.com/Codeception/module-asserts/tree/1.3.1" + "source": "https://github.com/Codeception/module-asserts/tree/3.1.0" }, - "time": "2020-10-21T16:48:15+00:00" + "time": "2025-04-24T17:18:25+00:00" }, { "name": "codeception/module-cli", - "version": "1.1.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/Codeception/module-cli.git", - "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f" + "reference": "a3a101fae4049fa2f810107f7bd5db3b3266ce63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-cli/zipball/1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f", - "reference": "1f841ad4a1d43e5d9e60a43c4cc9e5af8008024f", + "url": "https://api.github.com/repos/Codeception/module-cli/zipball/a3a101fae4049fa2f810107f7bd5db3b3266ce63", + "reference": "a3a101fae4049fa2f810107f7bd5db3b3266ce63", "shasum": "" }, "require": { "codeception/codeception": "*@dev", - "php": ">=5.6.0 <9.0" + "codeception/module-asserts": "*", + "php": "^7.4 || ^8.0" }, "conflict": { "codeception/codeception": "<4.0" @@ -845,36 +875,43 @@ } ], "description": "Codeception module for testing basic shell commands and shell output", - "homepage": "http://codeception.com/", + "homepage": "https://codeception.com/", "keywords": [ "codeception" ], "support": { "issues": "https://github.com/Codeception/module-cli/issues", - "source": "https://github.com/Codeception/module-cli/tree/1.1.1" + "source": "https://github.com/Codeception/module-cli/tree/2.0.1" }, - "time": "2020-12-26T16:56:19+00:00" + "time": "2023-01-13T18:41:03+00:00" }, { "name": "codeception/module-db", - "version": "1.2.0", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/Codeception/module-db.git", - "reference": "04c3e66fbd3a3ced17fcccc49627f6393a97b04b" + "reference": "0ac08372c13f72c33745050e396317c8456a5f7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-db/zipball/04c3e66fbd3a3ced17fcccc49627f6393a97b04b", - "reference": "04c3e66fbd3a3ced17fcccc49627f6393a97b04b", + "url": "https://api.github.com/repos/Codeception/module-db/zipball/0ac08372c13f72c33745050e396317c8456a5f7b", + "reference": "0ac08372c13f72c33745050e396317c8456a5f7b", "shasum": "" }, "require": { "codeception/codeception": "*@dev", - "php": ">=5.6.0 <9.0" + "ext-json": "*", + "ext-mbstring": "*", + "ext-pdo": "*", + "php": "^8.0" }, "conflict": { - "codeception/codeception": "<4.0" + "codeception/codeception": "<5.0" + }, + "require-dev": { + "behat/gherkin": "~4.10.0", + "squizlabs/php_codesniffer": "*" }, "type": "library", "autoload": { @@ -895,7 +932,7 @@ } ], "description": "DB module for Codeception", - "homepage": "http://codeception.com/", + "homepage": "https://codeception.com/", "keywords": [ "codeception", "database-testing", @@ -903,31 +940,31 @@ ], "support": { "issues": "https://github.com/Codeception/module-db/issues", - "source": "https://github.com/Codeception/module-db/tree/1.2.0" + "source": "https://github.com/Codeception/module-db/tree/3.2.2" }, - "time": "2022-03-05T19:38:40+00:00" + "time": "2025-03-03T08:10:27+00:00" }, { "name": "codeception/module-filesystem", - "version": "1.0.3", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/Codeception/module-filesystem.git", - "reference": "781be167fb1557bfc9b61e0a4eac60a32c534ec1" + "reference": "0fd78cf941cb72dc2a650c6132c5999c26ad4f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-filesystem/zipball/781be167fb1557bfc9b61e0a4eac60a32c534ec1", - "reference": "781be167fb1557bfc9b61e0a4eac60a32c534ec1", + "url": "https://api.github.com/repos/Codeception/module-filesystem/zipball/0fd78cf941cb72dc2a650c6132c5999c26ad4f9a", + "reference": "0fd78cf941cb72dc2a650c6132c5999c26ad4f9a", "shasum": "" }, "require": { - "codeception/codeception": "^4.0", - "php": ">=5.6.0 <9.0", - "symfony/finder": ">=2.7 <6.0" + "codeception/codeception": "*@dev", + "php": "^8.0", + "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0" }, "conflict": { - "codeception/codeception": "<4.0" + "codeception/codeception": "<5.0" }, "type": "library", "autoload": { @@ -948,42 +985,47 @@ } ], "description": "Codeception module for testing local filesystem", - "homepage": "http://codeception.com/", + "homepage": "https://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" + "source": "https://github.com/Codeception/module-filesystem/tree/3.0.1" }, - "time": "2020-10-24T14:46:40+00:00" + "time": "2023-12-08T19:23:28+00:00" }, { "name": "codeception/module-phpbrowser", - "version": "1.0.3", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/Codeception/module-phpbrowser.git", - "reference": "8ba6bede11d0914e74d98691f427fd8f397f192e" + "reference": "a972411f60cd00d00d5e5e3b35496ba4a23bcffc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-phpbrowser/zipball/8ba6bede11d0914e74d98691f427fd8f397f192e", - "reference": "8ba6bede11d0914e74d98691f427fd8f397f192e", + "url": "https://api.github.com/repos/Codeception/module-phpbrowser/zipball/a972411f60cd00d00d5e5e3b35496ba4a23bcffc", + "reference": "a972411f60cd00d00d5e5e3b35496ba4a23bcffc", "shasum": "" }, "require": { - "codeception/codeception": "^4.1", - "codeception/lib-innerbrowser": "^1.3", - "guzzlehttp/guzzle": "^6.3|^7.0", - "php": ">=5.6.0 <9.0" + "codeception/codeception": "*@dev", + "codeception/lib-innerbrowser": "*@dev", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.4", + "php": "^8.0", + "symfony/browser-kit": "^5.4 || ^6.0 || ^7.0" }, "conflict": { - "codeception/codeception": "<4.0" + "codeception/codeception": "<5.0", + "codeception/lib-innerbrowser": "<3.0" }, "require-dev": { - "codeception/module-rest": "^1.0" + "aws/aws-sdk-php": "^3.199", + "codeception/module-rest": "^2.0 || *@dev", + "ext-curl": "*" }, "suggest": { "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" @@ -1007,7 +1049,7 @@ } ], "description": "Codeception module for testing web application over HTTP", - "homepage": "http://codeception.com/", + "homepage": "https://codeception.com/", "keywords": [ "codeception", "functional-testing", @@ -1015,36 +1057,39 @@ ], "support": { "issues": "https://github.com/Codeception/module-phpbrowser/issues", - "source": "https://github.com/Codeception/module-phpbrowser/tree/1.0.3" + "source": "https://github.com/Codeception/module-phpbrowser/tree/3.0.1" }, - "time": "2022-05-21T13:50:41+00:00" + "time": "2023-12-08T19:41:28+00:00" }, { "name": "codeception/module-rest", - "version": "2.0.3", + "version": "3.4.1", "source": { "type": "git", "url": "https://github.com/Codeception/module-rest.git", - "reference": "ee4ea06cd8a5057f24f37f8bf25b6815ddc77840" + "reference": "5db3a2e62ce6948d1822709c034a22fa1b1f2309" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-rest/zipball/ee4ea06cd8a5057f24f37f8bf25b6815ddc77840", - "reference": "ee4ea06cd8a5057f24f37f8bf25b6815ddc77840", + "url": "https://api.github.com/repos/Codeception/module-rest/zipball/5db3a2e62ce6948d1822709c034a22fa1b1f2309", + "reference": "5db3a2e62ce6948d1822709c034a22fa1b1f2309", "shasum": "" }, "require": { - "codeception/codeception": "^4.1", + "codeception/codeception": "^5.0.8", + "codeception/lib-xml": "^1.0", "ext-dom": "*", "ext-json": "*", - "justinrainbow/json-schema": "~5.2.9", - "php": "^7.4 | ^8.0", - "softcreatr/jsonpath": "^0.5 | ^0.7 | ^0.8" + "justinrainbow/json-schema": "^5.2.9 || ^6", + "php": "^8.1", + "softcreatr/jsonpath": "^0.8 || ^0.9 || ^0.10" }, "require-dev": { - "codeception/lib-innerbrowser": "^2.0", + "codeception/lib-innerbrowser": "^3.0 | ^4.0", "codeception/stub": "^4.0", - "codeception/util-universalframework": "^1.0" + "codeception/util-universalframework": "^1.0", + "ext-libxml": "*", + "ext-simplexml": "*" }, "suggest": { "aws/aws-sdk-php": "For using AWS Auth" @@ -1072,28 +1117,33 @@ ], "support": { "issues": "https://github.com/Codeception/module-rest/issues", - "source": "https://github.com/Codeception/module-rest/tree/2.0.3" + "source": "https://github.com/Codeception/module-rest/tree/3.4.1" }, - "time": "2023-03-10T19:23:22+00:00" + "time": "2025-03-25T23:04:38+00:00" }, { "name": "codeception/module-webdriver", - "version": "1.4.1", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/Codeception/module-webdriver.git", - "reference": "e22ac7da756df659df6dd4fac2dff9c859e30131" + "reference": "551d214ddd57a9539acf1123d7c56ec82b1004df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/e22ac7da756df659df6dd4fac2dff9c859e30131", - "reference": "e22ac7da756df659df6dd4fac2dff9c859e30131", + "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/551d214ddd57a9539acf1123d7c56ec82b1004df", + "reference": "551d214ddd57a9539acf1123d7c56ec82b1004df", "shasum": "" }, "require": { - "codeception/codeception": "^4.0", - "php": ">=5.6.0 <9.0", - "php-webdriver/webdriver": "^1.8.0" + "codeception/codeception": "^5.0.8", + "codeception/lib-web": "^1.0.1", + "codeception/stub": "^4.0", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.1", + "php-webdriver/webdriver": "^1.14.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0" }, "suggest": { "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" @@ -1120,7 +1170,7 @@ } ], "description": "WebDriver module for Codeception", - "homepage": "http://codeception.com/", + "homepage": "https://codeception.com/", "keywords": [ "acceptance-testing", "browser-testing", @@ -1128,77 +1178,30 @@ ], "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" + "source": "https://github.com/Codeception/module-webdriver/tree/4.0.3" }, - "abandoned": true, - "time": "2022-05-23T06:24:11+00:00" + "time": "2025-02-14T07:10:05+00:00" }, { "name": "codeception/stub", - "version": "4.0.2", + "version": "4.1.4", "source": { "type": "git", "url": "https://github.com/Codeception/Stub.git", - "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d" + "reference": "6ce453073a0c220b254dd7f4383645615e4071c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Stub/zipball/18a148dacd293fc7b044042f5aa63a82b08bff5d", - "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/6ce453073a0c220b254dd7f4383645615e4071c3", + "reference": "6ce453073a0c220b254dd7f4383645615e4071c3", "shasum": "" }, "require": { "php": "^7.4 | ^8.0", - "phpunit/phpunit": "^8.4 | ^9.0 | ^10.0 | 10.0.x-dev" + "phpunit/phpunit": "^8.4 | ^9.0 | ^10.0 | ^11 | ^12" + }, + "conflict": { + "codeception/codeception": "<5.0.6" }, "require-dev": { "consolidation/robo": "^3.0" @@ -1216,9 +1219,9 @@ "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" + "source": "https://github.com/Codeception/Stub/tree/4.1.4" }, - "time": "2022-01-31T19:25:15+00:00" + "time": "2025-02-14T06:56:33+00:00" }, { "name": "codeception/util-universalframework", @@ -1408,48 +1411,48 @@ }, { "name": "composer/composer", - "version": "2.7.7", + "version": "2.8.10", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "291942978f39435cf904d33739f98d7d4eca7b23" + "reference": "53834f587d7ab2527eb237459d7b94d1fb9d4c5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/291942978f39435cf904d33739f98d7d4eca7b23", - "reference": "291942978f39435cf904d33739f98d7d4eca7b23", + "url": "https://api.github.com/repos/composer/composer/zipball/53834f587d7ab2527eb237459d7b94d1fb9d4c5a", + "reference": "53834f587d7ab2527eb237459d7b94d1fb9d4c5a", "shasum": "" }, "require": { - "composer/ca-bundle": "^1.0", - "composer/class-map-generator": "^1.3.3", + "composer/ca-bundle": "^1.5", + "composer/class-map-generator": "^1.4.0", "composer/metadata-minifier": "^1.0", - "composer/pcre": "^2.1 || ^3.1", + "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.2.11", + "justinrainbow/json-schema": "^6.3.1", "php": "^7.2.5 || ^8.0", "psr/log": "^1.0 || ^2.0 || ^3.0", - "react/promise": "^2.8 || ^3", + "react/promise": "^2.11 || ^3.2", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.2", "seld/signal-handler": "^2.0", - "symfony/console": "^5.4.11 || ^6.0.11 || ^7", - "symfony/filesystem": "^5.4 || ^6.0 || ^7", - "symfony/finder": "^5.4 || ^6.0 || ^7", + "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 || ^6.0 || ^7" + "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3" }, "require-dev": { - "phpstan/phpstan": "^1.11.0", + "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.1 || ^7.0.1" + "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", @@ -1467,7 +1470,7 @@ ] }, "branch-alias": { - "dev-main": "2.7-dev" + "dev-main": "2.8-dev" } }, "autoload": { @@ -1502,7 +1505,7 @@ "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.7.7" + "source": "https://github.com/composer/composer/tree/2.8.10" }, "funding": [ { @@ -1518,7 +1521,7 @@ "type": "tidelift" } ], - "time": "2024-06-10T20:11:12+00:00" + "time": "2025-07-10T17:08:33+00:00" }, { "name": "composer/metadata-minifier", @@ -1897,16 +1900,16 @@ }, { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.1.1", + "version": "v1.1.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "6e0fa428497bf560152ee73ffbb8af5c6a56b0dd" + "reference": "e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/6e0fa428497bf560152ee73ffbb8af5c6a56b0dd", - "reference": "6e0fa428497bf560152ee73ffbb8af5c6a56b0dd", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1", + "reference": "e9cf5e4bbf7eeaf9ef5db34938942602838fc2b1", "shasum": "" }, "require": { @@ -1989,7 +1992,7 @@ "type": "thanks_dev" } ], - "time": "2025-06-27T17:24:01+00:00" + "time": "2025-07-17T20:45:56+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -2077,74 +2080,68 @@ "time": "2025-04-07T20:06:18+00:00" }, { - "name": "doctrine/instantiator", - "version": "1.5.0", + "name": "druidfi/mysqldump-php", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "url": "https://github.com/druidfi/mysqldump-php.git", + "reference": "df0e3bc3f8a47ea79c5c8e14594a8720034ae24f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/druidfi/mysqldump-php/zipball/df0e3bc3f8a47ea79c5c8e14594a8720034ae24f", + "reference": "df0e3bc3f8a47ea79c5c8e14594a8720034ae24f", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "composer-runtime-api": "^2", + "ext-pdo": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpunit/phpunit": "^8.5.15 || ^9", + "squizlabs/php_codesniffer": "3.*" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Druidfi\\Mysqldump\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "GPL-3.0-or-later" ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" + "name": "Druid.fi", + "homepage": "https://github.com/druidfi" + }, + { + "name": "Diego Torres", + "homepage": "https://github.com/ifsnop", + "role": "Developer" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "description": "PHP version of mysqldump cli that comes with MySQL", + "homepage": "https://github.com/druidfi/mysqldump-php", "keywords": [ - "constructor", - "instantiate" + "PHP7", + "database", + "mariadb", + "mysql", + "mysql-backup", + "mysqldump", + "pdo", + "php", + "php8", + "sql" ], "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "issues": "https://github.com/druidfi/mysqldump-php/issues", + "source": "https://github.com/druidfi/mysqldump-php/tree/1.1.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:15:36+00:00" + "time": "2024-03-03T10:20:17+00:00" }, { "name": "eftec/bladeone", @@ -2522,6 +2519,68 @@ ], "time": "2025-03-19T11:14:02+00:00" }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.9.3", @@ -2959,77 +3018,18 @@ }, "time": "2024-04-01T10:36:11+00:00" }, - { - "name": "ifsnop/mysqldump-php", - "version": "v2.12", - "source": { - "type": "git", - "url": "https://github.com/ifsnop/mysqldump-php.git", - "reference": "2d3a43fc0c49f23bf7dee392b0dd1f8c799f89d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ifsnop/mysqldump-php/zipball/2d3a43fc0c49f23bf7dee392b0dd1f8c799f89d3", - "reference": "2d3a43fc0c49f23bf7dee392b0dd1f8c799f89d3", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "4.8.36", - "squizlabs/php_codesniffer": "1.*" - }, - "type": "library", - "autoload": { - "psr-4": { - "Ifsnop\\": "src/Ifsnop/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-3.0-or-later" - ], - "authors": [ - { - "name": "Diego Torres", - "homepage": "https://github.com/ifsnop", - "role": "Developer" - } - ], - "description": "PHP version of mysqldump cli that comes with MySQL", - "homepage": "https://github.com/ifsnop/mysqldump-php", - "keywords": [ - "PHP7", - "database", - "hhvm", - "mariadb", - "mysql", - "mysql-backup", - "mysqldump", - "pdo", - "php", - "php5", - "sql" - ], - "support": { - "issues": "https://github.com/ifsnop/mysqldump-php/issues", - "source": "https://github.com/ifsnop/mysqldump-php/tree/v2.12" - }, - "time": "2023-04-12T07:43:14+00:00" - }, { "name": "johnpbloch/wordpress-core", - "version": "6.8.1", + "version": "6.8.2", "source": { "type": "git", "url": "https://github.com/johnpbloch/wordpress-core.git", - "reference": "702c3bda87abb47ae43f90c7b8868cf0b7dff1e2" + "reference": "316a8fe38b6dde4e4f399946809f040462038403" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/702c3bda87abb47ae43f90c7b8868cf0b7dff1e2", - "reference": "702c3bda87abb47ae43f90c7b8868cf0b7dff1e2", + "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/316a8fe38b6dde4e4f399946809f040462038403", + "reference": "316a8fe38b6dde4e4f399946809f040462038403", "shasum": "" }, "require": { @@ -3037,7 +3037,7 @@ "php": ">=7.2.24" }, "provide": { - "wordpress/core-implementation": "6.8.1" + "wordpress/core-implementation": "6.8.2" }, "type": "wordpress-core", "notification-url": "https://packagist.org/downloads/", @@ -3064,29 +3064,34 @@ "source": "https://core.trac.wordpress.org/browser", "wiki": "https://codex.wordpress.org/" }, - "time": "2025-04-30T16:52:49+00:00" + "time": "2025-07-15T15:32:59+00:00" }, { "name": "justinrainbow/json-schema", - "version": "v5.2.13", + "version": "6.4.2", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793" + "reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793", - "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ce1fd2d47799bb60668643bc6220f6278a4c1d02", + "reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02", "shasum": "" }, "require": { - "php": ">=5.3.3" + "ext-json": "*", + "marc-mabe/php-enum": "^4.0", + "php": "^7.2 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", + "friendsofphp/php-cs-fixer": "3.3.0", "json-schema/json-schema-test-suite": "1.2.0", - "phpunit/phpunit": "^4.8.35" + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" }, "bin": [ "bin/validate-json" @@ -3094,7 +3099,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0.x-dev" + "dev-master": "6.x-dev" } }, "autoload": { @@ -3125,59 +3130,62 @@ } ], "description": "A library to validate a json schema.", - "homepage": "https://github.com/justinrainbow/json-schema", + "homepage": "https://github.com/jsonrainbow/json-schema", "keywords": [ "json", "schema" ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/v5.2.13" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.4.2" }, - "time": "2023-09-26T02:20:38+00:00" + "time": "2025-06-03T18:27:04+00:00" }, { "name": "lucatume/wp-browser", - "version": "3.7.13", + "version": "4.5.4", "source": { "type": "git", "url": "https://github.com/lucatume/wp-browser.git", - "reference": "b08d668b44d4a840189b5cb3ba690aa56f5b4f3f" + "reference": "82e713954afcea9b1515ba0c472fe5fab1f8bb91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lucatume/wp-browser/zipball/b08d668b44d4a840189b5cb3ba690aa56f5b4f3f", - "reference": "b08d668b44d4a840189b5cb3ba690aa56f5b4f3f", + "url": "https://api.github.com/repos/lucatume/wp-browser/zipball/82e713954afcea9b1515ba0c472fe5fab1f8bb91", + "reference": "82e713954afcea9b1515ba0c472fe5fab1f8bb91", "shasum": "" }, "require": { - "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/codeception": "^5.0", + "codeception/module-asserts": "^2.0 || ^3.0", + "codeception/module-cli": "^2.0 || ^3.0", + "codeception/module-db": "^2.0 || ^3.0", + "codeception/module-filesystem": "^2.0 || ^3.0", + "codeception/module-phpbrowser": "^2.0 || ^3.0", + "codeception/module-webdriver": "^2.0 || ^3.0 || ^4.0", "composer-runtime-api": "^2.2", + "druidfi/mysqldump-php": "^1.1", "ext-curl": "*", "ext-fileinfo": "*", "ext-json": "*", "ext-mysqli": "*", "ext-pdo": "*", "ext-zip": "*", - "ifsnop/mysqldump-php": "^2.12", - "php": ">=7.1 <8.0", - "symfony/filesystem": ">=3.4.47 <7.0", - "symfony/process": ">=3.4.47 <7.0", - "vlucas/phpdotenv": "^4.3" + "php": "^8.0", + "phpunit/phpunit": "<12.0.0", + "symfony/filesystem": ">=4.4.24 <8.0", + "symfony/process": ">=4.4.24 <8.0", + "vlucas/phpdotenv": "^5.0" }, "require-dev": { "gumlet/php-image-resize": "^1.6", - "lucatume/codeception-snapshot-assertions": "^0.4", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan-symfony": "^0.12.44", + "lucatume/codeception-snapshot-assertions": "^1.3.0", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "1.10.56", + "phpstan/phpstan-symfony": "^1.3", + "rector/rector": "0.19.8", "squizlabs/php_codesniffer": "^3.7", - "szepeviktor/phpstan-wordpress": "^0.7" + "szepeviktor/phpstan-wordpress": "^1.3" }, "suggest": { "ext-pdo_sqlite": "For SQLite database support.", @@ -3190,9 +3198,8 @@ "autoload": { "files": [ "src/version-4-aliases.php", - "src/Deprecated/deprecated-functions.php", - "src/functions.php", - "src/shim.php" + "src/deprecated-functions.php", + "src/functions.php" ], "psr-4": { "Hautelook\\Phpass\\": "includes/Hautelook/Phpass", @@ -3200,6 +3207,7 @@ "src/", "src/Deprecated" ], + "Codeception\\Extension\\": "src/Extension", "lucatume\\WPBrowser\\Opis\\Closure\\": "includes/opis/closure/src" } }, @@ -3215,23 +3223,163 @@ "role": "Developer" } ], - "description": "A set of Codeception modules to test WordPress projects.", - "homepage": "https://github.com/lucatume/wp-browser", + "description": "A set of Codeception modules to test WordPress projects.", + "homepage": "https://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/4.5.4" + }, + "funding": [ + { + "url": "https://github.com/lucatume", + "type": "github" + } + ], + "time": "2025-06-17T21:01:53+00:00" + }, + { + "name": "marc-mabe/php-enum", + "version": "v4.7.1", + "source": { + "type": "git", + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "shasum": "" + }, + "require": { + "ext-reflection": "*", + "php": "^7.1 | ^8.0" + }, + "require-dev": { + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" + } + }, + "autoload": { + "psr-4": { + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" + } + ], + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1" + }, + "time": "2024-11-28T04:54:44+00:00" + }, + { + "name": "masterminds/html5", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", "keywords": [ - "codeception", - "wordpress" + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" ], "support": { - "issues": "https://github.com/lucatume/wp-browser/issues", - "source": "https://github.com/lucatume/wp-browser/tree/3.7.13" + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" }, - "funding": [ - { - "url": "https://github.com/lucatume", - "type": "github" - } - ], - "time": "2025-06-20T08:50:06+00:00" + "time": "2024-03-31T07:05:07+00:00" }, { "name": "mck89/peast", @@ -3796,16 +3944,16 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.8.1", + "version": "v6.8.2", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "92e444847d94f7c30f88c60004648f507688acd5" + "reference": "9c8e22e437463197c1ec0d5eaa9ddd4a0eb6d7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/92e444847d94f7c30f88c60004648f507688acd5", - "reference": "92e444847d94f7c30f88c60004648f507688acd5", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/9c8e22e437463197c1ec0d5eaa9ddd4a0eb6d7f8", + "reference": "9c8e22e437463197c1ec0d5eaa9ddd4a0eb6d7f8", "shasum": "" }, "conflict": { @@ -3813,7 +3961,7 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "nikic/php-parser": "^5.4", + "nikic/php-parser": "^5.5", "php": "^7.4 || ^8.0", "php-stubs/generator": "^0.8.3", "phpdocumentor/reflection-docblock": "^5.4.1", @@ -3841,9 +3989,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.8.1" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.8.2" }, - "time": "2025-05-02T12:33:34+00:00" + "time": "2025-07-16T06:41:00+00:00" }, { "name": "php-stubs/wp-cli-stubs", @@ -4623,16 +4771,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.1.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", "shasum": "" }, "require": { @@ -4664,22 +4812,22 @@ "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.1.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" }, - "time": "2025-02-19T13:28:12+00:00" + "time": "2025-07-13T07:04:09+00:00" }, { "name": "phpstan/phpstan", - "version": "2.1.17", + "version": "2.1.19", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" + "reference": "473a8c30e450d87099f76313edcbb90852f9afdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/473a8c30e450d87099f76313edcbb90852f9afdf", + "reference": "473a8c30e450d87099f76313edcbb90852f9afdf", "shasum": "" }, "require": { @@ -4724,20 +4872,20 @@ "type": "github" } ], - "time": "2025-05-21T20:55:28+00:00" + "time": "2025-07-21T19:58:24+00:00" }, { "name": "phpstan/phpstan-strict-rules", - "version": "2.0.4", + "version": "2.0.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a" + "reference": "f9f77efa9de31992a832ff77ea52eb42d675b094" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", - "reference": "3e139cbe67fafa3588e1dbe27ca50f31fdb6236a", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/f9f77efa9de31992a832ff77ea52eb42d675b094", + "reference": "f9f77efa9de31992a832ff77ea52eb42d675b094", "shasum": "" }, "require": { @@ -4770,22 +4918,22 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.4" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.6" }, - "time": "2025-03-18T11:42:40+00:00" + "time": "2025-07-21T12:19:29+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.32", + "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { @@ -4793,18 +4941,18 @@ "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", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -4813,7 +4961,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -4842,7 +4990,7 @@ "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" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -4850,32 +4998,32 @@ "type": "github" } ], - "time": "2024-08-22T04:23:01+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -4902,7 +5050,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -4910,28 +5059,28 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -4939,7 +5088,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -4965,7 +5114,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -4973,32 +5122,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -5024,7 +5173,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -5032,32 +5182,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -5083,7 +5233,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -5091,54 +5241,52 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.23", + "version": "10.5.48", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" + "reference": "6e0a2bc39f6fae7617989d690d76c48e6d2eb541" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6e0a2bc39f6fae7617989d690d76c48e6d2eb541", + "reference": "6e0a2bc39f6fae7617989d690d76c48e6d2eb541", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.1", + "myclabs/deep-copy": "^1.13.3", "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" + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.3", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "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" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -5146,7 +5294,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -5178,7 +5326,7 @@ "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.23" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.48" }, "funding": [ { @@ -5202,26 +5350,31 @@ "type": "tidelift" } ], - "time": "2025-05-02T06:40:34+00:00" + "time": "2025-07-11T04:07:17+00:00" }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -5248,9 +5401,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -5462,6 +5615,85 @@ }, "time": "2023-04-04T09:54:51+00:00" }, + { + "name": "psy/psysh", + "version": "v0.12.9", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "1b801844becfe648985372cb4b12ad6840245ace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1b801844becfe648985372cb4b12ad6840245ace", + "reference": "1b801844becfe648985372cb4b12ad6840245ace", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.9" + }, + "time": "2025-06-23T02:35:06+00:00" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", @@ -5581,28 +5813,28 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -5625,7 +5857,8 @@ "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" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -5633,32 +5866,32 @@ "type": "github" } ], - "time": "2024-03-02T06:27:43+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -5681,7 +5914,7 @@ "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" + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -5689,32 +5922,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -5736,7 +5969,7 @@ "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" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -5744,34 +5977,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -5810,7 +6045,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" }, "funding": [ { @@ -5818,33 +6054,33 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2024-10-18T14:56:07+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -5867,7 +6103,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { @@ -5875,33 +6112,33 @@ "type": "github" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -5933,7 +6170,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -5941,27 +6179,27 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -5969,7 +6207,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -5988,7 +6226,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -5996,7 +6234,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -6004,34 +6243,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -6073,7 +6312,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" }, "funding": [ { @@ -6081,38 +6321,35 @@ "type": "github" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2024-03-02T07:17:12+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -6131,13 +6368,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://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" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -6145,33 +6383,33 @@ "type": "github" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.4", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -6194,7 +6432,8 @@ "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" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -6202,34 +6441,34 @@ "type": "github" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -6251,7 +6490,7 @@ "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" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -6259,32 +6498,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -6306,7 +6545,7 @@ "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" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -6314,32 +6553,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -6369,61 +6608,7 @@ "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" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { @@ -6431,32 +6616,32 @@ "type": "github" } ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -6479,7 +6664,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -6487,29 +6672,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -6532,7 +6717,7 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -6540,7 +6725,7 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { "name": "seld/jsonlint", @@ -6839,29 +7024,29 @@ }, { "name": "softcreatr/jsonpath", - "version": "0.7.6", + "version": "0.10.0", "source": { "type": "git", "url": "https://github.com/SoftCreatR/JSONPath.git", - "reference": "e04c02cb78bcc242c69d17dac5b29436bf3e1076" + "reference": "74f0b330a98135160db947ba7bc65216b64a0c86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/e04c02cb78bcc242c69d17dac5b29436bf3e1076", - "reference": "e04c02cb78bcc242c69d17dac5b29436bf3e1076", + "url": "https://api.github.com/repos/SoftCreatR/JSONPath/zipball/74f0b330a98135160db947ba7bc65216b64a0c86", + "reference": "74f0b330a98135160db947ba7bc65216b64a0c86", "shasum": "" }, "require": { "ext-json": "*", - "php": ">=7.1,<8.0" + "php": "8.1 - 8.4" }, "replace": { "flow/jsonpath": "*" }, "require-dev": { - "phpunit/phpunit": ">=7.0", - "roave/security-advisories": "dev-latest", - "squizlabs/php_codesniffer": "^3.5" + "friendsofphp/php-cs-fixer": "^3.58", + "phpunit/phpunit": "10 - 12", + "squizlabs/php_codesniffer": "^3.10" }, "type": "library", "autoload": { @@ -6904,33 +7089,37 @@ "type": "github" } ], - "time": "2022-09-27T09:27:12+00:00" + "time": "2025-03-22T00:28:17+00:00" }, { "name": "spatie/array-to-xml", - "version": "2.17.1", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46" + "reference": "7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", - "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67", + "reference": "7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67", "shasum": "" }, "require": { "ext-dom": "*", - "php": "^7.4|^8.0" + "php": "^8.0" }, "require-dev": { "mockery/mockery": "^1.2", "pestphp/pest": "^1.21", - "phpunit/phpunit": "^9.0", "spatie/pest-plugin-snapshots": "^1.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { "Spatie\\ArrayToXml\\": "src" @@ -6956,7 +7145,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/2.17.1" + "source": "https://github.com/spatie/array-to-xml/tree/3.4.0" }, "funding": [ { @@ -6968,7 +7157,7 @@ "type": "github" } ], - "time": "2022-12-26T08:22:07+00:00" + "time": "2024-12-16T12:45:15+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -7056,31 +7245,27 @@ }, { "name": "symfony/browser-kit", - "version": "v5.4.45", + "version": "v6.4.19", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "03cce39764429e07fbab9b989a1182a24578341d" + "reference": "ce95f3e3239159e7fa3be7690c6ce95a4714637f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/03cce39764429e07fbab9b989a1182a24578341d", - "reference": "03cce39764429e07fbab9b989a1182a24578341d", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/ce95f3e3239159e7fa3be7690c6ce95a4714637f", + "reference": "ce95f3e3239159e7fa3be7690c6ce95a4714637f", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/dom-crawler": "^5.4|^6.0|^7.0" }, "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": "" + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7108,7 +7293,7 @@ "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" + "source": "https://github.com/symfony/browser-kit/tree/v6.4.19" }, "funding": [ { @@ -7124,56 +7309,51 @@ "type": "tidelift" } ], - "time": "2024-10-22T13:05:35+00:00" + "time": "2025-02-14T11:23:16+00:00" }, { "name": "symfony/console", - "version": "v5.4.47", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", - "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93", + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^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" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.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" + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.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": "" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7207,7 +7387,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.47" + "source": "https://github.com/symfony/console/tree/v6.4.23" }, "funding": [ { @@ -7223,25 +7403,24 @@ "type": "tidelift" } ], - "time": "2024-11-06T11:30:55+00:00" + "time": "2025-06-27T19:37:22+00:00" }, { "name": "symfony/css-selector", - "version": "v5.4.45", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097" + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/4f7f3c35fba88146b56d0025d20ace3f3901f097", - "reference": "4f7f3c35fba88146b56d0025d20ace3f3901f097", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -7273,7 +7452,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.45" + "source": "https://github.com/symfony/css-selector/tree/v6.4.13" }, "funding": [ { @@ -7289,24 +7468,24 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.4", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", - "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { @@ -7315,7 +7494,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -7340,7 +7519,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -7356,38 +7535,30 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/dom-crawler", - "version": "v5.4.48", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "b57df76f4757a9a8dfbb57ba48d7780cc20776c6" + "reference": "22210aacb35dbadd772325d759d17bce2374a84d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b57df76f4757a9a8dfbb57ba48d7780cc20776c6", - "reference": "b57df76f4757a9a8dfbb57ba48d7780cc20776c6", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/22210aacb35dbadd772325d759d17bce2374a84d", + "reference": "22210aacb35dbadd772325d759d17bce2374a84d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "masterminds/html5": "^2.6", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "masterminds/html5": "<2.6" + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "masterminds/html5": "^2.6", - "symfony/css-selector": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/css-selector": "" + "symfony/css-selector": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7415,7 +7586,7 @@ "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" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.23" }, "funding": [ { @@ -7431,48 +7602,43 @@ "type": "tidelift" } ], - "time": "2024-11-13T14:36:38+00:00" + "time": "2025-06-13T12:10:00+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.45", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9" + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9", - "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.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": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7500,7 +7666,7 @@ "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" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.13" }, "funding": [ { @@ -7516,29 +7682,26 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.4", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", - "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "thanks": { @@ -7546,7 +7709,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -7579,7 +7742,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -7595,30 +7758,29 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", - "version": "v5.4.45", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "57c8294ed37d4a055b77057827c67f9558c95c54" + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54", - "reference": "57c8294ed37d4a055b77057827c67f9558c95c54", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^5.4|^6.4" + "symfony/process": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -7646,7 +7808,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.45" + "source": "https://github.com/symfony/filesystem/tree/v6.4.13" }, "funding": [ { @@ -7662,26 +7824,27 @@ "type": "tidelift" } ], - "time": "2024-10-22T13:05:35+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/finder", - "version": "v5.4.45", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "63741784cd7b9967975eec610b256eed3ede022b" + "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", - "reference": "63741784cd7b9967975eec610b256eed3ede022b", + "url": "https://api.github.com/repos/symfony/finder/zipball/1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", + "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0|^7.0" }, "type": "library", "autoload": { @@ -7709,7 +7872,7 @@ "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" + "source": "https://github.com/symfony/finder/tree/v6.4.17" }, "funding": [ { @@ -7725,7 +7888,7 @@ "type": "tidelift" } ], - "time": "2024-09-28T13:32:08+00:00" + "time": "2024-12-29T13:51:37+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8280,29 +8443,26 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.4", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", - "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "thanks": { @@ -8310,13 +8470,16 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8343,7 +8506,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -8359,38 +8522,38 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/string", - "version": "v5.4.47", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", - "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", + "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", "shasum": "" }, "require": { - "php": ">=7.2.5", + "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", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "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": { @@ -8429,7 +8592,92 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.47" + "source": "https://github.com/symfony/string/tree/v6.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-18T15:23:29+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.4.23", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "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 mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.23" }, "funding": [ { @@ -8445,35 +8693,32 @@ "type": "tidelift" } ], - "time": "2024-11-10T20:33:58+00:00" + "time": "2025-06-27T15:05:27+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.45", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a454d47278cc16a5db371fe73ae66a78a633371e" + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a454d47278cc16a5db371fe73ae66a78a633371e", - "reference": "a454d47278cc16a5db371fe73ae66a78a633371e", + "url": "https://api.github.com/repos/symfony/yaml/zipball/93e29e0deb5f1b2e360adfb389a20d25eb81a27b", + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.3" + "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.3|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/console": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -8504,7 +8749,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.45" + "source": "https://github.com/symfony/yaml/tree/v6.4.23" }, "funding": [ { @@ -8520,7 +8765,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-06-03T06:46:12+00:00" }, { "name": "szepeviktor/phpstan-wordpress", @@ -8746,41 +8991,43 @@ }, { "name": "vlucas/phpdotenv", - "version": "v4.3.0", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "67a491df68208bef8c37092db11fa3885008efcf" + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/67a491df68208bef8c37092db11fa3885008efcf", - "reference": "67a491df68208bef8c37092db11fa3885008efcf", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", - "phpoption/phpoption": "^1.7.3", - "symfony/polyfill-ctype": "^1.17" + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-filter": "*", - "ext-pcre": "*", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.30" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "suggest": { - "ext-filter": "Required to use the boolean validator.", - "ext-pcre": "Required to use most of the library." + "ext-filter": "Required to use the boolean validator." }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { - "dev-master": "4.3-dev" + "dev-master": "5.6-dev" } }, "autoload": { @@ -8812,7 +9059,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v4.3.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" }, "funding": [ { @@ -8824,7 +9071,7 @@ "type": "tidelift" } ], - "time": "2022-10-16T00:51:09+00:00" + "time": "2025-04-30T23:37:27+00:00" }, { "name": "webmozart/assert", @@ -11367,11 +11614,11 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.4 || ^8.0" + "php": "^8.1" }, "platform-dev": {}, "platform-overrides": { - "php": "7.4" + "php": "8.1" }, "plugin-api-version": "2.6.0" } diff --git a/plugins/wpgraphql-logging/readme.txt b/plugins/wpgraphql-logging/readme.txt index 4bcde764..8c4c97cf 100644 --- a/plugins/wpgraphql-logging/readme.txt +++ b/plugins/wpgraphql-logging/readme.txt @@ -1,17 +1,17 @@ === WPGraphQL Logging === Contributors: wpengine -Tags: GraphQL, Headless, WPGraphQL, React, Rest -Requires at least: 6.0 -Tested up to: 6.8,1 -Requires PHP: 7.4 -Requires WPGraphQL: 1.8.0 +Tags: GraphQL, Headless, WPGraphQL, React, Rest, Logging, Performance, Debugging, Monitoring +Requires at least: 6.5 +Tested up to: 6.8,2 +Requires PHP: 8.1 +Requires WPGraphQL: 2.3.0 Stable tag: 0.0.1 License: GPL-2.0 License URI: https://www.gnu.org/licenses/gpl-2.0.html == Description == -A plugin for analyzing and measuring the performance of WPGraphQL queries in your headless application. +A WPGraphQL logging plugin that provides visibility into request lifecycle to help quickly identify and resolve bottlenecks in your headless WordPress application. == Upgrade Notice == == Frequently Asked Questions == diff --git a/plugins/wpgraphql-logging/src/Database/LoggingEntity.php b/plugins/wpgraphql-logging/src/Database/LoggingEntity.php deleted file mode 100644 index bd390c13..00000000 --- a/plugins/wpgraphql-logging/src/Database/LoggingEntity.php +++ /dev/null @@ -1,163 +0,0 @@ -get_row( $wpdb->prepare( "SELECT * FROM $table WHERE id = %d", $id ), ARRAY_A ); - if ( ! $row ) { - return null; - } - $entity = new self(); - $entity->setId( (int) $row['id'] ); - $entity->setLevel( $row['level'] ); - $entity->setLevelName( $row['level_name'] ); - $entity->setMessage( $row['message'] ); - $entity->setContext( $row['context'] ); - $entity->setExtra( $row['extra'] ); - $entity->setFormatted( $row['formatted'] ); - $entity->setDatetime( $row['datetime'] ); - $entity->setChannel( $row['channel'] ); - - return $entity; - } - - public function write(): void { - // @TODO some type of try/catch or error handling here. - global $wpdb; - $table = self::getTableName(); - $data = [ - 'level' => $this->getLevel(), - 'level_name' => $this->getLevelName(), - 'message' => $this->getMessage(), - 'context' => wp_json_encode($this->getContext()), - 'extra' => wp_json_encode($this->getExtra()), - 'formatted' => $this->getFormatted(), - 'datetime' => $this->getDatetime(), - 'channel' => $this->getChannel(), - ]; - - - if ( isset( $this->id ) ) { - $wpdb->update( $table, $data, [ 'id' => $this->id ] ); - } else { - $wpdb->insert( $table, $data ); - $this->setId( (int) $wpdb->insert_id ); - } - } - - public function getLevel(): int { - return $this->level; - } - - public function setLevel( int $level ): void { - $this->level = $level; - } - - public function getLevelName(): string { - return $this->level_name; - } - - public function setLevelName( string $level_name ): void { - $this->level_name = $level_name; - } - - public function getMessage(): string { - return $this->message; - } - - public function setMessage( string $message ): void { - $this->message = $message; - } - - public function getContext(): array { - return $this->context; - } - - public function setContext( array $context ): void { - $this->context = $context; - } - - public function getExtra(): array { - return $this->extra; - } - - public function setExtra( array $extra ): void { - $this->extra = $extra; - } - - public function getFormatted(): ?string { - return $this->formatted; - } - - public function setFormatted( ?string $formatted ): void { - $this->formatted = $formatted; - } - - public function getDatetime(): DateTimeImmutable { - return $this->datetime; - } - - public function setDatetime( DateTimeImmutable $datetime ): void { - $this->datetime = $datetime; - } - - public function getChannel(): ?string { - return $this->channel; - } - - public function setChannel( ?string $channel ): void { - $this->channel = $channel; - } - - public function getId(): int { - return $this->id; - } - - public function setId( int $id ): void { - $this->id = $id; - } - - public static function getTableName(): string { - global $wpdb; - - return $wpdb->prefix . 'wpgraphql_logging'; - } - - /** - * @TODO POC - * - * This is probably not the best way to do this, but it works for now. - */ - public static function get_schema(): string { - return ' - CREATE TABLE ' . self::getTableName() . " ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - level INT NOT NULL, - level_name VARCHAR(50) NOT NULL, - message TEXT NOT NULL, - context JSON NULL, - extra JSON NULL, - formatted TEXT NULL, - datetime DATETIME NOT NULL, - channel VARCHAR(100) NULL - ) {$GLOBALS['wpdb']->get_charset_collate()}; - "; - } -} diff --git a/plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php b/plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php deleted file mode 100644 index 3675d120..00000000 --- a/plugins/wpgraphql-logging/src/Logging/Handlers/WPGraphQLDatabaseHandler.php +++ /dev/null @@ -1,34 +0,0 @@ -setMessage( $record['message'] ?? ''); - $entity->setContext( $record['context'] ?? [] ); - $entity->setLevel( $record['level'] ?? Logger::INFO ); - $entity->setLevelName( $record['level_name'] ?? 'INFO' ); - $entity->setChannel( $record['channel'] ?? 'wpgraphql_logging' ); - $entity->setDatetime( $record['datetime'] ?? new \DateTimeImmutable()); - $entity->setExtra( $record['extra'] ?? [] ); - $entity->setFormatted( $record['formatted'] ?? '' ); - $entity->write(); - } -} diff --git a/plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php b/plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php deleted file mode 100644 index 5e20c1fb..00000000 --- a/plugins/wpgraphql-logging/src/Logging/WPGraphQLLoggingService.php +++ /dev/null @@ -1,125 +0,0 @@ -setup(); - } - - return self::$instance; - } - - /** - * @TODO POC - * - * This is POC on how to log to monolog. This isn't the finished product and should have different services - */ - protected function setup(): void { - // Setup handlers - $this->setup_handlers(); - $this->setup_logging_events(); - } - - /** - * Setup the logging handlers. - * - * @TODO POC - Refactor this to use a service container or similar pattern. - * - * @return vpod - */ - protected function setup_handlers(): void { - - // Create the database handler - $logger = new Logger( 'wpgraphql_logging' ); - $dbHandler = new WPGraphQLDatabaseHandler( Logger::DEBUG ); - - // Optional: Set a custom formatter - $formatter = new LineFormatter( - "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n", - 'Y-m-d H:i:s' - ); - $dbHandler->setFormatter( $formatter ); - - // Add the handler to the logger - $logger->pushHandler( $dbHandler ); - - $this->logger = $logger; - } - - protected function setup_logging_events(): void { - add_action( 'do_graphql_request', [ $this, 'log_pre_request' ], 10, 3 ); - add_action( 'graphql_process_http_request_response', [ $this, 'log_post_request' ], 10, 5 ); - // @TODO POC - Add more events here - // @TODO somehow group these? - } - - public function log_pre_request( $query, $variables, $operation_name ): void { - $this->start_time = microtime( true ); - $this->start_memory = memory_get_usage( true ); - - // Log the incoming request - $this->logger->info( 'Request', [ - 'query' => $query, - 'time' => $this->start_time, - 'memory_usage' => $this->start_memory, - 'variables' => $variables, - 'operation_name' => $operation_name, - 'user_id' => get_current_user_id() - ] ); - } - - public function log_post_request( $response, $result, string $operation_name, string $query, array $variables ) { - $time = microtime( true ); - $memory = memory_get_usage( true ); - - // Log the incoming request - $this->logger->info( 'Response', [ - 'query' => $query, - 'time' => $time, - 'memory_usage' => $memory, - 'variables' => $variables, - 'operation_name' => $operation_name, - 'user_id' => get_current_user_id() - ] ); - } -} diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php index e5d1142d..b1bda8c8 100644 --- a/plugins/wpgraphql-logging/src/Plugin.php +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -4,9 +4,6 @@ namespace WPGraphQL\Logging; -use WPGraphQL\Logging\Database\LoggingEntity; -use WPGraphQL\Logging\Logging\WPGraphQLLoggingService; - /** * Plugin class for WPGraphQL Logging. * @@ -51,23 +48,7 @@ public static function init(): self { * Initialize the plugin admin, frontend & api functionality. */ public function setup(): void { - - // @TODO POC - // Might be better to move to a hooks class - add_action( 'wpgraphql_logging_activate', [ $this, 'setup_database' ], 1, 0 ); - - WPGraphQLLoggingService::init(); - } - - /** - * Setups the database for the plugin. - */ - public function setup_database(): void { - $database = new LoggingEntity(); - $schema = $database->get_schema(); - global $wpdb; - require_once ABSPATH . 'wp-admin/includes/upgrade.php'; - dbDelta( $schema ); + // @TODO } /** diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php new file mode 100644 index 00000000..2552ccac --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php @@ -0,0 +1,36 @@ +assertTrue( function_exists( 'wpgraphql_logging_activation_callback' ) ); + } + + + public function test_custom_filter_on_wpgraphql_logging_activate(): void { + $called = false; + + add_action( 'wpgraphql_logging_activate', function () use ( &$called ) { + $called = true; + } ); + + wpgraphql_logging_activation_callback(); + $this->assertTrue( $called, 'Custom filter on wpgraphql_logging_activate was not called.' ); + } +} diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/AutoloaderTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/AutoloaderTest.php new file mode 100644 index 00000000..df2d03a4 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/AutoloaderTest.php @@ -0,0 +1,123 @@ +assertInstanceOf( Autoloader::class, $autoloader ); + $this->assertTrue( method_exists( $autoloader, 'autoload' ) ); + $this->assertTrue( method_exists( $autoloader, 'get_composer_autoloader_path' ) ); + $this->assertTrue( method_exists( $autoloader, 'get_is_loaded' ) ); + + // Check composer autoloader file exists + $composer_file = $autoloader::get_composer_autoloader_path(); + $this->assertFileExists( $composer_file ); + $this->assertIsReadable( $composer_file ); + + // Autoload the composer dependencies + $result = $autoloader->autoload(); + $this->assertEquals( $result, $composer_file ); + $this->assertEquals( Autoloader::get_is_loaded(), $composer_file ); + $this->assertEquals( $result, Autoloader::get_is_loaded() ); + } + + // Additional test: Test that autoload() sets is_loaded to true when autoloader file exists and returns true. + public function test_autoload_sets_is_loaded_true_when_file_exists_and_returns_true(): void { + + // Create a temporary autoloader file that returns true + $temp_dir = sys_get_temp_dir() . '/wpgraphql-logging-test-' . uniqid(); + mkdir( $temp_dir . '/vendor', 0755, true ); + $autoloader_path = $temp_dir . '/vendor/autoload.php'; + file_put_contents( $autoloader_path, 'getMethod( 'get_composer_autoloader_path' ); + $method->setAccessible( true ); + + // Backup original method + $original_method = $method; + + // Override method to return our temp path + $mock = $this->getMockBuilder( Autoloader::class ) + ->disableOriginalConstructor() + ->onlyMethods( [ 'get_composer_autoloader_path' ] ) + ->getMock(); + + // Reset static property + $property = $reflection->getProperty( 'is_loaded' ); + $property->setAccessible( true ); + $property->setValue( null, false ); + + // Call autoload and assert + $result = Autoloader::autoload(); + $this->assertTrue( $result, 'Autoload should return true when autoloader file returns true' ); + $this->assertTrue( Autoloader::get_is_loaded(), 'is_loaded should be true after successful autoload' ); + + // Clean up + unlink( $autoloader_path ); + rmdir( $temp_dir . '/vendor' ); + rmdir( $temp_dir ); + } + + /** + * Test that missing autoloader notice is displayed in admin. + */ + public function test_missing_autoloader_notice_admin(): void { + + // Call the method that should trigger the notice + $reflection = new ReflectionClass( Autoloader::class ); + $method = $reflection->getMethod( 'missing_autoloader_notice' ); + $method->setAccessible( true ); + + $method->invoke( null ); + + // Check that hooks were added + $this->assertTrue( has_action( 'admin_notices' ) ); + $this->assertTrue( has_action( 'network_admin_notices' ) ); + + // Test the actual notice output + ob_start(); + do_action( 'admin_notices' ); + $output = ob_get_clean(); + + $this->assertStringContainsString( 'WPGraphQL Logging: The Composer autoloader was not found', $output ); + $this->assertStringContainsString( 'composer install', $output ); + $this->assertStringContainsString( 'error notice', $output ); + } + + + public function test_get_composer_autoloader_path_returns_expected_path() { + wpgraphql_logging_constants(); + $expected = WPGRAPHQL_LOGGING_PLUGIN_DIR . 'vendor/autoload.php'; + $this->assertEquals( + $expected, + Autoloader::get_composer_autoloader_path() + ); + } + + public function test_require_autoloader_returns_false_if_file_not_readable() { + $reflection = new \ReflectionClass( Autoloader::class ); + $method = $reflection->getMethod( 'require_autoloader' ); + $method->setAccessible( true ); + + // Use a non-existent file + $result = $method->invokeArgs( null, [ '/tmp/does-not-exist-' . uniqid() . '.php' ] ); + $this->assertFalse( $result ); + } +} diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/DeactivationTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/DeactivationTest.php new file mode 100644 index 00000000..bcc0f387 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/DeactivationTest.php @@ -0,0 +1,37 @@ +assertTrue( function_exists( 'wpgraphql_logging_deactivation_callback' ) ); + } + + + public function test_custom_filter_on_wpgraphql_logging_deactivate(): void { + $called = false; + + add_action( 'wpgraphql_logging_deactivate', function () use ( &$called ) { + $called = true; + } ); + + wpgraphql_logging_deactivation_callback(); + $this->assertTrue( $called, 'Custom filter on wpgraphql_logging_deactivate was not called.' ); + } +} diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php new file mode 100644 index 00000000..e22429e1 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php @@ -0,0 +1,69 @@ +assertTrue( $instance instanceof Plugin ); + } + + public function test_singleton_returns_same_instance() { + $first = Plugin::init(); + $second = Plugin::init(); + $this->assertSame( $first, $second, 'Plugin::instance() should always return the same instance' ); + } + + public function test_instance_creates_and_sets_up_plugin_when_not_set() { + $reflection = new ReflectionClass( Plugin::class ); + $instanceProperty = $reflection->getProperty( 'instance' ); + $instanceProperty->setAccessible( true ); + $instanceProperty->setValue( null ); + + $this->assertNull( $instanceProperty->getValue() ); + $instance = Plugin::init(); + + $this->assertInstanceOf( Plugin::class, $instanceProperty->getValue() ); + $this->assertSame( $instance, $instanceProperty->getValue(), 'Plugin::instance() should set the static instance property' ); + } + + + public function test_clone_method_throws_error() { + // Create a fresh instance instead of using singleton + $reflection = new ReflectionClass( Plugin::class ); + $plugin = $reflection->newInstanceWithoutConstructor(); + + $this->setExpectedIncorrectUsage( 'WPGraphQL\Logging\Plugin::__clone' ); + $clone = clone $plugin; + + // Verify the clone exists to ensure the operation completed + $this->assertInstanceOf( Plugin::class, $clone ); + } + + public function test_wakeup_method_throws_error() { + $this->setExpectedIncorrectUsage( 'WPGraphQL\Logging\Plugin::__wakeup' ); + + // Create a fresh instance + $reflection = new ReflectionClass( Plugin::class ); + $plugin = $reflection->newInstanceWithoutConstructor(); + + $serialized = serialize( $plugin ); + $unserialized = unserialize( $serialized ); + + // Verify the unserialized object exists + $this->assertInstanceOf( Plugin::class, $unserialized ); + } +} diff --git a/plugins/wpgraphql-logging/wpgraphql-logging.php b/plugins/wpgraphql-logging/wpgraphql-logging.php index f990a0b9..7a1f8a6d 100644 --- a/plugins/wpgraphql-logging/wpgraphql-logging.php +++ b/plugins/wpgraphql-logging/wpgraphql-logging.php @@ -3,20 +3,20 @@ * Plugin Name: WPGraphQL Logging * Plugin URI: https://github.com/wpengine/hwptoolkit * GitHub Plugin URI: https://github.com/wpengine/hwptoolkit - * Description: A POC plugin for logging data for WPGraphQL. + * Description: A WPGraphQL logging plugin that provides visibility into request lifecycle to help quickly identify and resolve bottlenecks in your headless WordPress application. * Author: WPEngine Headless OSS Team * Author URI: https://github.com/wpengine * Update URI: https://github.com/wpengine/hwptoolkit * Version: 0.0.1 * Text Domain: wpgraphql-logging * Domain Path: /languages - * Requires at least: 6.0 - * Tested up to: 6.8.1 - * Requires PHP: 7.4+ + * Requires at least: 6.5 + * Tested up to: 6.8.2 + * Requires PHP: 8.1+ * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Requires Plugins: wp-graphql - * WPGraphQL requires at least: 1.8.0 + * WPGraphQL requires at least: 2.3.0 * WPGraphQL tested up to: 2.3.3 * * @package WPGraphQL\Logging From 4ea7bdcdaeddf52b412f32e9c2e054402cd3071a Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 22 Jul 2025 14:37:50 +0100 Subject: [PATCH 03/19] Added .env.ci for tests. --- plugins/wpgraphql-logging/.docker/.env.ci | 59 +++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 plugins/wpgraphql-logging/.docker/.env.ci diff --git a/plugins/wpgraphql-logging/.docker/.env.ci b/plugins/wpgraphql-logging/.docker/.env.ci new file mode 100644 index 00000000..8d4e911d --- /dev/null +++ b/plugins/wpgraphql-logging/.docker/.env.ci @@ -0,0 +1,59 @@ +PLUGIN_SLUG=wpgraphql-logging + +# Configure these to match your existing testing environment or the one you want to create with Docker. +## Usually, these values should match the ones in the `wp-config.php` file. +## If using Local by Flywheel, you can `open AdminerEvo` and find the values in the URL: `http://localhost:{DB_PORT}/?username={DB_USER}&db={DB_NAME}` +## NOTE: Codeception may modify or the database during testing. If you want to preserve your local data, create a new database and use that for the `DB_NAME`. +DB_NAME=wordpress +DB_HOST=mysql +DB_USER=root +DB_PASSWORD=password +DB_PORT=3306 + +# The local path to the WordPress root directory, the one containing the wp-load.php file. +## This can be a relative path from the directory that contains the codeception.yml file, or an absolute path. +## If you are using Local by Flywheel, you can find the path in the Local by Flywheel app under the site's settings. +WORDPRESS_ROOT_DIR="/var/www/html" + +# This table prefix used by the WordPress site, and in Acceptance tests. +WORDPRESS_TABLE_PREFIX=wp_ + +# The URL and domain of the WordPress site, and in Acceptance tests. +## If the port is in use, you can change it to a different port. +WORDPRESS_URL=http://localhost +WORDPRESS_DOMAIN=localhost +WORDPRESS_ADMIN_PATH=/wp-admin + +# The username and password of the administrator user of the WordPress site, and in Acceptance tests. +WORDPRESS_ADMIN_USER=admin +WORDPRESS_ADMIN_PASSWORD=password +WORDPRESS_ADMIN_EMAIL=admin@example.com + +# Tests will require a MySQL database to run. +# Do not use a database that contains important data! +WORDPRESS_DB_HOST=${DB_HOST} +WORDPRESS_DB_USER=${DB_USER} +WORDPRESS_DB_PASSWORD=${DB_PASSWORD} +WORDPRESS_DB_NAME=${DB_NAME} +WORDPRESS_DB_PORT=${DB_PORT} + +# WPUnit tests will use these variables instead. +# By default this is the same as WordPress +TEST_DB_HOST=${WORDPRESS_DB_HOST} +TEST_DB_USER=${WORDPRESS_DB_USER} +TEST_DB_PASSWORD=${WORDPRESS_DB_PASSWORD} +TEST_DB_NAME=${WORDPRESS_DB_NAME} +TEST_DB_PORT=${WORDPRESS_DB_PORT} +# The Integration suite will use this table prefix for the WordPress tables. +TEST_TABLE_PREFIX=test_ + +# The DSN used by Acceptance tests. +TEST_DB_DSN="mysql:host=${TEST_DB_HOST};port=${TEST_DB_PORT};dbname=${TEST_DB_NAME}" + +# The following variables are used to determine test behavior. + +# Include 3rd party plugins (e.g. WooCommerce) in the tests. +# Skips recreating the database before running the tests. +SKIP_DB_CREATE=false +# Skips configuring the WordPress installation +SKIP_WP_SETUP=false From b604a6430d2d259f1a80996f6895abee084a5f37 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 22 Jul 2025 14:45:22 +0100 Subject: [PATCH 04/19] Added missing test directory. --- plugins/wpgraphql-logging/tests/_data/.gitignore | 1 + plugins/wpgraphql-logging/tests/_data/.gitkeep | 0 plugins/wpgraphql-logging/tests/_data/config.php | 1 + 3 files changed, 2 insertions(+) create mode 100644 plugins/wpgraphql-logging/tests/_data/.gitignore create mode 100644 plugins/wpgraphql-logging/tests/_data/.gitkeep create mode 100644 plugins/wpgraphql-logging/tests/_data/config.php diff --git a/plugins/wpgraphql-logging/tests/_data/.gitignore b/plugins/wpgraphql-logging/tests/_data/.gitignore new file mode 100644 index 00000000..9a9c1ca1 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/_data/.gitignore @@ -0,0 +1 @@ +dump.sql diff --git a/plugins/wpgraphql-logging/tests/_data/.gitkeep b/plugins/wpgraphql-logging/tests/_data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/plugins/wpgraphql-logging/tests/_data/config.php b/plugins/wpgraphql-logging/tests/_data/config.php new file mode 100644 index 00000000..8c73df40 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/_data/config.php @@ -0,0 +1 @@ + Date: Wed, 23 Jul 2025 16:08:46 +0100 Subject: [PATCH 05/19] Added Database entity and plugin hook class to add/drop table on activation/de-activation. --- plugins/wpgraphql-logging/src/Admin/.gitkeep | 0 plugins/wpgraphql-logging/src/Events/.gitkeep | 0 plugins/wpgraphql-logging/src/Hooks/.gitkeep | 0 .../src/Hooks/PluginHooks.php | 50 ++++++++++++++ plugins/wpgraphql-logging/src/Logger/.gitkeep | 0 .../src/Logger/Database/DatabaseEntity.php | 65 +++++++++++++++++ plugins/wpgraphql-logging/src/Plugin.php | 4 +- .../tests/wpunit/Core/ActivationTest.php | 7 ++ .../tests/wpunit/Core/PluginTest.php | 15 +--- .../tests/wpunit/Hooks/PluginHooksTest.php | 69 +++++++++++++++++++ 10 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 plugins/wpgraphql-logging/src/Admin/.gitkeep create mode 100644 plugins/wpgraphql-logging/src/Events/.gitkeep create mode 100644 plugins/wpgraphql-logging/src/Hooks/.gitkeep create mode 100644 plugins/wpgraphql-logging/src/Hooks/PluginHooks.php create mode 100644 plugins/wpgraphql-logging/src/Logger/.gitkeep create mode 100644 plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php diff --git a/plugins/wpgraphql-logging/src/Admin/.gitkeep b/plugins/wpgraphql-logging/src/Admin/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/plugins/wpgraphql-logging/src/Events/.gitkeep b/plugins/wpgraphql-logging/src/Events/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/plugins/wpgraphql-logging/src/Hooks/.gitkeep b/plugins/wpgraphql-logging/src/Hooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php b/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php new file mode 100644 index 00000000..f744dbbd --- /dev/null +++ b/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php @@ -0,0 +1,50 @@ +register(); + } + return self::$instance; + } + + /** + * Activation callback for the plugin. + */ + public static function activate_plugin(): void { + DatabaseEntity::create_table(); + } + + /** + * Deactivation callback for the plugin. + */ + public static function deactivate_plugin(): void { + // @TODO: Add configuration to determine if the table should be dropped on deactivation. + DatabaseEntity::drop_table(); + } + + /** + * Register actions and filters. + */ + protected function register(): void { + add_action( 'wpgraphql_logging_activate', [ self::class, 'activate_plugin' ] ); + add_action( 'wpgraphql_logging_deactivate', [ self::class, 'deactivate_plugin' ] ); + } +} diff --git a/plugins/wpgraphql-logging/src/Logger/.gitkeep b/plugins/wpgraphql-logging/src/Logger/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php new file mode 100644 index 00000000..1d73a3dd --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php @@ -0,0 +1,65 @@ +prefix . 'wpgraphql_logging' ); + } + + /** + * Gets the database schema for the logging table. + * + * @return string The SQL CREATE an TABLE statement. + */ + public static function get_schema(): string { + global $wpdb; + $table_name = self::get_table_name(); + $charset_collate = $wpdb->get_charset_collate(); + + return " + CREATE TABLE {$table_name} ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + channel VARCHAR(191) NOT NULL, + level SMALLINT UNSIGNED NOT NULL, + level_name VARCHAR(50) NOT NULL, + message LONGTEXT NOT NULL, + context JSON NULL, + extra JSON NULL, + datetime DATETIME NOT NULL, + INDEX channel_index (channel), + INDEX level_index (level), + INDEX datetime_index (datetime) + ) {$charset_collate}; + "; + } + + /** + * Creates the logging table in the database. + */ + public static function create_table(): void { + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + $schema = self::get_schema(); + dbDelta( $schema ); + } + + /** + * Drops the logging table from the database. + */ + public static function drop_table(): void { + global $wpdb; + $table_name = self::get_table_name(); + + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange + $wpdb->query( "DROP TABLE IF EXISTS {$table_name}" ); + } +} diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php index b1bda8c8..61c81f02 100644 --- a/plugins/wpgraphql-logging/src/Plugin.php +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -4,6 +4,8 @@ namespace WPGraphQL\Logging; +use WPGraphQL\Logging\Hooks\PluginHooks; + /** * Plugin class for WPGraphQL Logging. * @@ -48,7 +50,7 @@ public static function init(): self { * Initialize the plugin admin, frontend & api functionality. */ public function setup(): void { - // @TODO + PluginHooks::init(); } /** diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php index 2552ccac..e75b7f25 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/ActivationTest.php @@ -6,16 +6,23 @@ use lucatume\WPBrowser\TestCase\WPTestCase; +use WPGraphQL\Logging\Logger\Database\DatabaseEntity; /** * Test class for the activation callback. */ class ActivationTest extends WPTestCase { + protected function setUp(): void { parent::setUp(); if ( ! function_exists( 'wpgraphql_logging_activation_callback' ) ) { require_once dirname( __DIR__ ) . '/activation.php'; } + $this->drop_table(); + } + + public function drop_table(): void { + DatabaseEntity::drop_table(); } public function test_activation_callback_function_exists(): void { diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php index e22429e1..3a5c7f14 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php @@ -7,6 +7,7 @@ use WPGraphQL\Logging\Plugin; use lucatume\WPBrowser\TestCase\WPTestCase; use ReflectionClass; +use WPGraphQL\Logging\Logger\Database\DatabaseEntity; /** * Class PluginTest @@ -52,18 +53,4 @@ public function test_clone_method_throws_error() { // Verify the clone exists to ensure the operation completed $this->assertInstanceOf( Plugin::class, $clone ); } - - public function test_wakeup_method_throws_error() { - $this->setExpectedIncorrectUsage( 'WPGraphQL\Logging\Plugin::__wakeup' ); - - // Create a fresh instance - $reflection = new ReflectionClass( Plugin::class ); - $plugin = $reflection->newInstanceWithoutConstructor(); - - $serialized = serialize( $plugin ); - $unserialized = unserialize( $serialized ); - - // Verify the unserialized object exists - $this->assertInstanceOf( Plugin::class, $unserialized ); - } } diff --git a/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php b/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php new file mode 100644 index 00000000..a8b8dca0 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php @@ -0,0 +1,69 @@ +drop_table(); + } + + public function drop_table(): void { + DatabaseEntity::drop_table(); + } + + public function test_instance_from_function_in_hwp_previews() { + $instance = PluginHooks::init(); + $this->assertTrue( $instance instanceof PluginHooks ); + } + + public function test_singleton_returns_same_instance() { + $first = PluginHooks::init(); + $second = PluginHooks::init(); + $this->assertSame( $first, $second, 'PluginHooks::instance() should always return the same instance' ); + } + + public function test_instance_creates_and_sets_up_plugin_when_not_set() { + $reflection = new ReflectionClass( PluginHooks::class ); + $instanceProperty = $reflection->getProperty( 'instance' ); + $instanceProperty->setAccessible( true ); + $instanceProperty->setValue( null ); + + $this->assertNull( $instanceProperty->getValue() ); + $instance = PluginHooks::init(); + + $this->assertInstanceOf( PluginHooks::class, $instanceProperty->getValue() ); + $this->assertSame( $instance, $instanceProperty->getValue(), 'Plugin::instance() should set the static instance property' ); + } + + + public function test_database_table_creation() { + global $wpdb; + + // Setup plugin and run activation hook + PluginHooks::init(); + wpgraphql_logging_activation_callback(); + + // Check if the table now exists + $table_exists = $wpdb->get_var( $wpdb->prepare( + "SHOW TABLES LIKE %s", + DatabaseEntity::get_table_name() + ) ); + + $this->assertEquals( DatabaseEntity::get_table_name(), $table_exists, 'Database table should be created by setup method.' ); + } +} From d9e9edf5a61cebcaf9386074dc46d85993bbacb3 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Wed, 23 Jul 2025 16:32:31 +0100 Subject: [PATCH 06/19] Fixed QA errors. --- plugins/wpgraphql-logging/phpcs.xml | 347 ++++++++++++++++++ plugins/wpgraphql-logging/psalm.xml | 8 + .../src/Hooks/PluginHooks.php | 4 +- .../src/Logger/Database/DatabaseEntity.php | 8 +- 4 files changed, 364 insertions(+), 3 deletions(-) create mode 100644 plugins/wpgraphql-logging/phpcs.xml diff --git a/plugins/wpgraphql-logging/phpcs.xml b/plugins/wpgraphql-logging/phpcs.xml new file mode 100644 index 00000000..b1dbd3e6 --- /dev/null +++ b/plugins/wpgraphql-logging/phpcs.xml @@ -0,0 +1,347 @@ + + + + + + + + Coding standards for the WPGraphQL Logging plugin + ./wpgraphql-logging.php + ./activation.php + ./deactivation.php + ./vendor/autoload.php + ./src/ + */languages/* + */phpunit.xml* + **/tests/** + */vendor/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + warning + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/wpgraphql-logging/psalm.xml b/plugins/wpgraphql-logging/psalm.xml index de65e558..afe2259c 100644 --- a/plugins/wpgraphql-logging/psalm.xml +++ b/plugins/wpgraphql-logging/psalm.xml @@ -10,6 +10,8 @@ > + + @@ -25,5 +27,11 @@ + + + + + + diff --git a/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php b/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php index f744dbbd..8b5e908f 100644 --- a/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php +++ b/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php @@ -44,7 +44,7 @@ public static function deactivate_plugin(): void { * Register actions and filters. */ protected function register(): void { - add_action( 'wpgraphql_logging_activate', [ self::class, 'activate_plugin' ] ); - add_action( 'wpgraphql_logging_deactivate', [ self::class, 'deactivate_plugin' ] ); + add_action( 'wpgraphql_logging_activate', [ self::class, 'activate_plugin' ], 10, 0 ); + add_action( 'wpgraphql_logging_deactivate', [ self::class, 'deactivate_plugin' ], 10, 0 ); } } diff --git a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php index 1d73a3dd..026f24f2 100644 --- a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php +++ b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php @@ -45,9 +45,15 @@ public static function get_schema(): string { /** * Creates the logging table in the database. + * + * @throws \RuntimeException If ABSPATH is not defined. */ public static function create_table(): void { - require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + if ( ! defined( 'ABSPATH' ) ) { + throw new \RuntimeException( 'ABSPATH is not defined.' ); + } + + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // @phpstan-ignore-line $schema = self::get_schema(); dbDelta( $schema ); } From 2b24ee41fa6540c4018832f02cca4239983595be Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Thu, 24 Jul 2025 19:31:20 +0100 Subject: [PATCH 07/19] Updated Database entity with CRUD operations. Added tests. --- .../src/Logger/Database/DatabaseEntity.php | 269 ++++++++++++++++-- .../tests/wpunit/Core/PluginTest.php | 2 +- .../tests/wpunit/Hooks/PluginHooksTest.php | 2 +- .../Logger/Database/DatabaseEntityTest.php | 163 +++++++++++ 4 files changed, 404 insertions(+), 32 deletions(-) create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php diff --git a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php index 026f24f2..9c79ca0d 100644 --- a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php +++ b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php @@ -4,58 +4,198 @@ namespace WPGraphQL\Logging\Logger\Database; +/** + * Entity class for the custom database table for Monolog. + * + * This class represents a single log entry in the database and provides methods to create, save, and manage log entries. + * + * @package WPGraphQL\Logging + * + * @since 0.0.1 + */ class DatabaseEntity { /** - * Gets the name of the logging table. + * The ID of the log entry. Null if the entry is not yet saved. * - * @return string The name of the logging table. + * @var int|null */ - public static function get_table_name(): string { + protected ?int $id = null; + + /** + * The channel for the log entry. + * + * @var string + */ + protected string $channel = ''; + + /** + * The logging level. + * + * @var int + */ + protected int $level = 0; + + /** + * The name of the logging level. + * + * @var string + */ + protected string $level_name = ''; + + /** + * The log message. + * + * @var string + */ + protected string $message = ''; + + /** + * Additional context for the log entry. + * + * @var array + */ + protected array $context = []; + + /** + * Extra data for the log entry. + * + * @var array + */ + protected array $extra = []; + + /** + * The datetime of the log entry. + * + * @var string + */ + protected string $datetime = ''; + + /** + * The constructor is protected to encourage creation via static methods. + */ + protected function __construct() { + // Set a default datetime for new, unsaved entries. + $this->datetime = current_time( 'mysql', 1 ); + } + + /** + * Creates a new, unsaved log entry instance. + * + * @param string $channel The channel for the log entry. + * @param int $level The logging level. + * @param string $level_name The name of the logging level. + * @param string $message The log message. + * @param array $context Additional context for the log entry. + * @param array $extra Extra data for the log entry. + */ + public static function create(string $channel, int $level, string $level_name, string $message, array $context = [], array $extra = []): self { + $entity = new self(); + $entity->channel = self::sanitize_text_field( $channel ); + $entity->level = $level; + $entity->level_name = self::sanitize_text_field( $level_name ); + $entity->message = self::sanitize_text_field( $message ); + $entity->context = self::sanitize_array_field( $context ); + $entity->extra = self::sanitize_array_field( $extra ); + + return $entity; + } + + /** + * Finds a single log entry by its ID and returns it as an object. + * + * @param int $id The ID of the log entry to find. + * + * @return self|null Returns an instance of DatabaseEntity if found, or null if not found. + */ + public static function find(int $id): ?self { + global $wpdb; + $table_name = self::get_table_name(); + + $query = $wpdb->prepare( "SELECT * FROM {$table_name} WHERE id = %d", $id ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared + $row = $wpdb->get_row( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared + + if ( ! $row ) { + return null; + } + + return self::create_from_db_row( $row ); + } + + /** + * Saves a new logging entity to the database. This is an insert-only operation. + * + * @return int The ID of the newly created log entry, or 0 on failure. + */ + public function save(): int { global $wpdb; + $table_name = self::get_table_name(); + + $data = [ + 'channel' => $this->channel, + 'level' => $this->level, + 'level_name' => $this->level_name, + 'message' => $this->message, + 'context' => wp_json_encode( $this->context ), + 'extra' => wp_json_encode( $this->extra ), + 'datetime' => $this->datetime, + ]; + + $formats = [ '%s', '%d', '%s', '%s', '%s', '%s', '%s' ]; + + $result = $wpdb->insert( $table_name, $data, $formats ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery + + if ( $result ) { + $this->id = (int) $wpdb->insert_id; + return $this->id; + } - return (string) apply_filters( 'wpgraphql_logging_database_name', $wpdb->prefix . 'wpgraphql_logging' ); + return 0; + } + + /** + * Gets the name of the logging table. + */ + public static function get_table_name(): string { + global $wpdb; + $name = apply_filters( 'wpgraphql_logging_database_name', $wpdb->prefix . 'wpgraphql_logging' ); + return self::sanitize_text_field( $name ); } /** * Gets the database schema for the logging table. - * - * @return string The SQL CREATE an TABLE statement. */ public static function get_schema(): string { global $wpdb; $table_name = self::get_table_name(); $charset_collate = $wpdb->get_charset_collate(); + // **IMPORTANT**: This schema format with PRIMARY KEY on its own line is the + // correct and stable way to work with dbDelta. return " - CREATE TABLE {$table_name} ( - id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - channel VARCHAR(191) NOT NULL, - level SMALLINT UNSIGNED NOT NULL, - level_name VARCHAR(50) NOT NULL, - message LONGTEXT NOT NULL, - context JSON NULL, - extra JSON NULL, - datetime DATETIME NOT NULL, - INDEX channel_index (channel), - INDEX level_index (level), - INDEX datetime_index (datetime) - ) {$charset_collate}; - "; + CREATE TABLE {$table_name} ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + channel VARCHAR(191) NOT NULL, + level SMALLINT UNSIGNED NOT NULL, + level_name VARCHAR(50) NOT NULL, + message LONGTEXT NOT NULL, + context JSON NULL, + extra JSON NULL, + datetime DATETIME NOT NULL, + PRIMARY KEY (id), + INDEX channel_index (channel), + INDEX level_index (level), + INDEX datetime_index (datetime) + ) {$charset_collate}; + "; } /** * Creates the logging table in the database. * - * @throws \RuntimeException If ABSPATH is not defined. */ public static function create_table(): void { - if ( ! defined( 'ABSPATH' ) ) { - throw new \RuntimeException( 'ABSPATH is not defined.' ); - } - - require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // @phpstan-ignore-line - $schema = self::get_schema(); - dbDelta( $schema ); + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + dbDelta( self::get_schema() ); } /** @@ -64,8 +204,77 @@ public static function create_table(): void { public static function drop_table(): void { global $wpdb; $table_name = self::get_table_name(); + $wpdb->query( "DROP TABLE IF EXISTS {$table_name}" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching + } - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange - $wpdb->query( "DROP TABLE IF EXISTS {$table_name}" ); + /** + * Sanitizes a text field. + * + * @param string $value The value to sanitize. + */ + protected static function sanitize_text_field(string $value): string { + return sanitize_text_field( $value ); + } + + /** + * Sanitizes an array field recursively. + * + * @param array $data The array to sanitize. + * + * @return array The sanitized array. + */ + protected static function sanitize_array_field(array $data): array { + foreach ( $data as &$value ) { + if ( is_string( $value ) ) { + $value = self::sanitize_text_field( $value ); + continue; + } + + if ( is_array( $value ) ) { + $value = self::sanitize_array_field( $value ); + } + } + return $data; + } + + /** + * Helper to populate an instance from a database row. + * + * @param array $row The database row to populate from. + * + * @return self The populated instance. + */ + private static function create_from_db_row(array $row): self { + $log = new self(); + $log->id = (int) $row['id']; + $log->channel = $row['channel']; + $log->level = (int) $row['level']; + $log->level_name = $row['level_name']; + $log->message = $row['message']; + $log->context = $row['context'] ? json_decode( $row['context'], true ) : []; + $log->extra = $row['extra'] ? json_decode( $row['extra'], true ) : []; + $log->datetime = $row['datetime']; + return $log; + } + + /** + * Magic method to handle dynamic getters like get_level(). + * + * @param string $name The name of the method called. + * @param array $arguments The arguments passed to the method. + * + * @throws \BadMethodCallException If the method does not exist. + * + * @return mixed The value of the property if it exists, otherwise throws an exception. + */ + public function __call(string $name, array $arguments) { + if ( strpos( $name, 'get_' ) === 0 ) { + $property = substr( $name, 4 ); + if ( property_exists( $this, $property ) ) { + return $this->$property; + } + } + $name = $this->sanitize_text_field( $name ); + throw new \BadMethodCallException( sprintf( 'Method %s does not exist.', esc_html( $name ) ) ); } } diff --git a/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php b/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php index 3a5c7f14..ef96cc1d 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Core/PluginTest.php @@ -17,7 +17,7 @@ */ class PluginTest extends WPTestCase { - public function test_instance_from_function_in_hwp_previews() { + public function test_instance_from_function_in_wpgraphql_logging_plugin_init() { $instance = wpgraphql_logging_plugin_init(); $this->assertTrue( $instance instanceof Plugin ); } diff --git a/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php b/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php index a8b8dca0..5077a550 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php @@ -26,7 +26,7 @@ public function drop_table(): void { DatabaseEntity::drop_table(); } - public function test_instance_from_function_in_hwp_previews() { + public function test_instance_from_plugin_instance() { $instance = PluginHooks::init(); $this->assertTrue( $instance instanceof PluginHooks ); } diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php new file mode 100644 index 00000000..29156ee0 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php @@ -0,0 +1,163 @@ +drop_table(); + $this->create_table(); + } + + public function tearDown(): void + { + $this->drop_table(); + parent::tearDown(); + } + + private function drop_table(): void + { + DatabaseEntity::drop_table(); + } + + private function create_table(): void + { + DatabaseEntity::create_table(); + } + + public function test_save_method_inserts_log_into_database(): void + { + global $wpdb; + + $log_data = [ + 'channel' => 'wpgraphql_logging', + 'level' => 200, + 'level_name' => 'INFO', + 'message' => 'query GetPosts { posts { nodes { id title content } } }', + 'context' => [ + 'operation' => 'query', + 'name' => 'GetPosts', + 'memory' => '4MB', + 'usage' => 'fetch posts data' + ], + 'extra' => ['ip' => '127.0.0.1'], + ]; + + // Create and save the entity + $entity = DatabaseEntity::create(...array_values($log_data)); + $insert_id = $entity->save(); + + $this->assertIsInt( $insert_id ); + $this->assertGreaterThan(0, $insert_id, 'The save method should return a positive insert ID.'); + + $entity = DatabaseEntity::find($insert_id); + $this->assertInstanceOf(DatabaseEntity::class, $entity, 'The find method should return an instance of DatabaseEntity.'); + $this->assertEquals($log_data['channel'], $entity->get_channel(), 'The channel should match the saved data.'); + $this->assertEquals($log_data['level'], $entity->get_level(), 'The level should match the saved data.'); + $this->assertEquals($log_data['level_name'], $entity->get_level_name(), 'The level name should match the saved data.'); + $this->assertEquals($log_data['message'], $entity->get_message(), 'The message should match the saved data.'); + $this->assertEquals($log_data['context'], $entity->get_context(), 'The context should match the saved data.'); + $this->assertEquals($log_data['extra'], $entity->get_extra(), 'The extra data should match the saved data.'); + + // Test for a field which doesn't exist + $this->expectException(\BadMethodCallException::class); + $entity->get_nonexistent_field(); + } + + public function test_find_returns_null_for_nonexistent_id(): void + { + $entity = DatabaseEntity::find(999999); + $this->assertNull($entity, 'find() should return null for a non-existent ID.'); + } + + /** + * @test + * It should sanitize an array recursively. + */ + public function test_sanitize_array_field_method(): void + { + $reflection = new ReflectionClass(DatabaseEntity::class); + $method = $reflection->getMethod('sanitize_array_field'); + $method->setAccessible(true); + + $dirty_array = [ + 'field1' => 'Safe', + 'field2' => 'Unsafe ', + 'nested' => [ + 'deep_field' => 'Also unsafe', + 'numeric' => 123, + 'bool' => true, + ], + ]; + + $expected_clean_array = [ + 'field1' => 'Safe', + 'field2' => 'Unsafe', + 'nested' => [ + 'deep_field' => 'Also unsafe', + 'numeric' => 123, + 'bool' => true, + ], + ]; + + $clean_array = $method->invoke($this->entity_instance, $dirty_array); + + $this->assertEquals($expected_clean_array, $clean_array); + } + + /** + * @test + * It should return 0 when the database insert operation fails. + * + * This test uses a WordPress filter to intercept the database query + * and force it to fail, simulating a database error. + */ + public function test_save_returns_zero_on_database_failure(): void + { + // 1. Define a callback that will force the DB query to fail. + $force_fail_callback = function ($query) { + // Check if this is the specific INSERT query we want to fail. + if (strpos($query, 'INSERT INTO `' . DatabaseEntity::get_table_name() . '`') !== false) { + // Returning a non-string value like `false` will cause the + // $wpdb->insert() method to fail and return false. + return false; + } + // For all other queries, let them pass through untouched. + return $query; + }; + + // 2. Add the filter to intercept the query. + add_filter('query', $force_fail_callback); + + // 3. Create a valid entity that we will attempt to save. + $entity = DatabaseEntity::create( + 'failure_test', + 500, + 'CRITICAL', + 'This save operation is designed to fail.' + ); + + // 4. Call the save method. Due to our filter, this will fail. + $result_id = $entity->save(); + + // 5. CRUCIAL: Remove the filter so it doesn't affect other tests. + remove_filter('query', $force_fail_callback); + + // 6. Assert that the save method returned 0, indicating failure. + $this->assertSame(0, $result_id, 'The save() method should return 0 when the database insert fails.'); + } +} From 1ac0bfa60d596f6fc1b3a92e39f3b95805d839ca Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Thu, 24 Jul 2025 20:23:30 +0100 Subject: [PATCH 08/19] Added WordPress Database Handler with unit tests. --- .../src/Logger/Database/DatabaseEntity.php | 1 - .../Handlers/WordPressDatabaseHandler.php | 45 ++++++++ .../Handlers/WordPressDatabaseHandlerTest.php | 100 ++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php diff --git a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php index 9c79ca0d..b1e8d075 100644 --- a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php +++ b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php @@ -191,7 +191,6 @@ public static function get_schema(): string { /** * Creates the logging table in the database. - * */ public static function create_table(): void { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; diff --git a/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php b/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php new file mode 100644 index 00000000..47c470b4 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php @@ -0,0 +1,45 @@ +level->getName(); + $entity = DatabaseEntity::create( + $record->channel, + $record->level->value, + (is_string($name) && $name !== '') ? $name : 'INFO', + $record->message, + $record->context ?: [], + $record->extra ?: [] + ); + + $entity->save(); + } catch ( Throwable $e ) { + error_log( 'Error logging to WordPress database: ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log + } + } +} diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php new file mode 100644 index 00000000..5c497aba --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php @@ -0,0 +1,100 @@ +log_data = [ + 'channel' => 'wpgraphql_logging', + 'level' => Level::Info, + 'message' => 'Test log message', + 'context' => ['test_key' => 'test_value'], + 'extra' => ['extra_key' => 'extra_value'], + 'datetime' => new DateTimeImmutable(), + ]; + + // Create a LogRecord instance for testing. + $this->record = new LogRecord( + $this->log_data['datetime'], + $this->log_data['channel'], + $this->log_data['level'], + $this->log_data['message'], + $this->log_data['context'], + $this->log_data['extra'] + ); + } + + public function tearDown(): void + { + DatabaseEntity::drop_table(); + parent::tearDown(); + } + + public function test_write_method_saves_log_to_database(): void + { + global $wpdb; + + // 3. Create an instance of the handler and call the write method. + $handler = new WordPressDatabaseHandler(); + $handler->handle($this->record); + $log_data = $this->log_data; + + // 4. Verify the data was saved correctly in the database. + $table_name = DatabaseEntity::get_table_name(); + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery + $saved_row = $wpdb->get_row("SELECT * FROM {$table_name} ORDER BY id DESC LIMIT 1", ARRAY_A); + + $this->assertNotNull($saved_row, 'A log entry should have been created in the database.'); + $this->assertEquals($log_data['channel'], $saved_row['channel']); + $this->assertEquals($log_data['level']->value, $saved_row['level']); + $this->assertEquals($log_data['level']->getName(), $saved_row['level_name']); + $this->assertEquals($log_data['message'], $saved_row['message']); + + // Compare the JSON-decoded context and extra fields. + $this->assertEquals($log_data['context'], json_decode($saved_row['context'], true)); + $this->assertEquals($log_data['extra'], json_decode($saved_row['extra'], true)); + } + + public function test_write_method_handles_exceptions_gracefully(): void + { + // Drop the table to force the save operation to fail. + DatabaseEntity::drop_table(); + global $wpdb; + $wpdb->flush(); + + $handler = new WordPressDatabaseHandler(); + try { + $handler->handle($this->record); + $this->assertTrue(true, 'The handler should catch the exception and not crash.'); + } catch (\Throwable $e) { + $this->fail('The handler should have caught the exception. Error: ' . $e->getMessage()); + } + } +} From 915c25e31c26c11fbed16b55e723774755b2d1af Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 10:41:58 +0100 Subject: [PATCH 09/19] Created POC (not complete) with database handler, graphql query processor, and POC service to log request/response (not complete). --- plugins/wpgraphql-logging/phpcs.xml | 4 +- plugins/wpgraphql-logging/phpstan.neon.dist | 3 +- plugins/wpgraphql-logging/psalm.xml | 1 + .../src/Events/QueryEventLifecycle.php | 108 ++++++++ .../src/Hooks/PluginHooks.php | 7 + .../src/Logger/Database/DatabaseEntity.php | 89 ++++-- .../Handlers/WordPressDatabaseHandler.php | 25 +- .../src/Logger/LoggerService.php | 260 ++++++++++++++++++ .../Processors/WPGraphQLQueryProcessor.php | 102 +++++++ plugins/wpgraphql-logging/src/Plugin.php | 2 + .../Logger/Database/DatabaseEntityTest.php | 6 +- 11 files changed, 572 insertions(+), 35 deletions(-) create mode 100644 plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php create mode 100644 plugins/wpgraphql-logging/src/Logger/LoggerService.php create mode 100644 plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php diff --git a/plugins/wpgraphql-logging/phpcs.xml b/plugins/wpgraphql-logging/phpcs.xml index b1dbd3e6..9f3468e7 100644 --- a/plugins/wpgraphql-logging/phpcs.xml +++ b/plugins/wpgraphql-logging/phpcs.xml @@ -26,8 +26,8 @@ - - + + diff --git a/plugins/wpgraphql-logging/phpstan.neon.dist b/plugins/wpgraphql-logging/phpstan.neon.dist index 994f339a..05f71e10 100644 --- a/plugins/wpgraphql-logging/phpstan.neon.dist +++ b/plugins/wpgraphql-logging/phpstan.neon.dist @@ -25,9 +25,8 @@ parameters: # Configuration level: 8 phpVersion: - min: 70400 + min: 80100 max: 80400 paths: - wpgraphql-logging.php - src/ - diff --git a/plugins/wpgraphql-logging/psalm.xml b/plugins/wpgraphql-logging/psalm.xml index afe2259c..f6a82936 100644 --- a/plugins/wpgraphql-logging/psalm.xml +++ b/plugins/wpgraphql-logging/psalm.xml @@ -7,6 +7,7 @@ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" findUnusedBaselineEntry="true" findUnusedCode="false" + phpVersion="8.1" > diff --git a/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php b/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php new file mode 100644 index 00000000..4446d8e3 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php @@ -0,0 +1,108 @@ +setup(); + } + return self::$instance; + } + + /** + * Logs the pre-request event for a GraphQL query. + * + * @param string $query The GraphQL query. + * @param mixed $variables The variables for the query. + * @param string $operation_name The name of the operation. + */ + public function log_pre_request( $query, $variables, $operation_name ): void { + + try { + $context = []; + $context = apply_filters( 'wpgraphql_logging_pre_request_context', $context, $query, $variables, $operation_name ); + $level = apply_filters( 'wpgraphql_logging_pre_request_level', Level::Info, $query, $variables, $operation_name ); + $this->logger->log( $level, 'WPGraphQL Incoming Request', $context ); + } catch ( \Throwable $e ) { + // @TODO - Handle logging errors gracefully. + error_log( 'Error in log_pre_request: ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log + } + } + + /** + * Logs the post-request event for a GraphQL query. + * + * @param mixed $response The response from the GraphQL request. + * @param mixed $result The result of the GraphQL request. + * @param string $operation_name The name of the operation. + * @param string $query The GraphQL query. + * @param array $variables The variables for the query. + */ + public function log_post_request( $response, $result, string $operation_name, string $query, array $variables ): void { + + try { + $context = []; + $level = Level::Info; + $context = apply_filters( 'wpgraphql_logging_post_request_context', $context, $response, $result, $operation_name, $query, $variables ); + $level = apply_filters( 'wpgraphql_logging_post_request_level', $level, $response, $result, $operation_name, $query, $variables ); + $this->logger->log( $level, 'WPGraphQL Outgoing Response', $context ); + } catch ( \Throwable $e ) { + // @TODO - Handle logging errors gracefully. + error_log( 'Error in log_post_request: ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log + } + } + + /** + * Register actions and filters. + */ + protected function setup(): void { + + // @TODO: Update POC and use pub/sub for query events. + + /** + * @psalm-suppress HookNotFound + */ + add_action( 'do_graphql_request', [ $this, 'log_pre_request' ], 10, 3 ); + + /** + * @psalm-suppress HookNotFound + */ + add_action( 'graphql_process_http_request_response', [ $this, 'log_post_request' ], 10, 5 ); + } +} diff --git a/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php b/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php index 8b5e908f..a6636f91 100644 --- a/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php +++ b/plugins/wpgraphql-logging/src/Hooks/PluginHooks.php @@ -6,6 +6,13 @@ use WPGraphQL\Logging\Logger\Database\DatabaseEntity; +/** + * Hooks for the WPGraphQL Logging plugin. + * + * @package WPGraphQL\Logging + * + * @since 0.0.1 + */ class PluginHooks { /** * The single instance of the class. diff --git a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php index b1e8d075..7385bd46 100644 --- a/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php +++ b/plugins/wpgraphql-logging/src/Logger/Database/DatabaseEntity.php @@ -152,6 +152,68 @@ public function save(): int { return 0; } + /** + * Gets the ID of the log entry. + */ + public function get_id(): ?int { + return $this->id; + } + + /** + * Gets the channel of the log entry. + */ + public function get_channel(): string { + return $this->channel; + } + + /** + * Gets the logging level of the log entry. + */ + public function get_level(): int { + return $this->level; + } + + /** + * Gets the name of the logging level of the log entry. + */ + public function get_level_name(): string { + return $this->level_name; + } + + /** + * Gets the message of the log entry. + */ + public function get_message(): string { + return $this->message; + } + + /** + * Gets the context of the log entry. + * + * @return array The context of the log entry. + */ + public function get_context(): array { + return $this->context; + } + + /** + * Gets the extra data of the log entry. + * + * @return array The extra data of the log entry. + */ + public function get_extra(): array { + return $this->extra; + } + + /** + * Gets the datetime of the log entry. + * + * @return string The datetime of the log entry in MySQL format. + */ + public function get_datetime(): string { + return $this->datetime; + } + /** * Gets the name of the logging table. */ @@ -193,7 +255,7 @@ public static function get_schema(): string { * Creates the logging table in the database. */ public static function create_table(): void { - require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // @phpstan-ignore-line dbDelta( self::get_schema() ); } @@ -250,30 +312,9 @@ private static function create_from_db_row(array $row): self { $log->level = (int) $row['level']; $log->level_name = $row['level_name']; $log->message = $row['message']; - $log->context = $row['context'] ? json_decode( $row['context'], true ) : []; - $log->extra = $row['extra'] ? json_decode( $row['extra'], true ) : []; + $log->context = ( isset( $row['context'] ) && '' !== $row['context'] ) ? json_decode( $row['context'], true ) : []; + $log->extra = ( isset( $row['extra'] ) && '' !== $row['extra'] ) ? json_decode( $row['extra'], true ) : []; $log->datetime = $row['datetime']; return $log; } - - /** - * Magic method to handle dynamic getters like get_level(). - * - * @param string $name The name of the method called. - * @param array $arguments The arguments passed to the method. - * - * @throws \BadMethodCallException If the method does not exist. - * - * @return mixed The value of the property if it exists, otherwise throws an exception. - */ - public function __call(string $name, array $arguments) { - if ( strpos( $name, 'get_' ) === 0 ) { - $property = substr( $name, 4 ); - if ( property_exists( $this, $property ) ) { - return $this->$property; - } - } - $name = $this->sanitize_text_field( $name ); - throw new \BadMethodCallException( sprintf( 'Method %s does not exist.', esc_html( $name ) ) ); - } } diff --git a/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php b/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php index 47c470b4..74a3b9e0 100644 --- a/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php +++ b/plugins/wpgraphql-logging/src/Logger/Handlers/WordPressDatabaseHandler.php @@ -27,14 +27,13 @@ class WordPressDatabaseHandler extends AbstractProcessingHandler { */ protected function write( LogRecord $record ): void { try { - $name = $record->level->getName(); $entity = DatabaseEntity::create( $record->channel, $record->level->value, - (is_string($name) && $name !== '') ? $name : 'INFO', + $this->get_record_name( $record ), $record->message, - $record->context ?: [], - $record->extra ?: [] + $record->context ?? [], + $record->extra ?? [] ); $entity->save(); @@ -42,4 +41,22 @@ protected function write( LogRecord $record ): void { error_log( 'Error logging to WordPress database: ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } } + + /** + * Gets the name of the log record. + * + * @param \Monolog\LogRecord $record The log record. + * + * @return string The name of the log record. + */ + protected function get_record_name( LogRecord $record ): string { + + /** + * @psalm-suppress InvalidCast + */ + $name = (string) $record->level->getName(); // @phpstan-ignore-line + $default = 'INFO'; + + return $name ?: $default; // @phpstan-ignore-line + } } diff --git a/plugins/wpgraphql-logging/src/Logger/LoggerService.php b/plugins/wpgraphql-logging/src/Logger/LoggerService.php new file mode 100644 index 00000000..e404b0cf --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logger/LoggerService.php @@ -0,0 +1,260 @@ + $handlers The handlers to use for the logger. + * @param array<\Monolog\Processor\ProcessorInterface> $processors The processors to use for the logger. + * @param array $default_context The default context for the logger. + */ + protected function __construct(readonly string $channel, readonly array $handlers, readonly array $processors, readonly array $default_context ) { + + $this->monolog = new Logger( $this->channel ); + + foreach ( $this->handlers as $handler ) { + if ( $handler instanceof HandlerInterface ) { + $this->monolog->pushHandler( $handler ); + } + } + + foreach ( $this->processors as $processor ) { + if ( $processor instanceof ProcessorInterface ) { + $this->monolog->pushProcessor( $processor ); + } + } + } + + /** + * Get the instance of the LoggerService. + * + * This method implements the singleton pattern to ensure only one instance of the logger is created. + * It allows for custom handlers, processors, and default context to be specified. + * + * @param string $channel The channel for the logger. + * @param ?array<\Monolog\Handler\HandlerInterface> $handlers The handlers to use for the logger. + * @param ?array<\Monolog\Processor\ProcessorInterface> $processors The processors to use for the logger. + * @param ?array $default_context The default context for the logger. + */ + public static function get_instance( + string $channel = self::DEFAULT_CHANNEL, + ?array $handlers = null, + ?array $processors = null, + ?array $default_context = null + ): LoggerService { + if ( null !== self::$instance ) { + return self::$instance; + } + + $processors = $processors ?? self::get_default_processors(); + $handlers = $handlers ?? self::get_default_handlers(); + $default_context = $default_context ?? self::get_default_context(); + + self::$instance = new self( $channel, $handlers, $processors, $default_context ); + return self::$instance; + } + + /** + * Logs a emergency level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function emergency( string $message, array $context = [] ): void { + $this->monolog->emergency( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a alert level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function alert( string $message, array $context = [] ): void { + $this->monolog->alert( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a critical level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function critical( string $message, array $context = [] ): void { + $this->monolog->critical( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a error level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function error( string $message, array $context = [] ): void { + $this->monolog->error( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a warning level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function warning( string $message, array $context = [] ): void { + $this->monolog->warning( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a notice level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function notice( string $message, array $context = [] ): void { + $this->monolog->notice( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a info level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function info( string $message, array $context = [] ): void { + $this->monolog->info( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a debug level message. + * + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function debug( string $message, array $context = [] ): void { + $this->monolog->debug( $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Logs a log level message. + * + * @param mixed $level The log level (a Monolog, PSR-3 or RFC 5424 level). + * @param string $message The message to log. + * @param array $context Additional context for the log message. + * + * @link https://seldaek.github.io/monolog/doc/01-usage.html#log-levels + */ + public function log( $level, string $message, array $context = [] ): void { + $this->monolog->log( $level, $message, array_merge( $this->default_context, $context ) ); + } + + /** + * Returns an array of default processors. + * + * @link https://seldaek.github.io/monolog + * + * @return array<\Monolog\Processor\ProcessorInterface> + */ + public static function get_default_processors(): array { + $default_processors = [ + new MemoryUsageProcessor(), // Logs memory usage data. + new MemoryUsageProcessor(), // Logs memory peak data. + new WebProcessor(), // Logs web request data. e.g. IP address, request method, URI, etc. + new ProcessIdProcessor(), // Logs the process ID. + new WPGraphQLQueryProcessor(), // Custom processor to capture GraphQL request data. + ]; + return apply_filters( 'wpgraphql_logging_default_processors', $default_processors ); + } + + /** + * Returns an array of default processors. + * + * @link https://seldaek.github.io/monolog + * + * @return array<\Monolog\Handler\AbstractProcessingHandler> + */ + public static function get_default_handlers(): array { + $default_handlers = [ + new WordPressDatabaseHandler(), + ]; + return apply_filters( 'wpgraphql_logging_default_handlers', $default_handlers ); + } + + /** + * Gets the default context for the logger. + * + * @return array Default context for the logger. + */ + public static function get_default_context(): array { + $context = [ + 'wp_debug_mode' => defined( 'WP_DEBUG' ) && WP_DEBUG, + 'plugin_version' => defined( 'WPGRAPHQL_LOGGING_VERSION' ) ? WPGRAPHQL_LOGGING_VERSION : 'undefined', + 'wp_version' => get_bloginfo( 'version' ), + 'site_url' => home_url(), + ]; + + return apply_filters( 'wpgraphql_logging_default_context', $context ); + } +} diff --git a/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php b/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php new file mode 100644 index 00000000..ca7cd1b6 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php @@ -0,0 +1,102 @@ +|null + */ + protected static ?array $variables = null; + + /** + * The operation name for the current GraphQL request. + * + * @var string|null + */ + protected static ?string $operation_name = null; + + /** + * Constructor for the WPGraphQLQueryProcessor. + * + * This constructor sets up the necessary hooks to capture GraphQL request data and clear it after the request is completed. + */ + public function __construct() { + /** + * @psalm-suppress HookNotFound + */ + add_action( 'graphql_request_data', [ self::class, 'capture_request_data' ], 10, 1 ); // @phpstan-ignore-line + + /** + * @psalm-suppress HookNotFound + */ + add_action( 'graphql_process_http_request_response', [ self::class, 'clear_request_data' ], 10, 0 ); + } + + /** + * Captures the GraphQL request data. + * + * @param array $request_data The raw request data from WPGraphQL. + * + * @return array The raw request data from WPGraphQL. + */ + public static function capture_request_data(array $request_data): array { + self::$query = $request_data['query'] ?? null; + self::$variables = $request_data['variables'] ?? null; + self::$operation_name = $request_data['operationName'] ?? null; + + return $request_data; + } + + /** + * Clears the stored GraphQL request data to ensure it does not persist across requests. + */ + public static function clear_request_data(): void { + self::$query = null; + self::$variables = null; + self::$operation_name = null; + } + + /** + * This method is called for each log record. It adds the captured + * GraphQL data to the record's 'extra' array. + * + * @param \Monolog\LogRecord $record The log record to process. + * + * @return \Monolog\LogRecord The processed log record. + */ + public function __invoke(LogRecord $record): LogRecord { + if ( null !== self::$query ) { + $record->extra['wpgraphql_query'] = self::$query; + } + if ( null !== self::$operation_name ) { + $record->extra['wpgraphql_operation_name'] = self::$operation_name; + } + if ( null !== self::$variables ) { + $record->extra['wpgraphql_variables'] = self::$variables; + } + + return $record; + } +} diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php index 61c81f02..b825e08f 100644 --- a/plugins/wpgraphql-logging/src/Plugin.php +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -4,6 +4,7 @@ namespace WPGraphQL\Logging; +use WPGraphQL\Logging\Events\QueryEventLifecycle; use WPGraphQL\Logging\Hooks\PluginHooks; /** @@ -51,6 +52,7 @@ public static function init(): self { */ public function setup(): void { PluginHooks::init(); + QueryEventLifecycle::init(); } /** diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php index 29156ee0..ac4ffc9f 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php @@ -73,9 +73,9 @@ public function test_save_method_inserts_log_into_database(): void $this->assertEquals($log_data['context'], $entity->get_context(), 'The context should match the saved data.'); $this->assertEquals($log_data['extra'], $entity->get_extra(), 'The extra data should match the saved data.'); - // Test for a field which doesn't exist - $this->expectException(\BadMethodCallException::class); - $entity->get_nonexistent_field(); + $this->assertNotEmpty($entity->get_datetime(), 'The datetime should not be empty.'); + $this->assertIsInt($entity->get_id(), 'The ID should be an integer.'); + $this->assertGreaterThan(0, $entity->get_id(), 'The ID should be greater than 0.'); } public function test_find_returns_null_for_nonexistent_id(): void From 5dc17d683c459d74887ad303b53667ea3ab5c618 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 17:59:36 +0100 Subject: [PATCH 10/19] Fixing issue for new plugins that do not exist when creating a plugin artifact. --- .github/scripts/get_plugin_slug.sh | 7 +++++-- .github/workflows/plugin-artifact-for-pr.yml | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/scripts/get_plugin_slug.sh b/.github/scripts/get_plugin_slug.sh index 3768a4c9..3e86aace 100644 --- a/.github/scripts/get_plugin_slug.sh +++ b/.github/scripts/get_plugin_slug.sh @@ -32,9 +32,9 @@ UNIQUE_PLUGINS=($(printf '%s\n' "${PLUGINS[@]}" | sort -u)) # Find the first plugin that actually exists PLUGIN_SLUG="" for plugin in "${UNIQUE_PLUGINS[@]}"; do - if [ -d "plugins/$plugin" ]; then + if [ -d "plugins/$plugin" ] || [[ " ${CHANGED_FILES[@]} " =~ "plugins/$plugin/" ]]; then PLUGIN_SLUG="$plugin" - echo "Found existing plugin directory: $PLUGIN_SLUG" + echo "Found plugin in changes or directory: $PLUGIN_SLUG" break fi done @@ -45,3 +45,6 @@ if [ -z "$PLUGIN_SLUG" ]; then fi echo "slug=$PLUGIN_SLUG" >> "$GITHUB_OUTPUT" + +echo "Changed files: $CHANGED_FILES" +echo "Detected plugin(s): ${UNIQUE_PLUGINS[*]}" diff --git a/.github/workflows/plugin-artifact-for-pr.yml b/.github/workflows/plugin-artifact-for-pr.yml index 33fc1ed6..42db7a99 100644 --- a/.github/workflows/plugin-artifact-for-pr.yml +++ b/.github/workflows/plugin-artifact-for-pr.yml @@ -16,6 +16,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 - name: Get changed plugin directory id: plugin From 60c6dd71fa485035960d771bcc13ee45b421844b Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 18:03:04 +0100 Subject: [PATCH 11/19] Fix plugin slug script to use correct PR head SHA --- .github/workflows/plugin-artifact-for-pr.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/plugin-artifact-for-pr.yml b/.github/workflows/plugin-artifact-for-pr.yml index 42db7a99..c897155c 100644 --- a/.github/workflows/plugin-artifact-for-pr.yml +++ b/.github/workflows/plugin-artifact-for-pr.yml @@ -16,14 +16,13 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - name: Get changed plugin directory id: plugin run: | - bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh \ + ${{ github.event.pull_request.base.sha }} \ + ${{ github.event.pull_request.head.sha }} - name: Create plugin artifact uses: ./.github/actions/create-plugin-artifact From f37f1258610ea40e89b226c3d77a820d0ee77f70 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 18:06:03 +0100 Subject: [PATCH 12/19] Added fixes for other workflows. --- .github/workflows/code-quality.yml | 4 +++- .github/workflows/codeception.yml | 4 +++- .github/workflows/e2e-test.yml | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index af169d0c..1001c2de 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -34,7 +34,9 @@ jobs: if [ "${{ github.event_name }}" = "push" ]; then bash .github/scripts/get_plugin_slug.sh main else - bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh \ + ${{ github.event.pull_request.base.sha }} \ + ${{ github.event.pull_request.head.sha }} fi - name: Detect changed plugins with quality config diff --git a/.github/workflows/codeception.yml b/.github/workflows/codeception.yml index f32f62af..1c13e648 100644 --- a/.github/workflows/codeception.yml +++ b/.github/workflows/codeception.yml @@ -41,7 +41,9 @@ jobs: if [ "${{ github.event_name }}" = "push" ]; then bash .github/scripts/get_plugin_slug.sh main else - bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh \ + ${{ github.event.pull_request.base.sha }} \ + ${{ github.event.pull_request.head.sha }} fi - name: Detect changed plugins with quality config diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 8785b23b..32ba4cfa 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -43,7 +43,9 @@ jobs: if [ "${{ github.event_name }}" = "push" ]; then bash .github/scripts/get_plugin_slug.sh main else - bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh \ + ${{ github.event.pull_request.base.sha }} \ + ${{ github.event.pull_request.head.sha }} fi - name: Detect changed plugin with E2E config From 486539c9db14ae46d29ee2a7ff2fee911c7c58a9 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 18:29:47 +0100 Subject: [PATCH 13/19] Updated code quality to check min PHP version from the composer.json file. --- .github/workflows/code-quality.yml | 22 +++++++++++++++++++++- plugins/wpgraphql-logging/phpcs.xml | 4 ---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 1001c2de..913d64c7 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -24,6 +24,7 @@ jobs: outputs: plugins: ${{ steps.detect.outputs.plugins }} has-plugins: ${{ steps.detect.outputs.has-plugins }} + php-version: ${{ steps.detect-php-version.outputs.php-version }} steps: - name: Checkout uses: actions/checkout@v4 @@ -40,7 +41,7 @@ jobs: fi - name: Detect changed plugins with quality config - id: detect + id: detect-plugin-slug run: | if [ -z "${{ steps.plugin.outputs.slug }}" ]; then echo "No plugin slug detected" @@ -60,6 +61,23 @@ jobs: echo "has-plugins=false" >> $GITHUB_OUTPUT echo "ℹ️ No phpcs.xml found for plugin: $PLUGIN, skipping quality checks" fi + - name: Detect changed plugins with quality config + id: detect-php-version + run: | + PLUGIN="${{ steps.plugin.outputs.slug }}" + PHP_VERSION="7.4" + if [ -f "plugins/$PLUGIN/composer.json" ]; then + DETECTED_VERSION=$(jq -r '.require["php"] // empty' plugins/$PLUGIN/composer.json | grep -oE '[0-9]+\.[0-9]+' | head -1) + if [ -n "$DETECTED_VERSION" ]; then + PHP_VERSION="$DETECTED_VERSION" + echo "Detected PHP version $PHP_VERSION from composer.json" + else + echo "No PHP version found in composer.json, using default $PHP_VERSION" + fi + else + echo "No composer.json found, using default PHP version $PHP_VERSION" + fi + echo "php-version=$PHP_VERSION" >> $GITHUB_OUTPUT quality-checks: needs: detect-plugins if: needs.detect-plugins.outputs.has-plugins == 'true' @@ -77,3 +95,5 @@ jobs: uses: ./.github/actions/code-quality with: working-directory: plugins/${{ matrix.plugin }} + php-version: ${{ needs.detect-plugins.outputs.php-version }} + composer-options: '--no-progress --no-suggest' diff --git a/plugins/wpgraphql-logging/phpcs.xml b/plugins/wpgraphql-logging/phpcs.xml index 9f3468e7..73b9450e 100644 --- a/plugins/wpgraphql-logging/phpcs.xml +++ b/plugins/wpgraphql-logging/phpcs.xml @@ -210,10 +210,6 @@ - - - - From 198a41581880d8386984b8a95bd400e8815ab8ac Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 18:31:23 +0100 Subject: [PATCH 14/19] Updated wording. --- .github/workflows/code-quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 913d64c7..e02823ea 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -61,7 +61,7 @@ jobs: echo "has-plugins=false" >> $GITHUB_OUTPUT echo "ℹ️ No phpcs.xml found for plugin: $PLUGIN, skipping quality checks" fi - - name: Detect changed plugins with quality config + - name: Detect PHP version from composer.json id: detect-php-version run: | PLUGIN="${{ steps.plugin.outputs.slug }}" From 6c7b52fba936dad31b5378e48f619d150cf4d3ca Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 18:34:07 +0100 Subject: [PATCH 15/19] Fixes for logger service and query processor. --- plugins/wpgraphql-logging/src/Logger/LoggerService.php | 3 ++- .../src/Logger/Processors/WPGraphQLQueryProcessor.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/wpgraphql-logging/src/Logger/LoggerService.php b/plugins/wpgraphql-logging/src/Logger/LoggerService.php index e404b0cf..65d13738 100644 --- a/plugins/wpgraphql-logging/src/Logger/LoggerService.php +++ b/plugins/wpgraphql-logging/src/Logger/LoggerService.php @@ -6,6 +6,7 @@ use Monolog\Handler\HandlerInterface; use Monolog\Logger; +use Monolog\Processor\MemoryPeakUsageProcessor; use Monolog\Processor\MemoryUsageProcessor; use Monolog\Processor\ProcessIdProcessor; use Monolog\Processor\ProcessorInterface; @@ -220,7 +221,7 @@ public function log( $level, string $message, array $context = [] ): void { public static function get_default_processors(): array { $default_processors = [ new MemoryUsageProcessor(), // Logs memory usage data. - new MemoryUsageProcessor(), // Logs memory peak data. + new MemoryPeakUsageProcessor(), // Logs memory peak data. new WebProcessor(), // Logs web request data. e.g. IP address, request method, URI, etc. new ProcessIdProcessor(), // Logs the process ID. new WPGraphQLQueryProcessor(), // Custom processor to capture GraphQL request data. diff --git a/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php b/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php index ca7cd1b6..9fdfec6a 100644 --- a/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php +++ b/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php @@ -51,7 +51,7 @@ public function __construct() { /** * @psalm-suppress HookNotFound */ - add_action( 'graphql_process_http_request_response', [ self::class, 'clear_request_data' ], 10, 0 ); + add_action( 'graphql_process_http_request_response', [ self::class, 'clear_request_data' ], 999, 0 ); } /** From 9e26179ca2604ea7e2866e24346dd251feb6d401 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 19:07:16 +0100 Subject: [PATCH 16/19] Improved tests for writing data to be more accurate. --- .../Logger/Database/DatabaseEntityTest.php | 27 ++++++++++++++----- .../Handlers/WordPressDatabaseHandlerTest.php | 25 ++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php index ac4ffc9f..be28c3a3 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php @@ -5,6 +5,7 @@ namespace WPGraphQL\Logging\Tests\Database; use lucatume\WPBrowser\TestCase\WPTestCase; +use DateTimeImmutable; use ReflectionClass; use WPGraphQL\Logging\Logger\Database\DatabaseEntity; @@ -47,14 +48,28 @@ public function test_save_method_inserts_log_into_database(): void 'channel' => 'wpgraphql_logging', 'level' => 200, 'level_name' => 'INFO', - 'message' => 'query GetPosts { posts { nodes { id title content } } }', + 'message' => 'WPGraphQL Outgoing Response', 'context' => [ - 'operation' => 'query', - 'name' => 'GetPosts', - 'memory' => '4MB', - 'usage' => 'fetch posts data' + 'site_url' => 'http://test.local', + 'wp_version' => '6.8.2', + 'wp_debug_mode' => true, + 'plugin_version'=> '0.0.1' ], - 'extra' => ['ip' => '127.0.0.1'], + 'extra' => [ + 'ip' => '127.0.0.1', + 'url' => '/index.php?graphql', + 'server' => 'test.local', + 'referrer' => 'http://test.local/wp-admin/admin.php?page=graphiql-ide', + 'process_id' => 5819, + 'http_method' => 'POST', + 'memory_usage' => '14 MB', + 'wpgraphql_query' => 'query GetPost($uri: ID!) { post(id: $uri, idType: URI) { title content } }', + 'memory_peak_usage' => '14 MB', + 'wpgraphql_variables' => [ + 'uri' => 'hello-world' + ], + 'wpgraphql_operation_name' => 'GetPost' + ] ]; // Create and save the entity diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php index 5c497aba..9ec2c9ee 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php @@ -34,9 +34,28 @@ public function setUp(): void $this->log_data = [ 'channel' => 'wpgraphql_logging', 'level' => Level::Info, - 'message' => 'Test log message', - 'context' => ['test_key' => 'test_value'], - 'extra' => ['extra_key' => 'extra_value'], + 'message' => 'WPGraphQL Outgoing Response', + 'context' => [ + 'site_url' => 'http://test.local', + 'wp_version' => '6.8.2', + 'wp_debug_mode' => true, + 'plugin_version'=> '0.0.1' + ], + 'extra' => [ + 'ip' => '127.0.0.1', + 'url' => '/index.php?graphql', + 'server' => 'test.local', + 'referrer' => 'http://test.local/wp-admin/admin.php?page=graphiql-ide', + 'process_id' => 5819, + 'http_method' => 'POST', + 'memory_usage' => '14 MB', + 'wpgraphql_query' => 'query GetPost($uri: ID!) { post(id: $uri, idType: URI) { title content } }', + 'memory_peak_usage' => '14 MB', + 'wpgraphql_variables' => [ + 'uri' => 'hello-world' + ], + 'wpgraphql_operation_name' => 'GetPost' + ], 'datetime' => new DateTimeImmutable(), ]; From 2590baa5bfd3e8a5e05f4beca85cacbc2a030de7 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 28 Jul 2025 19:12:24 +0100 Subject: [PATCH 17/19] Added tests for WPGRaphQLQueryProcessor --- .../tests/wpunit/Hooks/PluginHooksTest.php | 6 +- .../Logger/Database/DatabaseEntityTest.php | 5 +- .../Handlers/WordPressDatabaseHandlerTest.php | 5 +- .../WPGraphQLQueryProcessorTest.php | 135 ++++++++++++++++++ 4 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php diff --git a/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php b/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php index 5077a550..af9cd4d4 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Hooks/PluginHooksTest.php @@ -10,10 +10,12 @@ use WPGraphQL\Logging\Logger\Database\DatabaseEntity; /** - * Class PluginTest + * Class PluginHooksTest * - * Tests for the Plugin class + * Tests for the PluginHooks class. * + * @package WPGraphQL\Logging + * @since 0.0.1 */ class PluginHooksTest extends WPTestCase { diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php index be28c3a3..0be1c628 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Database/DatabaseEntityTest.php @@ -12,7 +12,10 @@ /** * Class DatabaseEntityTest * - * Tests for the DatabaseEntity class + * Tests for the DatabaseEntity class. + * + * @package WPGraphQL\Logging + * @since 0.0.1 */ class DatabaseEntityTest extends WPTestCase { diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php index 9ec2c9ee..7b908d53 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php @@ -12,9 +12,12 @@ use WPGraphQL\Logging\Logger\Handlers\WordPressDatabaseHandler; /** - * Class WordPressDatabaseHandlerTest + * Class WPGraphQLQueryProcessorTest * * Tests for the WordPressDatabaseHandler class. + * + * @package WPGraphQL\Logging + * @since 0.0.1 */ class WordPressDatabaseHandlerTest extends WPTestCase { diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php new file mode 100644 index 00000000..6e56b651 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php @@ -0,0 +1,135 @@ +get_test_record(); + + $processed_record = $processor($record); + + $this->assertEmpty($processed_record->extra, 'Extra array should be empty when no data is captured.'); + } + + public function test_invoke_adds_captured_data_to_log_record(): void + { + $request_data = [ + 'query' => 'query TestQuery { posts { nodes { id } } }', + 'variables' => ['first' => 10], + 'operationName' => 'TestQuery', + ]; + + // Manually capture the data to simulate a GraphQL request starting. + WPGraphQLQueryProcessor::capture_request_data($request_data); + + $processor = new WPGraphQLQueryProcessor(); + $record = $this->get_test_record(); + + $processed_record = $processor($record); + + // Assert that the extra array contains the correct GraphQL data. + $this->assertArrayHasKey('wpgraphql_query', $processed_record->extra); + $this->assertEquals($request_data['query'], $processed_record->extra['wpgraphql_query']); + + $this->assertArrayHasKey('wpgraphql_operation_name', $processed_record->extra); + $this->assertEquals($request_data['operationName'], $processed_record->extra['wpgraphql_operation_name']); + + $this->assertArrayHasKey('wpgraphql_variables', $processed_record->extra); + $this->assertEquals($request_data['variables'], $processed_record->extra['wpgraphql_variables']); + } + + public function test_clear_request_data_resets_static_properties(): void + { + // 1. Capture some data. + WPGraphQLQueryProcessor::capture_request_data([ + 'query' => 'query Test { posts { nodes { id } } }' + ]); + + // 2. Call the clear method. + WPGraphQLQueryProcessor::clear_request_data(); + + // 3. Use reflection to access the private static properties and check their values. + $query_prop = new ReflectionProperty(WPGraphQLQueryProcessor::class, 'query'); + $query_prop->setAccessible(true); + $this->assertNull($query_prop->getValue(), 'The static query property should be null after clearing.'); + + $variables_prop = new ReflectionProperty(WPGraphQLQueryProcessor::class, 'variables'); + $variables_prop->setAccessible(true); + $this->assertNull($variables_prop->getValue(), 'The static variables property should be null after clearing.'); + + $operation_name_prop = new ReflectionProperty(WPGraphQLQueryProcessor::class, 'operation_name'); + $operation_name_prop->setAccessible(true); + $this->assertNull($operation_name_prop->getValue(), 'The static operation_name property should be null after clearing.'); + } + + /** + * @test + * It should hook into WordPress actions upon instantiation. + */ + public function test_constructor_hooks_into_wordpress_actions(): void + { + // Instantiate the processor to trigger its constructor. + $processor = new WPGraphQLQueryProcessor(); + + // Check if the hooks have been added correctly. + $this->assertNotFalse( + has_action('graphql_request_data', [WPGraphQLQueryProcessor::class, 'capture_request_data']), + 'The capture_request_data method should be hooked to graphql_request_data.' + ); + + $this->assertNotFalse( + has_action('graphql_process_http_request_response', [WPGraphQLQueryProcessor::class, 'clear_request_data']), + 'The clear_request_data method should be hooked to graphql_process_http_request_response.' + ); + + // Clean up the hooks after the test. + remove_action('graphql_request_data', [WPGraphQLQueryProcessor::class, 'capture_request_data'], 10); + remove_action('graphql_process_http_request_response', [WPGraphQLQueryProcessor::class, 'clear_request_data'], 999); + } + + /** + * Helper method to get a basic LogRecord for testing. + */ + private function get_test_record(): LogRecord + { + return new LogRecord( + new DateTimeImmutable(), + 'test-channel', + Level::Debug, + 'This is a test message.' + ); + } +} From 8127de1a12326cc4112b16fe5d384826befcde09 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 29 Jul 2025 10:14:50 +0100 Subject: [PATCH 18/19] Update logger service instance to get singleton instance by channel name. Added unit tests. --- .../wpgraphql-logging/codeception.dist.yml | 2 +- .../src/Logger/LoggerService.php | 14 +- .../tests/wpunit/Logger/LoggerServiceTest.php | 154 ++++++++++++++++++ 3 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 plugins/wpgraphql-logging/tests/wpunit/Logger/LoggerServiceTest.php diff --git a/plugins/wpgraphql-logging/codeception.dist.yml b/plugins/wpgraphql-logging/codeception.dist.yml index b96fa262..adb25dc4 100644 --- a/plugins/wpgraphql-logging/codeception.dist.yml +++ b/plugins/wpgraphql-logging/codeception.dist.yml @@ -51,7 +51,7 @@ coverage: - /vendor/* - /src/Templates/* show_only_summary: true - min_coverage: 90 + min_coverage: 85 modules: config: REST: diff --git a/plugins/wpgraphql-logging/src/Logger/LoggerService.php b/plugins/wpgraphql-logging/src/Logger/LoggerService.php index 65d13738..fb50ec7d 100644 --- a/plugins/wpgraphql-logging/src/Logger/LoggerService.php +++ b/plugins/wpgraphql-logging/src/Logger/LoggerService.php @@ -42,11 +42,11 @@ class LoggerService { protected readonly Logger $monolog; /** - * The instance of the logger. + * The instance of the logger based off the channel name. * - * @var \WPGraphQL\Logging\Logger\LoggerService|null + * @var array */ - protected static ?LoggerService $instance = null; + protected static array $instances = []; /** * Constructor for the LoggerService and initializes the Monolog logger with the provided channel, handlers, processors, and default context. @@ -90,16 +90,16 @@ public static function get_instance( ?array $processors = null, ?array $default_context = null ): LoggerService { - if ( null !== self::$instance ) { - return self::$instance; + if ( isset(self::$instances[$channel]) ) { + return self::$instances[$channel]; } $processors = $processors ?? self::get_default_processors(); $handlers = $handlers ?? self::get_default_handlers(); $default_context = $default_context ?? self::get_default_context(); - self::$instance = new self( $channel, $handlers, $processors, $default_context ); - return self::$instance; + self::$instances[$channel] = new self( $channel, $handlers, $processors, $default_context ); + return self::$instances[$channel]; } /** diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/LoggerServiceTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/LoggerServiceTest.php new file mode 100644 index 00000000..3d896953 --- /dev/null +++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/LoggerServiceTest.php @@ -0,0 +1,154 @@ +reset_logger_instance(); + } + + private function reset_logger_instance(): void + { + $reflection = new ReflectionClass(LoggerService::class); + $instance_prop = $reflection->getProperty('instances'); + $instance_prop->setAccessible(true); + $instance_prop->setValue(null, []); + } + + private function get_monolog_instance(LoggerService $service): \Monolog\Logger + { + $reflection = new ReflectionClass($service); + $monolog_prop = $reflection->getProperty('monolog'); + $monolog_prop->setAccessible(true); + return $monolog_prop->getValue($service); + } + + public function test_get_instance_returns_singleton(): void + { + $instance1 = LoggerService::get_instance(); + $instance2 = LoggerService::get_instance(); + + $this->assertSame($instance1, $instance2, 'get_instance() should always return the same object.'); + + $instance3 = LoggerService::get_instance('custom_channel'); + $this->assertInstanceOf(LoggerService::class, $instance3, 'Instance should be of type LoggerService.'); + $this->assertNotSame($instance1, $instance3, 'get_instance() should return different instances for different channels.'); + $this->assertEquals('custom_channel', $instance3->channel); + + $monolog = $this->get_monolog_instance($instance3); + $this->assertCount(count(LoggerService::get_default_handlers()), $monolog->getHandlers(), 'Should have the default number of handlers.'); + $this->assertCount(count(LoggerService::get_default_processors()), $monolog->getProcessors(), 'Should have the default number of processors.'); + } + + public function test_get_instance_with_custom_configuration(): void + { + $custom_handler = new TestHandler(); + $custom_processor = new class implements ProcessorInterface { + public function __invoke(LogRecord $record): LogRecord + { + $record = $record->with(extra: array_merge($record->extra, ['custom' => true])); + return $record; + } + }; + + $logger_service = LoggerService::get_instance( + 'custom_channel', + [$custom_handler], + [$custom_processor] + ); + + $monolog = $this->get_monolog_instance($logger_service); + + $this->assertEquals('custom_channel', $monolog->getName()); + $this->assertCount(1, $monolog->getHandlers()); + $this->assertSame($custom_handler, $monolog->getHandlers()[0]); + $this->assertCount(1, $monolog->getProcessors()); + } + + /** + * Provides log levels and corresponding LoggerService methods. + */ + public function logLevelProvider(): array + { + return [ + ['debug', 'debug'], + ['info', 'info'], + ['notice', 'notice'], + ['warning', 'warning'], + ['error', 'error'], + ['critical', 'critical'], + ['alert', 'alert'], + ['emergency','emergency'], + ]; + } + + /** + * @dataProvider logLevelProvider + */ + public function test_logging_methods_write_to_handler(string $level, string $method): void + { + $test_handler = new TestHandler(); + $logger_service = LoggerService::get_instance( + 'log_test_channel_' . $level, + [$test_handler], + [], + ['default_key' => 'default_value'] + ); + + $message = "Test $level message"; + $context = ['foo' => 'bar']; + + $logger_service->$method($message, $context); + + $checkMethod = 'has' . ucfirst($level) . 'Records'; + $this->assertTrue($test_handler->$checkMethod(), "Handler should have $level record."); + + $records = $test_handler->getRecords(); + $this->assertNotEmpty($records, 'Handler should have at least one record.'); + $record = $records[0]; + + $this->assertEquals($message, $record['message']); + $this->assertArrayHasKey('default_key', $record['context']); + $this->assertEquals('default_value', $record['context']['default_key']); + $this->assertArrayHasKey('foo', $record['context']); + $this->assertEquals('bar', $record['context']['foo']); + } + + public function test_log_method_accepts_arbitrary_level(): void + { + $test_handler = new TestHandler(); + $logger_service = LoggerService::get_instance( + 'arbitrary_level', + [$test_handler], + [], + ['default_key' => 'default_value'] + ); + + $logger_service->log('notice', 'Arbitrary level message', ['baz' => 'qux']); + + $this->assertTrue($test_handler->hasNoticeRecords()); + $records = $test_handler->getRecords(); + $this->assertEquals('Arbitrary level message', $records[0]['message']); + $this->assertEquals('default_value', $records[0]['context']['default_key']); + $this->assertEquals('qux', $records[0]['context']['baz']); + } +} From a17b273ad436d0a5daa1e0f8a562b8be5979c4d5 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 29 Jul 2025 10:41:41 +0100 Subject: [PATCH 19/19] Updated README --- plugins/wpgraphql-logging/README.md | 82 +++++++++++++++++++++++++++- plugins/wpgraphql-logging/readme.txt | 1 + 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/plugins/wpgraphql-logging/README.md b/plugins/wpgraphql-logging/README.md index 33c22eee..65cefa3c 100644 --- a/plugins/wpgraphql-logging/README.md +++ b/plugins/wpgraphql-logging/README.md @@ -5,16 +5,92 @@ A WPGraphQL logging plugin that provides visibility into request lifecycle to he * [Join the Headless WordPress community on Discord.](https://discord.gg/headless-wordpress-836253505944813629) * [Documentation](#getting-started) +> [!CAUTION] +> This plugin is currently in development state and is not production ready. ----- -TODO +@TODO - Badges ----- -> [!CAUTION] -> This plugin is currently a POC and not production ready yet. +## Table of Contents + +- [Overview](#overview) +- [Features](#features) +- [Getting Started](#getting-started) +- [Configuration](#configuration) +- [Extending the Functionality](#extending-the-functionality) +- [Testing](#testing) + + +----- + +## Overview + + +WPGraphQL Logging is a plugin that integrates directly with the WPGraphQL Query Lifecycle, capturing detailed information about each GraphQL request. By leveraging the powerful [Monolog](https://github.com/Seldaek/monolog) logging library, it records events and metrics that help you quickly identify performance bottlenecks and other issues in your headless WordPress application. + +Designed with extensibility in mind, developers can easily customize and extend the logging functionality to suit their specific needs, making it a valuable tool for debugging and optimizing WPGraphQL-powered sites. + +--- + +## Features + +@TODO + + +## Getting Started + +@TODO + + +--- + +## Project Structure + +```text +wpgraphql-logging/ +├── src/ # Main plugin source code +│ ├── Admin/ # Admin settings, menu, and settings page logic +│ ├── Events/ # Event definitions and event dispatcher logic +│ ├── Hooks/ # WordPress hooks and filters +│ ├── Logging/ # Logging logic, logger service, Monolog handlers & processors +│ ├── Plugin.php # Main plugin class (entry point) +│ └── Autoload.php # PSR-4 autoloader +├── tests/ # All test suites +│ ├── wpunit/ # WPBrowser/Codeception unit tests +├── [wpgraphql-logging.php] +├── [activation.php] +├── [composer.json] +├── [deactivation.php] +├── [ACTIONS_AND_FILTERS.md] +├── [TESTING.md] +├── [README.md] +``` + +## Configuration + +@TODO - When we integrate plugin configuration. + +### Settings + +@TODO - When we integrate plugin configuration. --- + +## Actions & Filters + +See the [Actions & Filters documentation](ACTIONS_AND_FILTERS.md) for a comprehensive list of available hooks and how to use them. + +--- + +## Testing + +See [Testing.md](TESTING.md) for details on how to test the plugin. + +## Screenshots + +@TODO - When before BETA release. diff --git a/plugins/wpgraphql-logging/readme.txt b/plugins/wpgraphql-logging/readme.txt index 8c4c97cf..f3d015bc 100644 --- a/plugins/wpgraphql-logging/readme.txt +++ b/plugins/wpgraphql-logging/readme.txt @@ -13,6 +13,7 @@ License URI: https://www.gnu.org/licenses/gpl-2.0.html A WPGraphQL logging plugin that provides visibility into request lifecycle to help quickly identify and resolve bottlenecks in your headless WordPress application. +@TODO == Upgrade Notice == == Frequently Asked Questions == == Screenshots ==