From da3c5f8cd47b5e139cc3d2960b53f48045b15c03 Mon Sep 17 00:00:00 2001 From: Walmir Silva Date: Wed, 16 Oct 2024 13:46:47 -0300 Subject: [PATCH 1/7] feat: structured project base for KaririCode Exception - Added base folder structure - Configured Composer with dependencies and autoload settings - Included development tools: PHPUnit, PHPStan, PHP CS Fixer, and PHP CodeSniffer - Added Docker setup with docker-compose.yml - Provided example environment configuration (.env.example) --- .docker/php/Dockerfile | 25 + .docker/php/kariricode-php.ini | 14 + .env.example | 3 + .gitattributes | 17 + .github/workflows/kariri-ci-cd.yml | 72 + .gitignore | 66 + .php-cs-fixer.php | 69 + .vscode/settings.json | 10 + Makefile | 174 + README.md | 68 + README.pt-br.md | 68 + composer.json | 46 + composer.lock | 4921 ++++++++++++++++++++++++++++ docker-compose.yml | 15 + phpcs.xml | 22 + phpinsights.php | 60 + phpstan.neon | 7 + phpunit.xml | 37 + psalm.xml | 32 + tests/application.php | 5 + 20 files changed, 5731 insertions(+) create mode 100644 .docker/php/Dockerfile create mode 100644 .docker/php/kariricode-php.ini create mode 100644 .env.example create mode 100644 .gitattributes create mode 100644 .github/workflows/kariri-ci-cd.yml create mode 100644 .gitignore create mode 100644 .php-cs-fixer.php create mode 100644 .vscode/settings.json create mode 100644 Makefile create mode 100644 README.md create mode 100644 README.pt-br.md create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 docker-compose.yml create mode 100644 phpcs.xml create mode 100644 phpinsights.php create mode 100644 phpstan.neon create mode 100644 phpunit.xml create mode 100644 psalm.xml create mode 100644 tests/application.php diff --git a/.docker/php/Dockerfile b/.docker/php/Dockerfile new file mode 100644 index 0000000..a3a7de4 --- /dev/null +++ b/.docker/php/Dockerfile @@ -0,0 +1,25 @@ +ARG PHP_VERSION=8.3 + +FROM php:${PHP_VERSION}-alpine + +# Install system dependencies +RUN apk update && apk add --no-cache \ + $PHPIZE_DEPS \ + linux-headers \ + zlib-dev \ + libmemcached-dev \ + cyrus-sasl-dev + +RUN pecl install xdebug redis memcached \ + && docker-php-ext-enable xdebug redis memcached + +# Copy custom PHP configuration +COPY .docker/php/kariricode-php.ini /usr/local/etc/php/conf.d/ + +# Instalação do Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +RUN apk del --purge $PHPIZE_DEPS && rm -rf /var/cache/apk/* + +# Mantém o contêiner ativo sem fazer nada +CMD tail -f /dev/null diff --git a/.docker/php/kariricode-php.ini b/.docker/php/kariricode-php.ini new file mode 100644 index 0000000..9e90446 --- /dev/null +++ b/.docker/php/kariricode-php.ini @@ -0,0 +1,14 @@ +[PHP] +memory_limit = 256M +upload_max_filesize = 50M +post_max_size = 50M +date.timezone = America/Sao_Paulo + +[Xdebug] +; zend_extension=xdebug.so +xdebug.mode=debug +xdebug.start_with_request=yes +xdebug.client_host=host.docker.internal +xdebug.client_port=9003 +xdebug.log=/tmp/xdebug.log +xdebug.idekey=VSCODE diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e461630 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +KARIRI_APP_ENV=develop +KARIRI_PHP_VERSION=8.3 +KARIRI_PHP_PORT=9003 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..31f41b6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +/.docker export-ignore +/.github export-ignore +/.vscode export-ignore +/tests export-ignore +/vendor export-ignore +/.env export-ignore +/.env.example export-ignore +/.gitignore export-ignore +/.php-cs-fixer.php export-ignore +/.phpcs-cache export-ignore +/docker-compose.yml export-ignore +/phpcs.xml export-ignore +/phpinsights.php export-ignore +/phpstan.neon export-ignore +/phpunit.xml export-ignore +/psalm.xml export-ignore +/Makefile export-ignore \ No newline at end of file diff --git a/.github/workflows/kariri-ci-cd.yml b/.github/workflows/kariri-ci-cd.yml new file mode 100644 index 0000000..bd9f272 --- /dev/null +++ b/.github/workflows/kariri-ci-cd.yml @@ -0,0 +1,72 @@ +name: Kariri CI Pipeline + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + setup-and-lint: + runs-on: ubuntu-latest + strategy: + matrix: + php: ["8.3"] + + steps: + - uses: actions/checkout@v3 + + - name: Cache Composer dependencies + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Set up PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: mbstring, xml + tools: composer:v2, php-cs-fixer, phpunit + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Validate composer.json + run: composer validate + + - name: Coding Standards Check + run: vendor/bin/php-cs-fixer fix --dry-run --diff + + unit-tests: + needs: setup-and-lint + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Download Composer Cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Set up PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: mbstring, xml + tools: composer:v2, php-cs-fixer, phpunit + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run PHPUnit Tests + run: XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text + + - name: Security Check + run: vendor/bin/security-checker security:check diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e5baad --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +# Arquivos de configuração do sistema +/.idea/ +*.sublime-project +*.sublime-workspace +/.phpunit.result.cache +/.php_cs.cache +/.php_cs.dist.cache +/phpstan.neon.dist +/phpstan.neon.cache +/.phpstan.result.cache +/.phpcs-cache + +# Dependências +/vendor/ +/node_modules/ + +# Arquivos específicos do sistema operacional +.DS_Store +Thumbs.db + +# Arquivos de build e compilação +/build/ +/dist/ +*.log +*.tlog +*.tmp +*.temp + +# Arquivos e pastas de ambientes virtuais +.env + +# Arquivos de cache +/cache/ +*.cache +*.class + +# Arquivos de log +*.log +*.sql +*.sqlite + +# Pasta de testes que não devem ser incluídas no repositório +coverage/ +coverage* + +# Arquivos de pacotes +*.jar +*.war +*.ear +*.zip +*.tar.gz +*.rar + +# Outros arquivos e pastas +*.swp +*~ +._* +temp/ +tmp/ +.vscode/launch.json +.vscode/extensions.json +tests/lista_de_arquivos.php +tests/lista_de_arquivos_test.php +lista_de_arquivos.txt +lista_de_arquivos_tests.txt +add_static_to_providers.php diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000..c3a51bb --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,69 @@ +in(__DIR__ . '/src') + ->in(__DIR__ . '/tests') + ->exclude('var') + ->exclude('config') + ->exclude('vendor'); + +return (new PhpCsFixer\Config()) + ->setParallelConfig(new PhpCsFixer\Runner\Parallel\ParallelConfig(4, 20)) + ->setRules([ + '@PSR12' => true, + '@Symfony' => true, + 'full_opening_tag' => false, + 'phpdoc_var_without_name' => false, + 'phpdoc_to_comment' => false, + 'array_syntax' => ['syntax' => 'short'], + 'concat_space' => ['spacing' => 'one'], + 'binary_operator_spaces' => [ + 'default' => 'single_space', + 'operators' => [ + '=' => 'single_space', + '=>' => 'single_space', + ], + ], + 'blank_line_before_statement' => [ + 'statements' => ['return'] + ], + 'cast_spaces' => ['space' => 'single'], + 'class_attributes_separation' => [ + 'elements' => [ + 'const' => 'none', + 'method' => 'one', + 'property' => 'none' + ] + ], + 'declare_equal_normalize' => ['space' => 'none'], + 'function_typehint_space' => true, + 'lowercase_cast' => true, + 'no_unused_imports' => true, + 'not_operator_with_successor_space' => true, + 'ordered_imports' => true, + 'phpdoc_align' => ['align' => 'left'], + 'phpdoc_no_alias_tag' => ['replacements' => ['type' => 'var', 'link' => 'see']], + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'single_quote' => true, + 'standardize_not_equals' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], + 'trim_array_spaces' => true, + 'space_after_semicolon' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_whitespace_before_comma_in_array' => true, + 'whitespace_after_comma_in_array' => true, + 'visibility_required' => ['elements' => ['const', 'method', 'property']], + 'multiline_whitespace_before_semicolons' => [ + 'strategy' => 'no_multi_line', + ], + 'method_chaining_indentation' => true, + 'class_definition' => [ + 'single_item_single_line' => false, + 'multi_line_extends_each_single_line' => true, + ], + 'not_operator_with_successor_space' => false + ]) + ->setRiskyAllowed(true) + ->setFinder($finder) + ->setUsingCache(false); diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..38f7f80 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "[php]": { + "editor.defaultFormatter": "junstyle.php-cs-fixer" + }, + "php-cs-fixer.executablePath": "${workspaceFolder}/vendor/bin/php-cs-fixer", + "php-cs-fixer.onsave": true, + "php-cs-fixer.rules": "@PSR12", + "php-cs-fixer.config": ".php_cs.dist", + "php-cs-fixer.formatHtml": true +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..07b1871 --- /dev/null +++ b/Makefile @@ -0,0 +1,174 @@ +# Initial configurations +PHP_SERVICE := kariricode-exception +DC := docker-compose + +# Command to execute commands inside the PHP container +EXEC_PHP := $(DC) exec -T php + +# Icons +CHECK_MARK := ✅ +WARNING := ⚠️ +INFO := ℹ️ + +# Colors +RED := \033[0;31m +GREEN := \033[0;32m +YELLOW := \033[1;33m +NC := \033[0m # No Color + +# Check if Docker is installed +CHECK_DOCKER := @command -v docker > /dev/null 2>&1 || { echo >&2 "${YELLOW}${WARNING} Docker is not installed. Aborting.${NC}"; exit 1; } +# Check if Docker Compose is installed +CHECK_DOCKER_COMPOSE := @command -v docker-compose > /dev/null 2>&1 || { echo >&2 "${YELLOW}${WARNING} Docker Compose is not installed. Aborting.${NC}"; exit 1; } +# Function to check if the container is running +CHECK_CONTAINER_RUNNING := @docker ps | grep $(PHP_SERVICE) > /dev/null 2>&1 || { echo >&2 "${YELLOW}${WARNING} The container $(PHP_SERVICE) is not running. Run 'make up' to start it.${NC}"; exit 1; } +# Check if the .env file exists +CHECK_ENV := @test -f .env || { echo >&2 "${YELLOW}${WARNING} .env file not found. Run 'make setup-env' to configure.${NC}"; exit 1; } + +## setup-env: Copy .env.example to .env if the latter does not exist +setup-env: + @test -f .env || (cp .env.example .env && echo "${GREEN}${CHECK_MARK} .env file created successfully from .env.example${NC}") + +check-environment: + @echo "${GREEN}${INFO} Checking Docker, Docker Compose, and .env file...${NC}" + $(CHECK_DOCKER) + $(CHECK_DOCKER_COMPOSE) + $(CHECK_ENV) + +check-container-running: + $(CHECK_CONTAINER_RUNNING) + +## up: Start all services in the background +up: check-environment + @echo "${GREEN}${INFO} Starting services...${NC}" + @$(DC) up -d + @echo "${GREEN}${CHECK_MARK} Services are up!${NC}" + +## down: Stop and remove all containers +down: check-environment + @echo "${YELLOW}${INFO} Stopping and removing services...${NC}" + @$(DC) down + @echo "${GREEN}${CHECK_MARK} Services stopped and removed!${NC}" + +## build: Build Docker images +build: check-environment + @echo "${YELLOW}${INFO} Building services...${NC}" + @$(DC) build + @echo "${GREEN}${CHECK_MARK} Services built!${NC}" + +## logs: Show container logs +logs: check-environment + @echo "${YELLOW}${INFO} Container logs:${NC}" + @$(DC) logs + +## re-build: Rebuild and restart containers +re-build: check-environment + @echo "${YELLOW}${INFO} Stopping and removing current services...${NC}" + @$(DC) down + @echo "${GREEN}${INFO} Rebuilding services...${NC}" + @$(DC) build + @echo "${GREEN}${INFO} Restarting services...${NC}" + @$(DC) up -d + @echo "${GREEN}${CHECK_MARK} Services rebuilt and restarted successfully!${NC}" + @$(DC) logs + +## shell: Access the shell of the PHP container +shell: check-environment check-container-running + @echo "${GREEN}${INFO} Accessing the shell of the PHP container...${NC}" + @$(DC) exec php sh + +## composer-install: Install Composer dependencies. Use make composer-install [PKG="[vendor/package [version]]"] [DEV="--dev"] +composer-install: check-environment check-container-running + @echo "${GREEN}${INFO} Installing Composer dependencies...${NC}" + @if [ -z "$(PKG)" ]; then \ + $(EXEC_PHP) composer install; \ + else \ + $(EXEC_PHP) composer require $(PKG) $(DEV); \ + fi + @echo "${GREEN}${CHECK_MARK} Composer operation completed!${NC}" + +## composer-remove: Remove Composer dependencies. Usage: make composer-remove PKG="vendor/package" +composer-remove: check-environment check-container-running + @if [ -z "$(PKG)" ]; then \ + echo "${RED}${WARNING} You must specify a package to remove. Usage: make composer-remove PKG=\"vendor/package\"${NC}"; \ + else \ + $(EXEC_PHP) composer remove $(PKG); \ + echo "${GREEN}${CHECK_MARK} Package $(PKG) removed successfully!${NC}"; \ + fi + +## composer-update: Update Composer dependencies +composer-update: check-environment check-container-running + @echo "${GREEN}${INFO} Updating Composer dependencies...${NC}" + $(EXEC_PHP) composer update + @echo "${GREEN}${CHECK_MARK} Dependencies updated!${NC}" + +## test: Run tests +test: check-environment check-container-running + @echo "${GREEN}${INFO} Running tests...${NC}" + $(EXEC_PHP) ./vendor/bin/phpunit --testdox --colors=always tests + @echo "${GREEN}${CHECK_MARK} Tests completed!${NC}" + +## test-file: Run tests on a specific class. Usage: make test-file FILE=[file] +test-file: check-environment check-container-running + @echo "${GREEN}${INFO} Running test for class $(FILE)...${NC}" + $(EXEC_PHP) ./vendor/bin/phpunit --testdox --colors=always tests/$(FILE) + @echo "${GREEN}${CHECK_MARK} Test for class $(FILE) completed!${NC}" + +## coverage: Run test coverage with visual formatting +coverage: check-environment check-container-running + @echo "${GREEN}${INFO} Analyzing test coverage...${NC}" + XDEBUG_MODE=coverage $(EXEC_PHP) ./vendor/bin/phpunit --coverage-text --colors=always tests | ccze -A + +## coverage-html: Run test coverage and generate HTML report +coverage-html: check-environment check-container-running + @echo "${GREEN}${INFO} Analyzing test coverage and generating HTML report...${NC}" + XDEBUG_MODE=coverage $(EXEC_PHP) ./vendor/bin/phpunit --coverage-html ./coverage-report-html tests + @echo "${GREEN}${INFO} Test coverage report generated in ./coverage-report-html${NC}" + +## run-script: Run a PHP script. Usage: make run-script SCRIPT="path/to/script.php" +run-script: check-environment check-container-running + @echo "${GREEN}${INFO} Running script: $(SCRIPT)...${NC}" + $(EXEC_PHP) php $(SCRIPT) + @echo "${GREEN}${CHECK_MARK} Script executed!${NC}" + +## cs-check: Run PHP_CodeSniffer to check code style +cs-check: check-environment check-container-running + @echo "${GREEN}${INFO} Checking code style...${NC}" + $(EXEC_PHP) ./vendor/bin/php-cs-fixer fix --dry-run --diff + @echo "${GREEN}${CHECK_MARK} Code style check completed!${NC}" + +## cs-fix: Run PHP CS Fixer to fix code style +cs-fix: check-environment check-container-running + @echo "${GREEN}${INFO} Fixing code style with PHP CS Fixer...${NC}" + $(EXEC_PHP) ./vendor/bin/php-cs-fixer fix + @echo "${GREEN}${CHECK_MARK} Code style fixed!${NC}" + +## security-check: Check for security vulnerabilities in dependencies +security-check: check-environment check-container-running + @echo "${GREEN}${INFO} Checking for security vulnerabilities with Security Checker...${NC}" + $(EXEC_PHP) ./vendor/bin/security-checker security:check + @echo "${GREEN}${CHECK_MARK} Security check completed!${NC}" + +## quality: Run all quality commands +quality: check-environment check-container-running cs-check test security-check + @echo "${GREEN}${CHECK_MARK} All quality commands executed!${NC}" + +## help: Show initial setup steps and available commands +help: + @echo "${GREEN}Initial setup steps for configuring the project:${NC}" + @echo "1. ${YELLOW}Initial environment setup:${NC}" + @echo " ${GREEN}${CHECK_MARK} Copy the environment file:${NC} make setup-env" + @echo " ${GREEN}${CHECK_MARK} Start the Docker containers:${NC} make up" + @echo " ${GREEN}${CHECK_MARK} Install Composer dependencies:${NC} make composer-install" + @echo "2. ${YELLOW}Development:${NC}" + @echo " ${GREEN}${CHECK_MARK} Access the PHP container shell:${NC} make shell" + @echo " ${GREEN}${CHECK_MARK} Run a PHP script:${NC} make run-script SCRIPT=\"script_name.php\"" + @echo " ${GREEN}${CHECK_MARK} Run the tests:${NC} make test" + @echo "3. ${YELLOW}Maintenance:${NC}" + @echo " ${GREEN}${CHECK_MARK} Update Composer dependencies:${NC} make composer-update" + @echo " ${GREEN}${CHECK_MARK} Clear the application cache:${NC} make cache-clear" + @echo " ${RED}${WARNING} Stop and remove all Docker containers:${NC} make down" + @echo "\n${GREEN}Available commands:${NC}" + @sed -n 's/^##//p' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ": "}; {printf "${YELLOW}%-30s${NC} %s\n", $$1, $$2}' + +.PHONY: setup-env up down build logs re-build shell composer-install composer-remove composer-update test test-file coverage coverage-html run-script cs-check cs-fix security-check quality help diff --git a/README.md b/README.md new file mode 100644 index 0000000..5cfc13b --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# KaririCode Framework: Sanitizer Component + +[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![pt-br](https://img.shields.io/badge/lang-pt--br-green.svg)](README.pt-br.md) + +![PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![PHPUnit](https://img.shields.io/badge/PHPUnit-3776AB?style=for-the-badge&logo=php&logoColor=white) + +### Prerequisites + +- Docker +- Docker Compose +- Make (optional, but recommended for easier command execution) + +### Development Setup + +1. Clone the repository: + + ```bash + git clone https://github.com/KaririCode-Framework/kariricode-exception.git + cd kariricode-exception + ``` + +2. Set up the environment: + + ```bash + make setup-env + ``` + +3. Start the Docker containers: + + ```bash + make up + ``` + +4. Install dependencies: + ```bash + make composer-install + ``` + +### Available Make Commands + +- `make up`: Start all services in the background +- `make down`: Stop and remove all containers +- `make build`: Build Docker images +- `make shell`: Access the PHP container shell +- `make test`: Run tests +- `make coverage`: Run test coverage with visual formatting +- `make cs-fix`: Run PHP CS Fixer to fix code style +- `make quality`: Run all quality commands (cs-check, test, security-check) + +For a full list of available commands, run: + +```bash +make help +``` + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## Support and Community + +- **Documentation**: [https://kariricode.org/docs/sanitizer](https://kariricode.org/docs/sanitizer) +- **Issue Tracker**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-exception/issues) +- **Community**: [KaririCode Club Community](https://kariricode.club) + +--- + +Built with ❤️ by the KaririCode team. Empowering developers to create more secure and robust PHP applications. diff --git a/README.pt-br.md b/README.pt-br.md new file mode 100644 index 0000000..82a1d42 --- /dev/null +++ b/README.pt-br.md @@ -0,0 +1,68 @@ +# Framework KaririCode: Componente Sanitizer + +[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![pt-br](https://img.shields.io/badge/lang-pt--br-green.svg)](README.pt-br.md) + +![PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![PHPUnit](https://img.shields.io/badge/PHPUnit-3776AB?style=for-the-badge&logo=php&logoColor=white) + +### Pré-requisitos + +- Docker +- Docker Compose +- Make (opcional, mas recomendado para execução mais fácil de comandos) + +### Configuração de Desenvolvimento + +1. Clone o repositório: + + ```bash + git clone https://github.com/KaririCode-Framework/kariricode-exception.git + cd kariricode-exception + ``` + +2. Configure o ambiente: + + ```bash + make setup-env + ``` + +3. Inicie os contêineres Docker: + + ```bash + make up + ``` + +4. Instale as dependências: + ```bash + make composer-install + ``` + +### Comandos Make Disponíveis + +- `make up`: Inicia todos os serviços em segundo plano +- `make down`: Para e remove todos os contêineres +- `make build`: Constrói imagens Docker +- `make shell`: Acessa o shell do contêiner PHP +- `make test`: Executa testes +- `make coverage`: Executa cobertura de testes com formatação visual +- `make cs-fix`: Executa PHP CS Fixer para corrigir o estilo do código +- `make quality`: Executa todos os comandos de qualidade (cs-check, test, security-check) + +Para uma lista completa de comandos disponíveis, execute: + +```bash +make help +``` + +## Licença + +Este projeto está licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes. + +## Suporte e Comunidade + +- **Documentação**: [https://kariricode.org/docs/sanitizer](https://kariricode.org/docs/sanitizer) +- **Rastreador de Problemas**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-exception/issues) +- **Comunidade**: [Comunidade KaririCode Club](https://kariricode.club) + +--- + +Construído com ❤️ pela equipe KaririCode. Capacitando desenvolvedores para criar aplicações PHP mais seguras e robustas. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..5a4595e --- /dev/null +++ b/composer.json @@ -0,0 +1,46 @@ +{ + "name": "kariricode/exception", + "description": "KaririCode Exception provides a robust and modular exception handling system for the KaririCode Framework, enabling seamless error management across various application domains.", + "keywords": [ + "kariri-code", + "framework", + "exception-handling", + "error-management", + "php-framework", + "modular-exceptions", + "php-exceptions" + ], + "homepage": "https://kariricode.org", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Walmir Silva", + "email": "community@kariricode.org" + } + ], + "require": { + "php": "^8.3" + }, + "autoload": { + "psr-4": { + "KaririCode\\Exception\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "KaririCode\\Exception\\Tests\\": "tests/" + } + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.51", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^11.0", + "squizlabs/php_codesniffer": "^3.9", + "enlightn/security-checker": "^2.0" + }, + "support": { + "issues": "https://github.com/KaririCode-Framework/kariricode-exception/issues", + "source": "https://github.com/KaririCode-Framework/kariricode-exception" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..b09d292 --- /dev/null +++ b/composer.lock @@ -0,0 +1,4921 @@ +{ + "_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": "2067995ac608af769ccf68461bd91e53", + "packages": [], + "packages-dev": [ + { + "name": "clue/ndjson-react", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.11.10", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.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": "2024-08-27T18:44:43+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/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": "enlightn/security-checker", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/enlightn/security-checker.git", + "reference": "d495ab07639388c7c770c5223aa0d42fee1d2604" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/enlightn/security-checker/zipball/d495ab07639388c7c770c5223aa0d42fee1d2604", + "reference": "d495ab07639388c7c770c5223aa0d42fee1d2604", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^6.3|^7.0", + "php": ">=8.2", + "symfony/console": "^7", + "symfony/finder": "^3|^4|^5|^6|^7", + "symfony/process": "^3.4|^4|^5|^6|^7", + "symfony/yaml": "^3.4|^4|^5|^6|^7" + }, + "require-dev": { + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^2.18|^3.0", + "phpunit/phpunit": "^5.5|^6|^7|^8|^9" + }, + "bin": [ + "security-checker" + ], + "type": "library", + "autoload": { + "psr-4": { + "Enlightn\\SecurityChecker\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paras Malhotra", + "email": "paras@laravel-enlightn.com" + }, + { + "name": "Miguel Piedrafita", + "email": "soy@miguelpiedrafita.com" + } + ], + "description": "A PHP dependency vulnerabilities scanner based on the Security Advisories Database.", + "keywords": [ + "package", + "php", + "scanner", + "security", + "security advisories", + "vulnerability scanner" + ], + "support": { + "issues": "https://github.com/enlightn/security-checker/issues", + "source": "https://github.com/enlightn/security-checker/tree/v2.0.0" + }, + "time": "2023-12-10T07:17:09+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+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": "friendsofphp/php-cs-fixer", + "version": "v3.64.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "58dd9c931c785a79739310aef5178928305ffa67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/58dd9c931c785a79739310aef5178928305ffa67", + "reference": "58dd9c931c785a79739310aef5178928305ffa67", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.0", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.0", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.5", + "react/event-loop": "^1.0", + "react/promise": "^2.0 || ^3.0", + "react/socket": "^1.0", + "react/stream": "^1.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3 || ^2.3", + "infection/infection": "^0.29.5", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", + "phpunit/phpunit": "^9.6.19 || ^10.5.21 || ^11.2", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "exclude-from-classmap": [ + "src/Fixer/Internal/*" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.64.0" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2024-08-30T23:09:38+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2024-07-24T11:22:20+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2024-07-18T10:29:17+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2024-07-18T11:15:46+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-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/v5.3.1" + }, + "time": "2024-10-08T18:51:32+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": "phpstan/phpstan", + "version": "1.12.6", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "dc4d2f145a88ea7141ae698effd64d9df46527ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc4d2f145a88ea7141ae698effd64d9df46527ae", + "reference": "dc4d2f145a88ea7141ae698effd64d9df46527ae", + "shasum": "" + }, + "require": { + "php": "^7.2|^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": "2024-10-06T15:03:59+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.4.1" + }, + "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": "11.0.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/11.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T06:21:38+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.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", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7875627f15f4da7e7f0823d1f323f7295a77334e", + "reference": "7875627f15f4da7e7f0823d1f323f7295a77334e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.6", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.1.0", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.1" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.4-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/11.4.1" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-10-08T15:38:37+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "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/" + } + }, + "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/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "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/3.0.2" + }, + "time": "2024-09-11T13:17:53+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/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.5", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/socket": "^1.8", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.5" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-16T13:41:56+00:00" + }, + { + "name": "react/dns", + "version": "v1.13.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.13.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-13T14:18:03+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+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": "react/socket", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.16.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-07-26T10:38:09+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "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": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.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", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.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", + "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", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:44:28+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa37b9e2ca618cb051d71b60120952ee8ca8b03d", + "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-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", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-09-11T15:42:56+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-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": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:54:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-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", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:56:19+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.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": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.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", + "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", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.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": "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", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-09-17T13:12:04+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.10.3", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", + "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", + "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" + } + ], + "time": "2024-09-18T10:38:58+00:00" + }, + { + "name": "symfony/console", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "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/v7.1.5" + }, + "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-20T08:28:38+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.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-04-18T09:32:20+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "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/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.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-04-18T09:32:20+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/61fe0566189bf32e8cfee78335d8776f64a66f5a", + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.1.5" + }, + "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-17T09:16:35+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.1.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "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/v7.1.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-08-13T14:28:19+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "5c03ee6369281177f07f7c68252a280beccba847" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847", + "reference": "5c03ee6369281177f07f7c68252a280beccba847", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.1.5" + }, + "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-19T21:48:23+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.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-04-18T09:32:20+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v7.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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 a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/string", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.1.5" + }, + "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-20T08:28:38+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "4e561c316e135e053bd758bf3b3eb291d9919de4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4e561c316e135e053bd758bf3b3eb291d9919de4", + "reference": "4e561c316e135e053bd758bf3b3eb291d9919de4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "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/v7.1.5" + }, + "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-17T12:49:58+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" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.3" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7dc18f1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + php: + container_name: kariricode-exception + build: + context: . + dockerfile: .docker/php/Dockerfile + args: + PHP_VERSION: ${KARIRI_PHP_VERSION} + environment: + XDEBUG_MODE: coverage + volumes: + - .:/app + working_dir: /app + ports: + - "${KARIRI_PHP_PORT}:9003" diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..07143a4 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + src/ + tests/ + + + vendor/* + config/* + tests/bootstrap.php + tests/object-manager.php + + diff --git a/phpinsights.php b/phpinsights.php new file mode 100644 index 0000000..5df088e --- /dev/null +++ b/phpinsights.php @@ -0,0 +1,60 @@ + 'symfony', + 'exclude' => [ + 'src/Migrations', + 'src/Kernel.php', + ], + 'add' => [], + 'remove' => [ + \PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff::class, + \NunoMaduro\PhpInsights\Domain\Sniffs\ForbiddenSetterSniff::class, + \SlevomatCodingStandard\Sniffs\Commenting\UselessFunctionDocCommentSniff::class, + \SlevomatCodingStandard\Sniffs\Commenting\DocCommentSpacingSniff::class, + \SlevomatCodingStandard\Sniffs\Classes\SuperfluousInterfaceNamingSniff::class, + \SlevomatCodingStandard\Sniffs\Classes\SuperfluousExceptionNamingSniff::class, + \SlevomatCodingStandard\Sniffs\ControlStructures\DisallowYodaComparisonSniff::class, + \NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits::class, + \NunoMaduro\PhpInsights\Domain\Insights\ForbiddenNormalClasses::class, + \SlevomatCodingStandard\Sniffs\Classes\SuperfluousTraitNamingSniff::class, + \SlevomatCodingStandard\Sniffs\Classes\ForbiddenPublicPropertySniff::class, + \NunoMaduro\PhpInsights\Domain\Insights\CyclomaticComplexityIsHigh::class, + \NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineFunctions::class, + \NunoMaduro\PhpInsights\Domain\Insights\ForbiddenFinalClasses::class, + \NunoMaduro\PhpInsights\Domain\Insights\ForbiddenGlobals::class, + \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FunctionCommentSniff::class, + \SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSniff::class, + \SlevomatCodingStandard\Sniffs\Commenting\InlineDocCommentDeclarationSniff::class, + \SlevomatCodingStandard\Sniffs\Classes\ModernClassNameReferenceSniff::class, + \PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\UselessOverridingMethodSniff::class, + \SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff::class, + \SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSniff::class, + \SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff::class, + \SlevomatCodingStandard\Sniffs\Arrays\TrailingArrayCommaSniff::class + ], + 'config' => [ + \PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff::class => [ + 'lineLimit' => 120, + 'absoluteLineLimit' => 160, + ], + \SlevomatCodingStandard\Sniffs\Commenting\InlineDocCommentDeclarationSniff::class => [ + 'exclude' => [ + 'src/Exception/BaseException.php', + ], + ], + \SlevomatCodingStandard\Sniffs\ControlStructures\AssignmentInConditionSniff::class => [ + 'enabled' => false, + ], + ], + 'requirements' => [ + 'min-quality' => 80, + 'min-complexity' => 50, + 'min-architecture' => 75, + 'min-style' => 95, + 'disable-security-check' => false, + ], + 'threads' => null +]; diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..c3392e9 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,7 @@ +parameters: + level: max + paths: + - src + - tests + ignoreErrors: + - '#Method .* has parameter \$.* with no value type specified in iterable type array.#' diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..ba8e7af --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + tests + + + + + + src + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..f0c90a3 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/application.php b/tests/application.php new file mode 100644 index 0000000..a075e1e --- /dev/null +++ b/tests/application.php @@ -0,0 +1,5 @@ + Date: Wed, 16 Oct 2024 13:49:19 -0300 Subject: [PATCH 2/7] chore: add initial project structure with files and strict typing declarations --- createDirectory.php | 67 +++++++++++++++++++ src/AbstractErrorMessage.php | 3 + src/AbstractException.php | 3 + src/Auth/AuthenticationException.php | 3 + src/Auth/AuthorizationException.php | 3 + src/Cache/CacheException.php | 3 + src/CommonErrorMessages.php | 3 + src/Config/ConfigurationException.php | 3 + src/Container/ContainerException.php | 3 + src/Contract/ErrorMessage.php | 3 + src/Contract/Throwable.php | 3 + src/Database/DatabaseException.php | 3 + src/Event/EventException.php | 3 + .../ExternalServiceException.php | 3 + src/File/FileException.php | 3 + src/Input/InputException.php | 3 + src/Localization/LocalizationException.php | 3 + src/Middleware/MiddlewareException.php | 3 + src/Network/HttpException.php | 3 + src/Network/NetworkException.php | 3 + src/Queue/QueueException.php | 3 + src/Routing/RoutingException.php | 3 + src/Runtime/RuntimeException.php | 3 + src/Security/EncryptionException.php | 3 + src/Security/SecurityException.php | 3 + src/Session/SessionException.php | 3 + src/System/SystemException.php | 3 + src/Template/TemplateException.php | 3 + src/Validation/RuleViolationException.php | 3 + src/Validation/ValidationException.php | 3 + 30 files changed, 154 insertions(+) create mode 100644 createDirectory.php create mode 100644 src/AbstractErrorMessage.php create mode 100644 src/AbstractException.php create mode 100644 src/Auth/AuthenticationException.php create mode 100644 src/Auth/AuthorizationException.php create mode 100644 src/Cache/CacheException.php create mode 100644 src/CommonErrorMessages.php create mode 100644 src/Config/ConfigurationException.php create mode 100644 src/Container/ContainerException.php create mode 100644 src/Contract/ErrorMessage.php create mode 100644 src/Contract/Throwable.php create mode 100644 src/Database/DatabaseException.php create mode 100644 src/Event/EventException.php create mode 100644 src/ExternalService/ExternalServiceException.php create mode 100644 src/File/FileException.php create mode 100644 src/Input/InputException.php create mode 100644 src/Localization/LocalizationException.php create mode 100644 src/Middleware/MiddlewareException.php create mode 100644 src/Network/HttpException.php create mode 100644 src/Network/NetworkException.php create mode 100644 src/Queue/QueueException.php create mode 100644 src/Routing/RoutingException.php create mode 100644 src/Runtime/RuntimeException.php create mode 100644 src/Security/EncryptionException.php create mode 100644 src/Security/SecurityException.php create mode 100644 src/Session/SessionException.php create mode 100644 src/System/SystemException.php create mode 100644 src/Template/TemplateException.php create mode 100644 src/Validation/RuleViolationException.php create mode 100644 src/Validation/ValidationException.php diff --git a/createDirectory.php b/createDirectory.php new file mode 100644 index 0000000..1081481 --- /dev/null +++ b/createDirectory.php @@ -0,0 +1,67 @@ + Date: Wed, 16 Oct 2024 14:03:40 -0300 Subject: [PATCH 3/7] feat(exceptions): add new exception classes for various modules - Created `AbstractException` as the base exception class - Added `AuthenticationException` and `AuthorizationException` under `Auth` - Added `CacheException` under `Cache` - Added `ConfigurationException` under `Config` - Added `ContainerException` under `Container` - Added `DatabaseException` under `Database` - Added `EventException` under `Event` - Added `ExternalServiceException` under `ExternalService` - Added `FileException` under `File` - Added `InputException` under `Input` - Added `LocalizationException` under `Localization` - Added `MiddlewareException` under `Middleware` - Added `NetworkException` and `HttpException` under `Network` - Added `QueueException` under `Queue` - Added `RoutingException` under `Routing` - Added `RuntimeException` under `Runtime` - Added `SecurityException` and `EncryptionException` under `Security` - Added `SessionException` under `Session` - Added `SystemException` under `System` - Added `TemplateException` under `Template` - Added `ValidationException` and `RuleViolationException` under `Validation` --- src/AbstractErrorMessage.php | 3 -- src/AbstractException.php | 28 +++++++++++++++++++ src/Auth/AuthenticationException.php | 23 +++++++++++++++ src/Auth/AuthorizationException.php | 18 ++++++++++++ src/Cache/CacheException.php | 23 +++++++++++++++ src/CommonErrorMessages.php | 3 -- src/Config/ConfigurationException.php | 23 +++++++++++++++ src/Container/ContainerException.php | 18 ++++++++++++ src/Contract/ErrorMessage.php | 9 ++++++ src/Contract/Throwable.php | 9 ++++++ src/Database/DatabaseException.php | 23 +++++++++++++++ src/Event/EventException.php | 18 ++++++++++++ src/ExceptionMessage.php | 26 +++++++++++++++++ .../ExternalServiceException.php | 23 +++++++++++++++ src/File/FileException.php | 28 +++++++++++++++++++ src/Input/InputException.php | 23 +++++++++++++++ src/Localization/LocalizationException.php | 18 ++++++++++++ src/Middleware/MiddlewareException.php | 18 ++++++++++++ src/Network/HttpException.php | 18 ++++++++++++ src/Network/NetworkException.php | 18 ++++++++++++ src/Queue/QueueException.php | 23 +++++++++++++++ src/Routing/RoutingException.php | 18 ++++++++++++ src/Runtime/RuntimeException.php | 23 +++++++++++++++ src/Security/EncryptionException.php | 18 ++++++++++++ src/Security/SecurityException.php | 23 +++++++++++++++ src/Session/SessionException.php | 18 ++++++++++++ src/System/SystemException.php | 23 +++++++++++++++ src/Template/TemplateException.php | 18 ++++++++++++ src/Validation/RuleViolationException.php | 13 +++++++++ src/Validation/ValidationException.php | 28 +++++++++++++++++++ 30 files changed, 569 insertions(+), 6 deletions(-) delete mode 100644 src/AbstractErrorMessage.php delete mode 100644 src/CommonErrorMessages.php create mode 100644 src/ExceptionMessage.php diff --git a/src/AbstractErrorMessage.php b/src/AbstractErrorMessage.php deleted file mode 100644 index 174d7fd..0000000 --- a/src/AbstractErrorMessage.php +++ /dev/null @@ -1,3 +0,0 @@ -getMessage(), 0, $previous); + $this->context = $context; + } + + public function getContext(): array + { + return $this->context; + } + + protected function addContext(string $key, mixed $value): self + { + $this->context[$key] = $value; + + return $this; + } +} diff --git a/src/Auth/AuthenticationException.php b/src/Auth/AuthenticationException.php index 174d7fd..8caa183 100644 --- a/src/Auth/AuthenticationException.php +++ b/src/Auth/AuthenticationException.php @@ -1,3 +1,26 @@ code; + } + + public function getMessage(): string + { + return $this->message; + } +} diff --git a/src/ExternalService/ExternalServiceException.php b/src/ExternalService/ExternalServiceException.php index 174d7fd..68cbbd9 100644 --- a/src/ExternalService/ExternalServiceException.php +++ b/src/ExternalService/ExternalServiceException.php @@ -1,3 +1,26 @@ validationErrors[$field][] = $errorMessage; + + return $this; + } + + public function getValidationErrors(): array + { + return $this->validationErrors; + } +} From 2483827f70ded185861aa44070b10feb3d5828f5 Mon Sep 17 00:00:00 2001 From: Walmir Silva Date: Wed, 16 Oct 2024 14:07:45 -0300 Subject: [PATCH 4/7] feat(tests): create initial PHPUnit test files for all exception classes - Added PHPUnit test classes for each exception class under `tests` directory - Created directory structure mirroring the source code for proper organization of tests --- createDirectory.php | 65 ++++++++++--------- tests/AbstractErrorMessageTest.php | 3 + tests/AbstractExceptionTest.php | 3 + tests/Auth/AuthenticationExceptionTest.php | 3 + tests/Auth/AuthorizationExceptionTest.php | 3 + tests/Cache/CacheExceptionTest.php | 3 + tests/CommonErrorMessagesTest.php | 3 + tests/Config/ConfigurationExceptionTest.php | 3 + tests/Container/ContainerExceptionTest.php | 3 + tests/Contract/ErrorMessageTest.php | 3 + tests/Contract/ThrowableTest.php | 3 + tests/Database/DatabaseExceptionTest.php | 3 + tests/Event/EventExceptionTest.php | 3 + .../ExternalServiceExceptionTest.php | 3 + tests/File/FileExceptionTest.php | 3 + tests/Input/InputExceptionTest.php | 3 + .../LocalizationExceptionTest.php | 3 + tests/Middleware/MiddlewareExceptionTest.php | 3 + tests/Network/HttpExceptionTest.php | 3 + tests/Network/NetworkExceptionTest.php | 3 + tests/Queue/QueueExceptionTest.php | 3 + tests/Routing/RoutingExceptionTest.php | 3 + tests/Runtime/RuntimeExceptionTest.php | 3 + tests/Security/EncryptionExceptionTest.php | 3 + tests/Security/SecurityExceptionTest.php | 3 + tests/Session/SessionExceptionTest.php | 3 + tests/System/SystemExceptionTest.php | 3 + tests/Template/TemplateExceptionTest.php | 3 + .../Validation/RuleViolationExceptionTest.php | 3 + tests/Validation/ValidationExceptionTest.php | 3 + 30 files changed, 120 insertions(+), 32 deletions(-) create mode 100644 tests/AbstractErrorMessageTest.php create mode 100644 tests/AbstractExceptionTest.php create mode 100644 tests/Auth/AuthenticationExceptionTest.php create mode 100644 tests/Auth/AuthorizationExceptionTest.php create mode 100644 tests/Cache/CacheExceptionTest.php create mode 100644 tests/CommonErrorMessagesTest.php create mode 100644 tests/Config/ConfigurationExceptionTest.php create mode 100644 tests/Container/ContainerExceptionTest.php create mode 100644 tests/Contract/ErrorMessageTest.php create mode 100644 tests/Contract/ThrowableTest.php create mode 100644 tests/Database/DatabaseExceptionTest.php create mode 100644 tests/Event/EventExceptionTest.php create mode 100644 tests/ExternalService/ExternalServiceExceptionTest.php create mode 100644 tests/File/FileExceptionTest.php create mode 100644 tests/Input/InputExceptionTest.php create mode 100644 tests/Localization/LocalizationExceptionTest.php create mode 100644 tests/Middleware/MiddlewareExceptionTest.php create mode 100644 tests/Network/HttpExceptionTest.php create mode 100644 tests/Network/NetworkExceptionTest.php create mode 100644 tests/Queue/QueueExceptionTest.php create mode 100644 tests/Routing/RoutingExceptionTest.php create mode 100644 tests/Runtime/RuntimeExceptionTest.php create mode 100644 tests/Security/EncryptionExceptionTest.php create mode 100644 tests/Security/SecurityExceptionTest.php create mode 100644 tests/Session/SessionExceptionTest.php create mode 100644 tests/System/SystemExceptionTest.php create mode 100644 tests/Template/TemplateExceptionTest.php create mode 100644 tests/Validation/RuleViolationExceptionTest.php create mode 100644 tests/Validation/ValidationExceptionTest.php diff --git a/createDirectory.php b/createDirectory.php index 1081481..8247e17 100644 --- a/createDirectory.php +++ b/createDirectory.php @@ -12,47 +12,48 @@ function createDirectory(string $path): void function createFile(string $filePath): void { $content = " Date: Wed, 16 Oct 2024 14:56:29 -0300 Subject: [PATCH 5/7] feat: add all test files --- src/AbstractException.php | 4 +- src/Contract/ErrorMessage.php | 4 +- src/ExceptionMessage.php | 10 ++- tests/AbstractErrorMessageTest.php | 3 - tests/AbstractExceptionTest.php | 66 +++++++++++++++++++ tests/Auth/AuthenticationExceptionTest.php | 26 ++++++++ tests/Auth/AuthorizationExceptionTest.php | 22 +++++++ tests/Cache/CacheExceptionTest.php | 29 ++++++++ tests/CommonErrorMessagesTest.php | 3 - tests/Config/ConfigurationExceptionTest.php | 30 +++++++++ tests/Container/ContainerExceptionTest.php | 23 +++++++ tests/Contract/ErrorMessageTest.php | 3 - tests/Contract/ThrowableTest.php | 3 - tests/Database/DatabaseExceptionTest.php | 29 ++++++++ tests/Event/EventExceptionTest.php | 22 +++++++ tests/ExceptionMessageTest.php | 30 +++++++++ .../ExternalServiceExceptionTest.php | 30 +++++++++ tests/File/FileExceptionTest.php | 36 ++++++++++ tests/Input/InputExceptionTest.php | 30 +++++++++ .../LocalizationExceptionTest.php | 23 +++++++ tests/Middleware/MiddlewareExceptionTest.php | 22 +++++++ tests/Network/HttpExceptionTest.php | 22 +++++++ tests/Network/NetworkExceptionTest.php | 22 +++++++ tests/Queue/QueueExceptionTest.php | 29 ++++++++ tests/Routing/RoutingExceptionTest.php | 23 +++++++ tests/Runtime/RuntimeExceptionTest.php | 28 ++++++++ tests/Security/EncryptionExceptionTest.php | 20 ++++++ tests/Security/SecurityExceptionTest.php | 26 ++++++++ tests/Session/SessionExceptionTest.php | 20 ++++++ tests/System/SystemExceptionTest.php | 29 ++++++++ tests/Template/TemplateExceptionTest.php | 22 +++++++ .../Validation/RuleViolationExceptionTest.php | 16 +++++ tests/Validation/ValidationExceptionTest.php | 27 ++++++++ 33 files changed, 716 insertions(+), 16 deletions(-) delete mode 100644 tests/AbstractErrorMessageTest.php delete mode 100644 tests/CommonErrorMessagesTest.php delete mode 100644 tests/Contract/ErrorMessageTest.php delete mode 100644 tests/Contract/ThrowableTest.php create mode 100644 tests/ExceptionMessageTest.php diff --git a/src/AbstractException.php b/src/AbstractException.php index ca79dbb..945e93f 100644 --- a/src/AbstractException.php +++ b/src/AbstractException.php @@ -13,8 +13,10 @@ abstract class AbstractException extends \Exception implements Throwable public function __construct(ErrorMessage $errorMessage, ?\Throwable $previous = null, array $context = []) { + + $this->context = array_merge(['code' => $errorMessage->getCode()], $context); + parent::__construct($errorMessage->getMessage(), 0, $previous); - $this->context = $context; } public function getContext(): array diff --git a/src/Contract/ErrorMessage.php b/src/Contract/ErrorMessage.php index 7d93310..b4fec89 100644 --- a/src/Contract/ErrorMessage.php +++ b/src/Contract/ErrorMessage.php @@ -6,7 +6,9 @@ interface ErrorMessage { - public function getCode(): string; + public function getCode(): int; + + public function getErrorCode(): string; public function getMessage(): string; } diff --git a/src/ExceptionMessage.php b/src/ExceptionMessage.php index 48fa837..b95601d 100644 --- a/src/ExceptionMessage.php +++ b/src/ExceptionMessage.php @@ -9,16 +9,22 @@ final class ExceptionMessage implements ErrorMessage { public function __construct( - private readonly string $code, + private readonly int $code, + private readonly string $errorCode, private readonly string $message ) { } - public function getCode(): string + public function getCode(): int { return $this->code; } + public function getErrorCode(): string + { + return $this->errorCode; + } + public function getMessage(): string { return $this->message; diff --git a/tests/AbstractErrorMessageTest.php b/tests/AbstractErrorMessageTest.php deleted file mode 100644 index 174d7fd..0000000 --- a/tests/AbstractErrorMessageTest.php +++ /dev/null @@ -1,3 +0,0 @@ -exception = new ConcreteTestException($errorMessage); + } + + public function testExceptionCreation(): void + { + $this->assertSame('Test message', $this->exception->getMessage()); + $this->assertSame(['code' => 'TEST_CODE'], $this->exception->getContext()); + } + + public function testExceptionWithContext(): void + { + $errorMessage = new ExceptionMessage('TEST_CODE', 'Test message'); + $context = ['key' => 'value']; + $exception = new ConcreteTestException($errorMessage, null, $context); + + $this->assertSame(['code' => 'TEST_CODE', 'key' => 'value'], $exception->getContext()); + } + + public function testAddContext(): void + { + $this->exception->addTestContext('newKey', 'newValue'); + + $expectedContext = ['code' => 'TEST_CODE', 'newKey' => 'newValue']; + $this->assertSame($expectedContext, $this->exception->getContext()); + } + + public function testExceptionWithPrevious(): void + { + $previousException = new \Exception('Previous exception'); + $errorMessage = new ExceptionMessage('TEST_CODE', 'Test message'); + $exception = new ConcreteTestException($errorMessage, $previousException); + + $this->assertSame($previousException, $exception->getPrevious()); + } + + protected function assertExceptionStructure(AbstractException $exception, string $expectedCode, string $expectedMessage): void + { + $this->assertInstanceOf(AbstractException::class, $exception); + $this->assertSame($expectedMessage, $exception->getMessage()); + $this->assertArrayHasKey('code', $exception->getContext()); + $this->assertSame($expectedCode, $exception->getContext()['code']); + } +} + +// Concrete implementation of AbstractException for testing +final class ConcreteTestException extends AbstractException +{ + public function addTestContext(string $key, mixed $value): self + { + return $this->addContext($key, $value); + } +} diff --git a/tests/Auth/AuthenticationExceptionTest.php b/tests/Auth/AuthenticationExceptionTest.php index 174d7fd..43f85ba 100644 --- a/tests/Auth/AuthenticationExceptionTest.php +++ b/tests/Auth/AuthenticationExceptionTest.php @@ -1,3 +1,29 @@ assertExceptionStructure($exception, 'INVALID_CREDENTIALS', 'Invalid credentials provided'); + } + + public function testAccountLocked(): void + { + $exception = AuthenticationException::accountLocked(); + $this->assertExceptionStructure($exception, 'ACCOUNT_LOCKED', 'Account is locked'); + } + + public function testTwoFactorRequired(): void + { + $exception = AuthenticationException::twoFactorRequired(); + $this->assertExceptionStructure($exception, 'TWO_FACTOR_REQUIRED', 'Two-factor authentication is required'); + } +} diff --git a/tests/Auth/AuthorizationExceptionTest.php b/tests/Auth/AuthorizationExceptionTest.php index 174d7fd..98c00b7 100644 --- a/tests/Auth/AuthorizationExceptionTest.php +++ b/tests/Auth/AuthorizationExceptionTest.php @@ -1,3 +1,25 @@ assertExceptionStructure($exception, 'INSUFFICIENT_PERMISSIONS', "Insufficient permissions for action: {$action}"); + } + + public function testRoleRequired(): void + { + $role = 'admin'; + $exception = AuthorizationException::roleRequired($role); + $this->assertExceptionStructure($exception, 'ROLE_REQUIRED', "Required role not present: {$role}"); + } +} diff --git a/tests/Cache/CacheExceptionTest.php b/tests/Cache/CacheExceptionTest.php index 174d7fd..1781b8b 100644 --- a/tests/Cache/CacheExceptionTest.php +++ b/tests/Cache/CacheExceptionTest.php @@ -1,3 +1,32 @@ assertExceptionStructure($exception, 'CACHE_ITEM_NOT_FOUND', "Cache item not found: {$key}"); + } + + public function testStorageError(): void + { + $details = 'Redis connection failed'; + $exception = CacheException::storageError($details); + $this->assertExceptionStructure($exception, 'CACHE_STORAGE_ERROR', "Cache storage error: {$details}"); + } + + public function testInvalidTtl(): void + { + $ttl = -1; + $exception = CacheException::invalidTtl($ttl); + $this->assertExceptionStructure($exception, 'INVALID_TTL', "Invalid TTL value: {$ttl}"); + } +} diff --git a/tests/CommonErrorMessagesTest.php b/tests/CommonErrorMessagesTest.php deleted file mode 100644 index 174d7fd..0000000 --- a/tests/CommonErrorMessagesTest.php +++ /dev/null @@ -1,3 +0,0 @@ -assertExceptionStructure($exception, 'MISSING_CONFIG_KEY', "Missing configuration key: {$key}"); + } + + public function testInvalidValue(): void + { + $key = 'app.debug'; + $value = 'not_a_boolean'; + $exception = ConfigurationException::invalidValue($key, $value); + $this->assertExceptionStructure($exception, 'INVALID_CONFIG_VALUE', "Invalid configuration value for key '{$key}': " . var_export($value, true)); + } + + public function testEnvironmentNotSet(): void + { + $envVar = 'APP_KEY'; + $exception = ConfigurationException::environmentNotSet($envVar); + $this->assertExceptionStructure($exception, 'ENVIRONMENT_NOT_SET', "Environment variable not set: {$envVar}"); + } +} diff --git a/tests/Container/ContainerExceptionTest.php b/tests/Container/ContainerExceptionTest.php index 174d7fd..5569fe9 100644 --- a/tests/Container/ContainerExceptionTest.php +++ b/tests/Container/ContainerExceptionTest.php @@ -1,3 +1,26 @@ assertExceptionStructure($exception, 'SERVICE_NOT_FOUND', "Service not found in container: {$serviceId}"); + } + + public function testCircularDependency(): void + { + $serviceId = 'App\Service\UserService'; + $exception = ContainerException::circularDependency($serviceId); + $this->assertExceptionStructure($exception, 'CIRCULAR_DEPENDENCY', "Circular dependency detected for service: {$serviceId}"); + } +} diff --git a/tests/Contract/ErrorMessageTest.php b/tests/Contract/ErrorMessageTest.php deleted file mode 100644 index 174d7fd..0000000 --- a/tests/Contract/ErrorMessageTest.php +++ /dev/null @@ -1,3 +0,0 @@ -assertExceptionStructure($exception, 'DB_CONNECTION_ERROR', "Database connection error: {$details}"); + } + + public function testQueryError(): void + { + $query = 'SELECT * FROM users'; + $error = 'Table "users" not found'; + $exception = DatabaseException::queryError($query, $error); + $this->assertExceptionStructure($exception, 'DB_QUERY_ERROR', "Database query error: {$error}"); + } + + public function testDeadlockDetected(): void + { + $exception = DatabaseException::deadlockDetected(); + $this->assertExceptionStructure($exception, 'DB_DEADLOCK', 'Database deadlock detected'); + } +} diff --git a/tests/Event/EventExceptionTest.php b/tests/Event/EventExceptionTest.php index 174d7fd..8e98d04 100644 --- a/tests/Event/EventExceptionTest.php +++ b/tests/Event/EventExceptionTest.php @@ -1,3 +1,25 @@ assertExceptionStructure($exception, 'LISTENER_NOT_CALLABLE', "Event listener is not callable for event: {$eventName}"); + } + + public function testEventDispatchFailed(): void + { + $eventName = 'email.sent'; + $exception = EventException::eventDispatchFailed($eventName); + $this->assertExceptionStructure($exception, 'EVENT_DISPATCH_FAILED', "Failed to dispatch event: {$eventName}"); + } +} diff --git a/tests/ExceptionMessageTest.php b/tests/ExceptionMessageTest.php new file mode 100644 index 0000000..62814ca --- /dev/null +++ b/tests/ExceptionMessageTest.php @@ -0,0 +1,30 @@ +assertSame($code, $exceptionMessage->getCode()); + $this->assertSame($message, $exceptionMessage->getMessage()); + } + + public function testExceptionMessageImmutability(): void + { + $exceptionMessage = new ExceptionMessage('CODE', 'Message'); + + $this->expectException(\Error::class); + $reflectionProperty = new \ReflectionProperty($exceptionMessage, 'code'); + $reflectionProperty->setValue($exceptionMessage, 'NEW_CODE'); + } +} diff --git a/tests/ExternalService/ExternalServiceExceptionTest.php b/tests/ExternalService/ExternalServiceExceptionTest.php index 174d7fd..af13c8c 100644 --- a/tests/ExternalService/ExternalServiceExceptionTest.php +++ b/tests/ExternalService/ExternalServiceExceptionTest.php @@ -1,3 +1,33 @@ assertExceptionStructure($exception, 'API_ERROR', "Error from external service '{$service}': {$error}"); + } + + public function testServiceUnavailable(): void + { + $service = 'EmailService'; + $exception = ExternalServiceException::serviceUnavailable($service); + $this->assertExceptionStructure($exception, 'SERVICE_UNAVAILABLE', "External service unavailable: {$service}"); + } + + public function testInvalidResponse(): void + { + $service = 'WeatherAPI'; + $exception = ExternalServiceException::invalidResponse($service); + $this->assertExceptionStructure($exception, 'INVALID_RESPONSE', "Invalid response from external service: {$service}"); + } +} diff --git a/tests/File/FileExceptionTest.php b/tests/File/FileExceptionTest.php index 174d7fd..92f45ad 100644 --- a/tests/File/FileExceptionTest.php +++ b/tests/File/FileExceptionTest.php @@ -1,3 +1,39 @@ assertExceptionStructure($exception, 'FILE_NOT_FOUND', "File not found: {$path}"); + } + + public function testPermissionDenied(): void + { + $path = '/path/to/file.txt'; + $exception = FileException::permissionDenied($path); + $this->assertExceptionStructure($exception, 'PERMISSION_DENIED', "Permission denied for file: {$path}"); + } + + public function testUnreadable(): void + { + $path = '/path/to/file.txt'; + $exception = FileException::unreadable($path); + $this->assertExceptionStructure($exception, 'FILE_UNREADABLE', "File is not readable: {$path}"); + } + + public function testUploadFailed(): void + { + $filename = 'upload.txt'; + $exception = FileException::uploadFailed($filename); + $this->assertExceptionStructure($exception, 'UPLOAD_FAILED', "Failed to upload file: {$filename}"); + } +} diff --git a/tests/Input/InputExceptionTest.php b/tests/Input/InputExceptionTest.php index 174d7fd..a9d156b 100644 --- a/tests/Input/InputExceptionTest.php +++ b/tests/Input/InputExceptionTest.php @@ -1,3 +1,33 @@ assertExceptionStructure($exception, 'INVALID_FORMAT', "Invalid format for field: {$field}"); + } + + public function testMissingRequired(): void + { + $field = 'username'; + $exception = InputException::missingRequired($field); + $this->assertExceptionStructure($exception, 'MISSING_REQUIRED', "Missing required field: {$field}"); + } + + public function testExceedsMaxLength(): void + { + $field = 'description'; + $maxLength = 255; + $exception = InputException::exceedsMaxLength($field, $maxLength); + $this->assertExceptionStructure($exception, 'EXCEEDS_MAX_LENGTH', "Field '{$field}' exceeds maximum length of {$maxLength}"); + } +} diff --git a/tests/Localization/LocalizationExceptionTest.php b/tests/Localization/LocalizationExceptionTest.php index 174d7fd..3f80f70 100644 --- a/tests/Localization/LocalizationExceptionTest.php +++ b/tests/Localization/LocalizationExceptionTest.php @@ -1,3 +1,26 @@ assertExceptionStructure($exception, 'MISSING_TRANSLATION', "Missing translation for key '{$key}' in locale '{$locale}'"); + } + + public function testInvalidLocale(): void + { + $locale = 'invalid_locale'; + $exception = LocalizationException::invalidLocale($locale); + $this->assertExceptionStructure($exception, 'INVALID_LOCALE', "Invalid locale: {$locale}"); + } +} diff --git a/tests/Middleware/MiddlewareExceptionTest.php b/tests/Middleware/MiddlewareExceptionTest.php index 174d7fd..67d03f5 100644 --- a/tests/Middleware/MiddlewareExceptionTest.php +++ b/tests/Middleware/MiddlewareExceptionTest.php @@ -1,3 +1,25 @@ assertExceptionStructure($exception, 'INVALID_MIDDLEWARE', "Invalid middleware: {$middlewareName}"); + } + + public function testMiddlewareExecutionFailed(): void + { + $middlewareName = 'RateLimitMiddleware'; + $exception = MiddlewareException::middlewareExecutionFailed($middlewareName); + $this->assertExceptionStructure($exception, 'MIDDLEWARE_EXECUTION_FAILED', "Execution failed for middleware: {$middlewareName}"); + } +} diff --git a/tests/Network/HttpExceptionTest.php b/tests/Network/HttpExceptionTest.php index 174d7fd..19146be 100644 --- a/tests/Network/HttpExceptionTest.php +++ b/tests/Network/HttpExceptionTest.php @@ -1,3 +1,25 @@ assertExceptionStructure($exception, 'HTTP_CLIENT_ERROR', "HTTP client error with status code: {$statusCode}"); + } + + public function testServerError(): void + { + $statusCode = 500; + $exception = HttpException::serverError($statusCode); + $this->assertExceptionStructure($exception, 'HTTP_SERVER_ERROR', "HTTP server error with status code: {$statusCode}"); + } +} diff --git a/tests/Network/NetworkExceptionTest.php b/tests/Network/NetworkExceptionTest.php index 174d7fd..9548805 100644 --- a/tests/Network/NetworkExceptionTest.php +++ b/tests/Network/NetworkExceptionTest.php @@ -1,3 +1,25 @@ assertExceptionStructure($exception, 'CONNECTION_FAILED', "Failed to connect to host: {$host}"); + } + + public function testTimeout(): void + { + $operation = 'HTTP request'; + $exception = NetworkException::timeout($operation); + $this->assertExceptionStructure($exception, 'TIMEOUT', "Network operation timed out: {$operation}"); + } +} diff --git a/tests/Queue/QueueExceptionTest.php b/tests/Queue/QueueExceptionTest.php index 174d7fd..9080088 100644 --- a/tests/Queue/QueueExceptionTest.php +++ b/tests/Queue/QueueExceptionTest.php @@ -1,3 +1,32 @@ assertExceptionStructure($exception, 'JOB_PUSH_FAILED', "Failed to push job to queue: {$jobClass}"); + } + + public function testJobProcessingFailed(): void + { + $jobId = 'job_123456'; + $exception = QueueException::jobProcessingFailed($jobId); + $this->assertExceptionStructure($exception, 'JOB_PROCESSING_FAILED', "Failed to process job: {$jobId}"); + } + + public function testQueueConnectionFailed(): void + { + $connection = 'redis'; + $exception = QueueException::queueConnectionFailed($connection); + $this->assertExceptionStructure($exception, 'QUEUE_CONNECTION_FAILED', "Failed to connect to queue: {$connection}"); + } +} diff --git a/tests/Routing/RoutingExceptionTest.php b/tests/Routing/RoutingExceptionTest.php index 174d7fd..2bc2fb4 100644 --- a/tests/Routing/RoutingExceptionTest.php +++ b/tests/Routing/RoutingExceptionTest.php @@ -1,3 +1,26 @@ assertExceptionStructure($exception, 'ROUTE_NOT_FOUND', "Route not found for URI: {$uri}"); + } + + public function testMethodNotAllowed(): void + { + $method = 'POST'; + $uri = '/get-only-path'; + $exception = RoutingException::methodNotAllowed($method, $uri); + $this->assertExceptionStructure($exception, 'METHOD_NOT_ALLOWED', "Method {$method} not allowed for URI: {$uri}"); + } +} diff --git a/tests/Runtime/RuntimeExceptionTest.php b/tests/Runtime/RuntimeExceptionTest.php index 174d7fd..90e0300 100644 --- a/tests/Runtime/RuntimeExceptionTest.php +++ b/tests/Runtime/RuntimeExceptionTest.php @@ -1,3 +1,31 @@ assertExceptionStructure($exception, 'UNEXPECTED_VALUE', "Unexpected value: {$details}"); + } + + public function testOutOfMemory(): void + { + $exception = RuntimeException::outOfMemory(); + $this->assertExceptionStructure($exception, 'OUT_OF_MEMORY', 'Out of memory error'); + } + + public function testClassNotFound(): void + { + $className = 'App\NonExistentClass'; + $exception = RuntimeException::classNotFound($className); + $this->assertExceptionStructure($exception, 'CLASS_NOT_FOUND', "Class not found: {$className}"); + } +} diff --git a/tests/Security/EncryptionExceptionTest.php b/tests/Security/EncryptionExceptionTest.php index 174d7fd..08358f4 100644 --- a/tests/Security/EncryptionExceptionTest.php +++ b/tests/Security/EncryptionExceptionTest.php @@ -1,3 +1,23 @@ assertExceptionStructure($exception, 'ENCRYPTION_FAILED', 'Encryption operation failed'); + } + + public function testDecryptionFailed(): void + { + $exception = EncryptionException::decryptionFailed(); + $this->assertExceptionStructure($exception, 'DECRYPTION_FAILED', 'Decryption operation failed'); + } +} diff --git a/tests/Security/SecurityExceptionTest.php b/tests/Security/SecurityExceptionTest.php index 174d7fd..9fd025d 100644 --- a/tests/Security/SecurityExceptionTest.php +++ b/tests/Security/SecurityExceptionTest.php @@ -1,3 +1,29 @@ assertExceptionStructure($exception, 'UNAUTHORIZED', 'Unauthorized access'); + } + + public function testCsrfTokenMismatch(): void + { + $exception = SecurityException::csrfTokenMismatch(); + $this->assertExceptionStructure($exception, 'CSRF_TOKEN_MISMATCH', 'CSRF token mismatch'); + } + + public function testRateLimitExceeded(): void + { + $exception = SecurityException::rateLimitExceeded(); + $this->assertExceptionStructure($exception, 'RATE_LIMIT_EXCEEDED', 'Rate limit exceeded'); + } +} diff --git a/tests/Session/SessionExceptionTest.php b/tests/Session/SessionExceptionTest.php index 174d7fd..ea32e3a 100644 --- a/tests/Session/SessionExceptionTest.php +++ b/tests/Session/SessionExceptionTest.php @@ -1,3 +1,23 @@ assertExceptionStructure($exception, 'SESSION_START_FAILED', 'Failed to start session'); + } + + public function testInvalidSessionId(): void + { + $exception = SessionException::invalidSessionId(); + $this->assertExceptionStructure($exception, 'INVALID_SESSION_ID', 'Invalid session ID'); + } +} diff --git a/tests/System/SystemExceptionTest.php b/tests/System/SystemExceptionTest.php index 174d7fd..5be4b35 100644 --- a/tests/System/SystemExceptionTest.php +++ b/tests/System/SystemExceptionTest.php @@ -1,3 +1,32 @@ assertExceptionStructure($exception, 'RESOURCE_UNAVAILABLE', "System resource unavailable: {$resource}"); + } + + public function testEnvironmentError(): void + { + $details = 'Missing .env file'; + $exception = SystemException::environmentError($details); + $this->assertExceptionStructure($exception, 'ENVIRONMENT_ERROR', "Environment error: {$details}"); + } + + public function testExtensionNotLoaded(): void + { + $extension = 'gd'; + $exception = SystemException::extensionNotLoaded($extension); + $this->assertExceptionStructure($exception, 'EXTENSION_NOT_LOADED', "PHP extension not loaded: {$extension}"); + } +} diff --git a/tests/Template/TemplateExceptionTest.php b/tests/Template/TemplateExceptionTest.php index 174d7fd..f4241be 100644 --- a/tests/Template/TemplateExceptionTest.php +++ b/tests/Template/TemplateExceptionTest.php @@ -1,3 +1,25 @@ assertExceptionStructure($exception, 'TEMPLATE_NOT_FOUND', "Template not found: {$templateName}"); + } + + public function testRenderingFailed(): void + { + $templateName = 'email/welcome.html.twig'; + $exception = TemplateException::renderingFailed($templateName); + $this->assertExceptionStructure($exception, 'RENDERING_FAILED', "Failed to render template: {$templateName}"); + } +} diff --git a/tests/Validation/RuleViolationExceptionTest.php b/tests/Validation/RuleViolationExceptionTest.php index 174d7fd..97b3352 100644 --- a/tests/Validation/RuleViolationExceptionTest.php +++ b/tests/Validation/RuleViolationExceptionTest.php @@ -1,3 +1,19 @@ assertExceptionStructure($exception, 'RULE_VIOLATION', "Validation rule '{$rule}' violated for field '{$field}'"); + } +} diff --git a/tests/Validation/ValidationExceptionTest.php b/tests/Validation/ValidationExceptionTest.php index 174d7fd..a63cd58 100644 --- a/tests/Validation/ValidationExceptionTest.php +++ b/tests/Validation/ValidationExceptionTest.php @@ -1,3 +1,30 @@ assertExceptionStructure($exception, 'VALIDATION_FAILED', 'Validation failed'); + } + + public function testAddValidationError(): void + { + $exception = ValidationException::create(); + $errorMessage = new ExceptionMessage('FIELD_ERROR', 'Field has an error'); + $exception->addError('field_name', $errorMessage); + + $errors = $exception->getValidationErrors(); + $this->assertArrayHasKey('field_name', $errors); + $this->assertCount(1, $errors['field_name']); + $this->assertSame($errorMessage, $errors['field_name'][0]); + } +} From 4cd5eed9459c1871da45ef9afbe9e951be9fff7f Mon Sep 17 00:00:00 2001 From: Walmir Silva Date: Wed, 16 Oct 2024 18:01:38 -0300 Subject: [PATCH 6/7] Refactor Exception Classes to Include Error Code Constants - **Added numeric error code constants** to all exception classes in `src/` directory. - Each exception class now defines private constants for error codes. - Factory methods updated to use these constants when creating `ExceptionMessage` instances. - **Modified `ExceptionMessage` class** to accept `int $code` as the first parameter. - Updated constructor signature to `public function __construct(int $code, string $errorCode, string $message)`. - Ensured compatibility across all usages. - **Updated `AbstractException` class**: - Constructor now sets the numeric code from `ExceptionMessage` using `$errorMessage->getCode()`. - Maintains error code string and context. - **Refactored exception tests in `tests/` directory**: - Updated `assertExceptionStructure` method in `AbstractExceptionTest` to include assertion for numeric error code. - All exception test classes now pass the expected numeric code to `assertExceptionStructure`. - Ensured that all tests reflect the changes in the exception classes and pass successfully. - **Consistent Error Code Ranges**: - Established a consistent error code range for each exception type as per the error code range table. - This enhances error categorization and future maintainability. **Summary:** This commit refactors the exception handling mechanism by introducing numeric error code constants across all exception classes and their corresponding tests. This change enhances the clarity and maintainability of the codebase by: - Providing a standardized way to identify exceptions through numeric codes. - Improving error categorization according to the defined error code ranges. - Ensuring consistency between the exception classes and their tests. - Facilitating better integration with logging and error handling systems that utilize numeric error codes. --- script.php | 142 ++++++++++++++++++ src/AbstractException.php | 12 +- src/Auth/AuthenticationException.php | 22 ++- src/Auth/AuthorizationException.php | 15 +- src/Cache/CacheException.php | 22 ++- src/Config/ConfigurationException.php | 22 ++- src/Container/ContainerException.php | 15 +- src/Database/DatabaseException.php | 22 ++- src/Event/EventException.php | 15 +- .../ExternalServiceException.php | 22 ++- src/File/FileException.php | 29 +++- src/Input/InputException.php | 22 ++- src/Localization/LocalizationException.php | 15 +- src/Middleware/MiddlewareException.php | 15 +- src/Network/HttpException.php | 15 +- src/Network/NetworkException.php | 15 +- src/Queue/QueueException.php | 22 ++- src/Routing/RoutingException.php | 15 +- src/Runtime/RuntimeException.php | 22 ++- src/Security/EncryptionException.php | 15 +- src/Security/SecurityException.php | 22 ++- src/Session/SessionException.php | 15 +- src/System/SystemException.php | 22 ++- src/Template/TemplateException.php | 15 +- src/Validation/RuleViolationException.php | 8 +- src/Validation/ValidationException.php | 8 +- tests/AbstractExceptionTest.php | 19 ++- tests/Auth/AuthenticationExceptionTest.php | 6 +- tests/Auth/AuthorizationExceptionTest.php | 4 +- tests/Cache/CacheExceptionTest.php | 6 +- tests/Config/ConfigurationExceptionTest.php | 6 +- tests/Container/ContainerExceptionTest.php | 5 +- tests/Database/DatabaseExceptionTest.php | 6 +- tests/Event/EventExceptionTest.php | 4 +- tests/ExceptionMessageTest.php | 10 +- .../ExternalServiceExceptionTest.php | 21 ++- tests/File/FileExceptionTest.php | 8 +- tests/Input/InputExceptionTest.php | 21 ++- .../LocalizationExceptionTest.php | 14 +- tests/Middleware/MiddlewareExceptionTest.php | 14 +- tests/Network/HttpExceptionTest.php | 14 +- tests/Network/NetworkExceptionTest.php | 14 +- tests/Queue/QueueExceptionTest.php | 21 ++- tests/Routing/RoutingExceptionTest.php | 14 +- tests/Runtime/RuntimeExceptionTest.php | 21 ++- tests/Security/EncryptionExceptionTest.php | 14 +- tests/Security/SecurityExceptionTest.php | 21 ++- tests/Session/SessionExceptionTest.php | 14 +- tests/System/SystemExceptionTest.php | 21 ++- tests/Template/TemplateExceptionTest.php | 14 +- .../Validation/RuleViolationExceptionTest.php | 9 +- tests/Validation/ValidationExceptionTest.php | 17 ++- 52 files changed, 788 insertions(+), 134 deletions(-) create mode 100644 script.php diff --git a/script.php b/script.php new file mode 100644 index 0000000..6db59dd --- /dev/null +++ b/script.php @@ -0,0 +1,142 @@ +createForNewestSupportedVersion(); + + try { + $ast = $parser->parse($code); + } catch (Error $error) { + echo "Erro ao analisar o arquivo {$filePath}: {$error->getMessage()}\n"; + return; + } + + $traverser = new NodeTraverser(); + + // Adicionar NameResolver + $traverser->addVisitor(new NameResolver()); + + // Adicionar ParentConnectingVisitor + $traverser->addVisitor(new ParentConnectingVisitor()); + + $visitor = new class ($codeMapping) extends NodeVisitorAbstract { + private $codeMapping; + private $currentClass; + private $classNode; + + public function __construct(array $codeMapping) + { + $this->codeMapping = $codeMapping; + } + + public function enterNode(Node $node) + { + if ($node instanceof Node\Stmt\Class_) { + if (isset($node->namespacedName)) { + $this->currentClass = $node->namespacedName->toString(); + } else { + $this->currentClass = $node->name->toString(); + } + $this->classNode = $node; + } + + if ($node instanceof Node\Stmt\ClassMethod && $node->isStatic()) { + if ($this->currentClass && isset($this->codeMapping[$this->currentClass])) { + $methodName = $node->name->toString(); + if (isset($this->codeMapping[$this->currentClass][$methodName])) { + $codeInt = $this->codeMapping[$this->currentClass][$methodName]; + + // Adicionar a constante de código inteiro na classe, se ainda não existir + $constName = 'CODE_' . strtoupper($methodName); + + // Verificar se a constante já existe + $constExists = false; + foreach ($this->classNode->stmts as $stmt) { + if ($stmt instanceof Node\Stmt\ClassConst) { + foreach ($stmt->consts as $const) { + if ($const->name->toString() === $constName) { + $constExists = true; + break 2; + } + } + } + } + + if (!$constExists) { + $const = new Node\Stmt\ClassConst( + [ + new Node\Const_( + new Node\Identifier($constName), + new Int_($codeInt) + ) + ], + Modifiers::PRIVATE + ); + + // Inserir a constante no início dos statements da classe + array_unshift($this->classNode->stmts, $const); + } + } + } + } + } + }; + + $traverser->addVisitor($visitor); + $modifiedAst = $traverser->traverse($ast); + + // Converter o AST de volta para código PHP + $prettyPrinter = new PrettyPrinter\Standard(); + $modifiedCode = $prettyPrinter->prettyPrintFile($modifiedAst); + + // Salvar o código modificado de volta no arquivo + file_put_contents($filePath, $modifiedCode); + echo "Arquivo atualizado: {$filePath}\n"; +} + +// Iniciar o processo de varredura +scanDirectory($baseDir, $codeMapping); + +echo "Atualização concluída.\n"; diff --git a/src/AbstractException.php b/src/AbstractException.php index 945e93f..2a1de1f 100644 --- a/src/AbstractException.php +++ b/src/AbstractException.php @@ -10,13 +10,14 @@ abstract class AbstractException extends \Exception implements Throwable { protected array $context = []; + private string $errorCode; public function __construct(ErrorMessage $errorMessage, ?\Throwable $previous = null, array $context = []) { + $this->errorCode = $errorMessage->getErrorCode(); + $this->context = array_merge(['code' => $this->errorCode], $context); - $this->context = array_merge(['code' => $errorMessage->getCode()], $context); - - parent::__construct($errorMessage->getMessage(), 0, $previous); + parent::__construct($errorMessage->getMessage(), $errorMessage->getCode(), $previous); } public function getContext(): array @@ -24,6 +25,11 @@ public function getContext(): array return $this->context; } + public function getErrorCode(): string + { + return $this->errorCode; + } + protected function addContext(string $key, mixed $value): self { $this->context[$key] = $value; diff --git a/src/Auth/AuthenticationException.php b/src/Auth/AuthenticationException.php index 8caa183..33a2383 100644 --- a/src/Auth/AuthenticationException.php +++ b/src/Auth/AuthenticationException.php @@ -9,18 +9,34 @@ final class AuthenticationException extends AbstractException { + private const CODE_INVALID_CREDENTIALS = 1001; + private const CODE_ACCOUNT_LOCKED = 1002; + private const CODE_TWO_FACTOR_REQUIRED = 1003; + public static function invalidCredentials(): self { - return new self(new ExceptionMessage('INVALID_CREDENTIALS', 'Invalid credentials provided')); + return new self(new ExceptionMessage( + self::CODE_INVALID_CREDENTIALS, + 'INVALID_CREDENTIALS', + 'Invalid credentials provided' + )); } public static function accountLocked(): self { - return new self(new ExceptionMessage('ACCOUNT_LOCKED', 'Account is locked')); + return new self(new ExceptionMessage( + self::CODE_ACCOUNT_LOCKED, + 'ACCOUNT_LOCKED', + 'Account is locked' + )); } public static function twoFactorRequired(): self { - return new self(new ExceptionMessage('TWO_FACTOR_REQUIRED', 'Two-factor authentication is required')); + return new self(new ExceptionMessage( + self::CODE_TWO_FACTOR_REQUIRED, + 'TWO_FACTOR_REQUIRED', + 'Two-factor authentication is required' + )); } } diff --git a/src/Auth/AuthorizationException.php b/src/Auth/AuthorizationException.php index 2ce7c27..db9255d 100644 --- a/src/Auth/AuthorizationException.php +++ b/src/Auth/AuthorizationException.php @@ -9,13 +9,24 @@ final class AuthorizationException extends AbstractException { + private const CODE_INSUFFICIENT_PERMISSIONS = 1101; + private const CODE_ROLE_REQUIRED = 1102; + public static function insufficientPermissions(string $action): self { - return new self(new ExceptionMessage('INSUFFICIENT_PERMISSIONS', "Insufficient permissions for action: {$action}")); + return new self(new ExceptionMessage( + self::CODE_INSUFFICIENT_PERMISSIONS, + 'INSUFFICIENT_PERMISSIONS', + "Insufficient permissions for action: {$action}" + )); } public static function roleRequired(string $role): self { - return new self(new ExceptionMessage('ROLE_REQUIRED', "Required role not present: {$role}")); + return new self(new ExceptionMessage( + self::CODE_ROLE_REQUIRED, + 'ROLE_REQUIRED', + "Required role not present: {$role}" + )); } } diff --git a/src/Cache/CacheException.php b/src/Cache/CacheException.php index df7c33e..0e20f30 100644 --- a/src/Cache/CacheException.php +++ b/src/Cache/CacheException.php @@ -9,18 +9,34 @@ final class CacheException extends AbstractException { + private const CODE_ITEM_NOT_FOUND = 1201; + private const CODE_STORAGE_ERROR = 1202; + private const CODE_INVALID_TTL = 1203; + public static function itemNotFound(string $key): self { - return new self(new ExceptionMessage('CACHE_ITEM_NOT_FOUND', "Cache item not found: {$key}")); + return new self(new ExceptionMessage( + self::CODE_ITEM_NOT_FOUND, + 'CACHE_ITEM_NOT_FOUND', + "Cache item not found: {$key}" + )); } public static function storageError(string $details): self { - return new self(new ExceptionMessage('CACHE_STORAGE_ERROR', "Cache storage error: {$details}")); + return new self(new ExceptionMessage( + self::CODE_STORAGE_ERROR, + 'CACHE_STORAGE_ERROR', + "Cache storage error: {$details}" + )); } public static function invalidTtl(int $ttl): self { - return new self(new ExceptionMessage('INVALID_TTL', "Invalid TTL value: {$ttl}")); + return new self(new ExceptionMessage( + self::CODE_INVALID_TTL, + 'INVALID_TTL', + "Invalid TTL value: {$ttl}" + )); } } diff --git a/src/Config/ConfigurationException.php b/src/Config/ConfigurationException.php index f769fbb..10157dd 100644 --- a/src/Config/ConfigurationException.php +++ b/src/Config/ConfigurationException.php @@ -9,18 +9,34 @@ final class ConfigurationException extends AbstractException { + private const CODE_MISSING_KEY = 1301; + private const CODE_INVALID_VALUE = 1302; + private const CODE_ENVIRONMENT_NOT_SET = 1303; + public static function missingKey(string $key): self { - return new self(new ExceptionMessage('MISSING_CONFIG_KEY', "Missing configuration key: {$key}")); + return new self(new ExceptionMessage( + self::CODE_MISSING_KEY, + 'MISSING_CONFIG_KEY', + "Missing configuration key: {$key}" + )); } public static function invalidValue(string $key, mixed $value): self { - return new self(new ExceptionMessage('INVALID_CONFIG_VALUE', "Invalid configuration value for key '{$key}': " . var_export($value, true))); + return new self(new ExceptionMessage( + self::CODE_INVALID_VALUE, + 'INVALID_CONFIG_VALUE', + "Invalid configuration value for key '{$key}': " . var_export($value, true) + )); } public static function environmentNotSet(string $envVar): self { - return new self(new ExceptionMessage('ENVIRONMENT_NOT_SET', "Environment variable not set: {$envVar}")); + return new self(new ExceptionMessage( + self::CODE_ENVIRONMENT_NOT_SET, + 'ENVIRONMENT_NOT_SET', + "Environment variable not set: {$envVar}" + )); } } diff --git a/src/Container/ContainerException.php b/src/Container/ContainerException.php index 2cd0615..fa85dce 100644 --- a/src/Container/ContainerException.php +++ b/src/Container/ContainerException.php @@ -9,13 +9,24 @@ final class ContainerException extends AbstractException { + private const CODE_SERVICE_NOT_FOUND = 1401; + private const CODE_CIRCULAR_DEPENDENCY = 1402; + public static function serviceNotFound(string $serviceId): self { - return new self(new ExceptionMessage('SERVICE_NOT_FOUND', "Service not found in container: {$serviceId}")); + return new self(new ExceptionMessage( + self::CODE_SERVICE_NOT_FOUND, + 'SERVICE_NOT_FOUND', + "Service not found in container: {$serviceId}" + )); } public static function circularDependency(string $serviceId): self { - return new self(new ExceptionMessage('CIRCULAR_DEPENDENCY', "Circular dependency detected for service: {$serviceId}")); + return new self(new ExceptionMessage( + self::CODE_CIRCULAR_DEPENDENCY, + 'CIRCULAR_DEPENDENCY', + "Circular dependency detected for service: {$serviceId}" + )); } } diff --git a/src/Database/DatabaseException.php b/src/Database/DatabaseException.php index f0b1c21..eeb6ed6 100644 --- a/src/Database/DatabaseException.php +++ b/src/Database/DatabaseException.php @@ -9,18 +9,34 @@ final class DatabaseException extends AbstractException { + private const CODE_CONNECTION_ERROR = 1501; + private const CODE_QUERY_ERROR = 1502; + private const CODE_DEADLOCK_DETECTED = 1503; + public static function connectionError(string $details): self { - return new self(new ExceptionMessage('DB_CONNECTION_ERROR', "Database connection error: {$details}")); + return new self(new ExceptionMessage( + self::CODE_CONNECTION_ERROR, + 'DB_CONNECTION_ERROR', + "Database connection error: {$details}" + )); } public static function queryError(string $query, string $error): self { - return new self(new ExceptionMessage('DB_QUERY_ERROR', "Database query error: {$error}")); + return new self(new ExceptionMessage( + self::CODE_QUERY_ERROR, + 'DB_QUERY_ERROR', + "Database query error: {$error}" + )); } public static function deadlockDetected(): self { - return new self(new ExceptionMessage('DB_DEADLOCK', 'Database deadlock detected')); + return new self(new ExceptionMessage( + self::CODE_DEADLOCK_DETECTED, + 'DB_DEADLOCK', + 'Database deadlock detected' + )); } } diff --git a/src/Event/EventException.php b/src/Event/EventException.php index 26c39f4..544a968 100644 --- a/src/Event/EventException.php +++ b/src/Event/EventException.php @@ -9,13 +9,24 @@ final class EventException extends AbstractException { + private const CODE_LISTENER_NOT_CALLABLE = 1601; + private const CODE_EVENT_DISPATCH_FAILED = 1602; + public static function listenerNotCallable(string $eventName): self { - return new self(new ExceptionMessage('LISTENER_NOT_CALLABLE', "Event listener is not callable for event: {$eventName}")); + return new self(new ExceptionMessage( + self::CODE_LISTENER_NOT_CALLABLE, + 'LISTENER_NOT_CALLABLE', + "Event listener is not callable for event: {$eventName}" + )); } public static function eventDispatchFailed(string $eventName): self { - return new self(new ExceptionMessage('EVENT_DISPATCH_FAILED', "Failed to dispatch event: {$eventName}")); + return new self(new ExceptionMessage( + self::CODE_EVENT_DISPATCH_FAILED, + 'EVENT_DISPATCH_FAILED', + "Failed to dispatch event: {$eventName}" + )); } } diff --git a/src/ExternalService/ExternalServiceException.php b/src/ExternalService/ExternalServiceException.php index 68cbbd9..c7d9bed 100644 --- a/src/ExternalService/ExternalServiceException.php +++ b/src/ExternalService/ExternalServiceException.php @@ -9,18 +9,34 @@ final class ExternalServiceException extends AbstractException { + private const CODE_API_ERROR = 1701; + private const CODE_SERVICE_UNAVAILABLE = 1702; + private const CODE_INVALID_RESPONSE = 1703; + public static function apiError(string $service, string $error): self { - return new self(new ExceptionMessage('API_ERROR', "Error from external service '{$service}': {$error}")); + return new self(new ExceptionMessage( + self::CODE_API_ERROR, + 'API_ERROR', + "Error from external service '{$service}': {$error}" + )); } public static function serviceUnavailable(string $service): self { - return new self(new ExceptionMessage('SERVICE_UNAVAILABLE', "External service unavailable: {$service}")); + return new self(new ExceptionMessage( + self::CODE_SERVICE_UNAVAILABLE, + 'SERVICE_UNAVAILABLE', + "External service unavailable: {$service}" + )); } public static function invalidResponse(string $service): self { - return new self(new ExceptionMessage('INVALID_RESPONSE', "Invalid response from external service: {$service}")); + return new self(new ExceptionMessage( + self::CODE_INVALID_RESPONSE, + 'INVALID_RESPONSE', + "Invalid response from external service: {$service}" + )); } } diff --git a/src/File/FileException.php b/src/File/FileException.php index d744dc2..1e55627 100644 --- a/src/File/FileException.php +++ b/src/File/FileException.php @@ -9,23 +9,44 @@ final class FileException extends AbstractException { + private const CODE_NOT_FOUND = 1801; + private const CODE_PERMISSION_DENIED = 1802; + private const CODE_UNREADABLE = 1803; + private const CODE_UPLOAD_FAILED = 1804; + public static function notFound(string $path): self { - return new self(new ExceptionMessage('FILE_NOT_FOUND', "File not found: {$path}")); + return new self(new ExceptionMessage( + self::CODE_NOT_FOUND, + 'FILE_NOT_FOUND', + "File not found: {$path}" + )); } public static function permissionDenied(string $path): self { - return new self(new ExceptionMessage('PERMISSION_DENIED', "Permission denied for file: {$path}")); + return new self(new ExceptionMessage( + self::CODE_PERMISSION_DENIED, + 'PERMISSION_DENIED', + "Permission denied for file: {$path}" + )); } public static function unreadable(string $path): self { - return new self(new ExceptionMessage('FILE_UNREADABLE', "File is not readable: {$path}")); + return new self(new ExceptionMessage( + self::CODE_UNREADABLE, + 'FILE_UNREADABLE', + "File is not readable: {$path}" + )); } public static function uploadFailed(string $filename): self { - return new self(new ExceptionMessage('UPLOAD_FAILED', "Failed to upload file: {$filename}")); + return new self(new ExceptionMessage( + self::CODE_UPLOAD_FAILED, + 'UPLOAD_FAILED', + "Failed to upload file: {$filename}" + )); } } diff --git a/src/Input/InputException.php b/src/Input/InputException.php index 338bc57..2795c20 100644 --- a/src/Input/InputException.php +++ b/src/Input/InputException.php @@ -9,18 +9,34 @@ final class InputException extends AbstractException { + private const CODE_INVALID_FORMAT = 1901; + private const CODE_MISSING_REQUIRED = 1902; + private const CODE_EXCEEDS_MAX_LENGTH = 1903; + public static function invalidFormat(string $field): self { - return new self(new ExceptionMessage('INVALID_FORMAT', "Invalid format for field: {$field}")); + return new self(new ExceptionMessage( + self::CODE_INVALID_FORMAT, + 'INVALID_FORMAT', + "Invalid format for field: {$field}" + )); } public static function missingRequired(string $field): self { - return new self(new ExceptionMessage('MISSING_REQUIRED', "Missing required field: {$field}")); + return new self(new ExceptionMessage( + self::CODE_MISSING_REQUIRED, + 'MISSING_REQUIRED', + "Missing required field: {$field}" + )); } public static function exceedsMaxLength(string $field, int $maxLength): self { - return new self(new ExceptionMessage('EXCEEDS_MAX_LENGTH', "Field '{$field}' exceeds maximum length of {$maxLength}")); + return new self(new ExceptionMessage( + self::CODE_EXCEEDS_MAX_LENGTH, + 'EXCEEDS_MAX_LENGTH', + "Field '{$field}' exceeds maximum length of {$maxLength}" + )); } } diff --git a/src/Localization/LocalizationException.php b/src/Localization/LocalizationException.php index 4b12715..560ab1e 100644 --- a/src/Localization/LocalizationException.php +++ b/src/Localization/LocalizationException.php @@ -9,13 +9,24 @@ final class LocalizationException extends AbstractException { + private const CODE_MISSING_TRANSLATION = 2001; + private const CODE_INVALID_LOCALE = 2002; + public static function missingTranslation(string $key, string $locale): self { - return new self(new ExceptionMessage('MISSING_TRANSLATION', "Missing translation for key '{$key}' in locale '{$locale}'")); + return new self(new ExceptionMessage( + self::CODE_MISSING_TRANSLATION, + 'MISSING_TRANSLATION', + "Missing translation for key '{$key}' in locale '{$locale}'" + )); } public static function invalidLocale(string $locale): self { - return new self(new ExceptionMessage('INVALID_LOCALE', "Invalid locale: {$locale}")); + return new self(new ExceptionMessage( + self::CODE_INVALID_LOCALE, + 'INVALID_LOCALE', + "Invalid locale: {$locale}" + )); } } diff --git a/src/Middleware/MiddlewareException.php b/src/Middleware/MiddlewareException.php index a143f6b..3fed9d9 100644 --- a/src/Middleware/MiddlewareException.php +++ b/src/Middleware/MiddlewareException.php @@ -9,13 +9,24 @@ final class MiddlewareException extends AbstractException { + private const CODE_INVALID_MIDDLEWARE = 2101; + private const CODE_MIDDLEWARE_EXECUTION_FAILED = 2102; + public static function invalidMiddleware(string $middlewareName): self { - return new self(new ExceptionMessage('INVALID_MIDDLEWARE', "Invalid middleware: {$middlewareName}")); + return new self(new ExceptionMessage( + self::CODE_INVALID_MIDDLEWARE, + 'INVALID_MIDDLEWARE', + "Invalid middleware: {$middlewareName}" + )); } public static function middlewareExecutionFailed(string $middlewareName): self { - return new self(new ExceptionMessage('MIDDLEWARE_EXECUTION_FAILED', "Execution failed for middleware: {$middlewareName}")); + return new self(new ExceptionMessage( + self::CODE_MIDDLEWARE_EXECUTION_FAILED, + 'MIDDLEWARE_EXECUTION_FAILED', + "Execution failed for middleware: {$middlewareName}" + )); } } diff --git a/src/Network/HttpException.php b/src/Network/HttpException.php index f1d9bc8..6a4de2c 100644 --- a/src/Network/HttpException.php +++ b/src/Network/HttpException.php @@ -9,13 +9,24 @@ final class HttpException extends AbstractException { + private const CODE_CLIENT_ERROR = 2203; + private const CODE_SERVER_ERROR = 2204; + public static function clientError(int $statusCode): self { - return new self(new ExceptionMessage('HTTP_CLIENT_ERROR', "HTTP client error with status code: {$statusCode}")); + return new self(new ExceptionMessage( + self::CODE_CLIENT_ERROR, + 'HTTP_CLIENT_ERROR', + "HTTP client error with status code: {$statusCode}" + )); } public static function serverError(int $statusCode): self { - return new self(new ExceptionMessage('HTTP_SERVER_ERROR', "HTTP server error with status code: {$statusCode}")); + return new self(new ExceptionMessage( + self::CODE_SERVER_ERROR, + 'HTTP_SERVER_ERROR', + "HTTP server error with status code: {$statusCode}" + )); } } diff --git a/src/Network/NetworkException.php b/src/Network/NetworkException.php index e0f5ac2..d54df19 100644 --- a/src/Network/NetworkException.php +++ b/src/Network/NetworkException.php @@ -9,13 +9,24 @@ final class NetworkException extends AbstractException { + private const CODE_CONNECTION_FAILED = 2201; + private const CODE_TIMEOUT = 2202; + public static function connectionFailed(string $host): self { - return new self(new ExceptionMessage('CONNECTION_FAILED', "Failed to connect to host: {$host}")); + return new self(new ExceptionMessage( + self::CODE_CONNECTION_FAILED, + 'CONNECTION_FAILED', + "Failed to connect to host: {$host}" + )); } public static function timeout(string $operation): self { - return new self(new ExceptionMessage('TIMEOUT', "Network operation timed out: {$operation}")); + return new self(new ExceptionMessage( + self::CODE_TIMEOUT, + 'TIMEOUT', + "Network operation timed out: {$operation}" + )); } } diff --git a/src/Queue/QueueException.php b/src/Queue/QueueException.php index 393dd6d..312438b 100644 --- a/src/Queue/QueueException.php +++ b/src/Queue/QueueException.php @@ -9,18 +9,34 @@ final class QueueException extends AbstractException { + private const CODE_JOB_PUSH_FAILED = 2301; + private const CODE_JOB_PROCESSING_FAILED = 2302; + private const CODE_QUEUE_CONNECTION_FAILED = 2303; + public static function jobPushFailed(string $jobClass): self { - return new self(new ExceptionMessage('JOB_PUSH_FAILED', "Failed to push job to queue: {$jobClass}")); + return new self(new ExceptionMessage( + self::CODE_JOB_PUSH_FAILED, + 'JOB_PUSH_FAILED', + "Failed to push job to queue: {$jobClass}" + )); } public static function jobProcessingFailed(string $jobId): self { - return new self(new ExceptionMessage('JOB_PROCESSING_FAILED', "Failed to process job: {$jobId}")); + return new self(new ExceptionMessage( + self::CODE_JOB_PROCESSING_FAILED, + 'JOB_PROCESSING_FAILED', + "Failed to process job: {$jobId}" + )); } public static function queueConnectionFailed(string $connection): self { - return new self(new ExceptionMessage('QUEUE_CONNECTION_FAILED', "Failed to connect to queue: {$connection}")); + return new self(new ExceptionMessage( + self::CODE_QUEUE_CONNECTION_FAILED, + 'QUEUE_CONNECTION_FAILED', + "Failed to connect to queue: {$connection}" + )); } } diff --git a/src/Routing/RoutingException.php b/src/Routing/RoutingException.php index 1d075ac..b1297bc 100644 --- a/src/Routing/RoutingException.php +++ b/src/Routing/RoutingException.php @@ -9,13 +9,24 @@ final class RoutingException extends AbstractException { + private const CODE_ROUTE_NOT_FOUND = 2401; + private const CODE_METHOD_NOT_ALLOWED = 2402; + public static function routeNotFound(string $uri): self { - return new self(new ExceptionMessage('ROUTE_NOT_FOUND', "Route not found for URI: {$uri}")); + return new self(new ExceptionMessage( + self::CODE_ROUTE_NOT_FOUND, + 'ROUTE_NOT_FOUND', + "Route not found for URI: {$uri}" + )); } public static function methodNotAllowed(string $method, string $uri): self { - return new self(new ExceptionMessage('METHOD_NOT_ALLOWED', "Method {$method} not allowed for URI: {$uri}")); + return new self(new ExceptionMessage( + self::CODE_METHOD_NOT_ALLOWED, + 'METHOD_NOT_ALLOWED', + "Method {$method} not allowed for URI: {$uri}" + )); } } diff --git a/src/Runtime/RuntimeException.php b/src/Runtime/RuntimeException.php index abc05de..30b440f 100644 --- a/src/Runtime/RuntimeException.php +++ b/src/Runtime/RuntimeException.php @@ -9,18 +9,34 @@ final class RuntimeException extends AbstractException { + private const CODE_UNEXPECTED_VALUE = 2501; + private const CODE_OUT_OF_MEMORY = 2502; + private const CODE_CLASS_NOT_FOUND = 2503; + public static function unexpectedValue(string $details): self { - return new self(new ExceptionMessage('UNEXPECTED_VALUE', "Unexpected value: {$details}")); + return new self(new ExceptionMessage( + self::CODE_UNEXPECTED_VALUE, + 'UNEXPECTED_VALUE', + "Unexpected value: {$details}" + )); } public static function outOfMemory(): self { - return new self(new ExceptionMessage('OUT_OF_MEMORY', 'Out of memory error')); + return new self(new ExceptionMessage( + self::CODE_OUT_OF_MEMORY, + 'OUT_OF_MEMORY', + 'Out of memory error' + )); } public static function classNotFound(string $className): self { - return new self(new ExceptionMessage('CLASS_NOT_FOUND', "Class not found: {$className}")); + return new self(new ExceptionMessage( + self::CODE_CLASS_NOT_FOUND, + 'CLASS_NOT_FOUND', + "Class not found: {$className}" + )); } } diff --git a/src/Security/EncryptionException.php b/src/Security/EncryptionException.php index 693eab8..472dc5b 100644 --- a/src/Security/EncryptionException.php +++ b/src/Security/EncryptionException.php @@ -9,13 +9,24 @@ final class EncryptionException extends AbstractException { + private const CODE_ENCRYPTION_FAILED = 2601; + private const CODE_DECRYPTION_FAILED = 2602; + public static function encryptionFailed(): self { - return new self(new ExceptionMessage('ENCRYPTION_FAILED', 'Encryption operation failed')); + return new self(new ExceptionMessage( + self::CODE_ENCRYPTION_FAILED, + 'ENCRYPTION_FAILED', + 'Encryption operation failed' + )); } public static function decryptionFailed(): self { - return new self(new ExceptionMessage('DECRYPTION_FAILED', 'Decryption operation failed')); + return new self(new ExceptionMessage( + self::CODE_DECRYPTION_FAILED, + 'DECRYPTION_FAILED', + 'Decryption operation failed' + )); } } diff --git a/src/Security/SecurityException.php b/src/Security/SecurityException.php index fe4c0e0..2afb3ea 100644 --- a/src/Security/SecurityException.php +++ b/src/Security/SecurityException.php @@ -9,18 +9,34 @@ final class SecurityException extends AbstractException { + private const CODE_UNAUTHORIZED = 2701; + private const CODE_CSRF_TOKEN_MISMATCH = 2702; + private const CODE_RATE_LIMIT_EXCEEDED = 2703; + public static function unauthorized(): self { - return new self(new ExceptionMessage('UNAUTHORIZED', 'Unauthorized access')); + return new self(new ExceptionMessage( + self::CODE_UNAUTHORIZED, + 'UNAUTHORIZED', + 'Unauthorized access' + )); } public static function csrfTokenMismatch(): self { - return new self(new ExceptionMessage('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch')); + return new self(new ExceptionMessage( + self::CODE_CSRF_TOKEN_MISMATCH, + 'CSRF_TOKEN_MISMATCH', + 'CSRF token mismatch' + )); } public static function rateLimitExceeded(): self { - return new self(new ExceptionMessage('RATE_LIMIT_EXCEEDED', 'Rate limit exceeded')); + return new self(new ExceptionMessage( + self::CODE_RATE_LIMIT_EXCEEDED, + 'RATE_LIMIT_EXCEEDED', + 'Rate limit exceeded' + )); } } diff --git a/src/Session/SessionException.php b/src/Session/SessionException.php index 4f94a3a..694b56b 100644 --- a/src/Session/SessionException.php +++ b/src/Session/SessionException.php @@ -9,13 +9,24 @@ final class SessionException extends AbstractException { + private const CODE_SESSION_START_FAILED = 2801; + private const CODE_INVALID_SESSION_ID = 2802; + public static function sessionStartFailed(): self { - return new self(new ExceptionMessage('SESSION_START_FAILED', 'Failed to start session')); + return new self(new ExceptionMessage( + self::CODE_SESSION_START_FAILED, + 'SESSION_START_FAILED', + 'Failed to start session' + )); } public static function invalidSessionId(): self { - return new self(new ExceptionMessage('INVALID_SESSION_ID', 'Invalid session ID')); + return new self(new ExceptionMessage( + self::CODE_INVALID_SESSION_ID, + 'INVALID_SESSION_ID', + 'Invalid session ID' + )); } } diff --git a/src/System/SystemException.php b/src/System/SystemException.php index 87765ba..4a4379d 100644 --- a/src/System/SystemException.php +++ b/src/System/SystemException.php @@ -9,18 +9,34 @@ final class SystemException extends AbstractException { + private const CODE_RESOURCE_UNAVAILABLE = 2901; + private const CODE_ENVIRONMENT_ERROR = 2902; + private const CODE_EXTENSION_NOT_LOADED = 2903; + public static function resourceUnavailable(string $resource): self { - return new self(new ExceptionMessage('RESOURCE_UNAVAILABLE', "System resource unavailable: {$resource}")); + return new self(new ExceptionMessage( + self::CODE_RESOURCE_UNAVAILABLE, + 'RESOURCE_UNAVAILABLE', + "System resource unavailable: {$resource}" + )); } public static function environmentError(string $details): self { - return new self(new ExceptionMessage('ENVIRONMENT_ERROR', "Environment error: {$details}")); + return new self(new ExceptionMessage( + self::CODE_ENVIRONMENT_ERROR, + 'ENVIRONMENT_ERROR', + "Environment error: {$details}" + )); } public static function extensionNotLoaded(string $extension): self { - return new self(new ExceptionMessage('EXTENSION_NOT_LOADED', "PHP extension not loaded: {$extension}")); + return new self(new ExceptionMessage( + self::CODE_EXTENSION_NOT_LOADED, + 'EXTENSION_NOT_LOADED', + "PHP extension not loaded: {$extension}" + )); } } diff --git a/src/Template/TemplateException.php b/src/Template/TemplateException.php index fa73f4c..9536cc2 100644 --- a/src/Template/TemplateException.php +++ b/src/Template/TemplateException.php @@ -9,13 +9,24 @@ final class TemplateException extends AbstractException { + private const CODE_TEMPLATE_NOT_FOUND = 3001; + private const CODE_RENDERING_FAILED = 3002; + public static function templateNotFound(string $templateName): self { - return new self(new ExceptionMessage('TEMPLATE_NOT_FOUND', "Template not found: {$templateName}")); + return new self(new ExceptionMessage( + self::CODE_TEMPLATE_NOT_FOUND, + 'TEMPLATE_NOT_FOUND', + "Template not found: {$templateName}" + )); } public static function renderingFailed(string $templateName): self { - return new self(new ExceptionMessage('RENDERING_FAILED', "Failed to render template: {$templateName}")); + return new self(new ExceptionMessage( + self::CODE_RENDERING_FAILED, + 'RENDERING_FAILED', + "Failed to render template: {$templateName}" + )); } } diff --git a/src/Validation/RuleViolationException.php b/src/Validation/RuleViolationException.php index 5614b54..bd1931f 100644 --- a/src/Validation/RuleViolationException.php +++ b/src/Validation/RuleViolationException.php @@ -9,8 +9,14 @@ final class RuleViolationException extends AbstractException { + private const CODE_RULE_VIOLATION = 3102; + public static function create(string $rule, string $field): self { - return new self(new ExceptionMessage('RULE_VIOLATION', "Validation rule '{$rule}' violated for field '{$field}'")); + return new self(new ExceptionMessage( + self::CODE_RULE_VIOLATION, + 'RULE_VIOLATION', + "Validation rule '{$rule}' violated for field '{$field}'" + )); } } diff --git a/src/Validation/ValidationException.php b/src/Validation/ValidationException.php index 845e962..8bfb6e4 100644 --- a/src/Validation/ValidationException.php +++ b/src/Validation/ValidationException.php @@ -10,11 +10,17 @@ final class ValidationException extends AbstractException { + private const CODE_VALIDATION_FAILED = 3101; + private array $validationErrors = []; public static function create(): self { - return new self(new ExceptionMessage('VALIDATION_FAILED', 'Validation failed')); + return new self(new ExceptionMessage( + self::CODE_VALIDATION_FAILED, + 'VALIDATION_FAILED', + 'Validation failed' + )); } public function addError(string $field, ErrorMessage $errorMessage): self diff --git a/tests/AbstractExceptionTest.php b/tests/AbstractExceptionTest.php index 3314022..82d9d49 100644 --- a/tests/AbstractExceptionTest.php +++ b/tests/AbstractExceptionTest.php @@ -14,7 +14,7 @@ class AbstractExceptionTest extends TestCase protected function setUp(): void { - $errorMessage = new ExceptionMessage('TEST_CODE', 'Test message'); + $errorMessage = new ExceptionMessage(9999, 'TEST_CODE', 'Test message'); $this->exception = new ConcreteTestException($errorMessage); } @@ -22,15 +22,19 @@ public function testExceptionCreation(): void { $this->assertSame('Test message', $this->exception->getMessage()); $this->assertSame(['code' => 'TEST_CODE'], $this->exception->getContext()); + $this->assertSame('TEST_CODE', $this->exception->getErrorCode()); + $this->assertSame(9999, $this->exception->getCode()); } public function testExceptionWithContext(): void { - $errorMessage = new ExceptionMessage('TEST_CODE', 'Test message'); + $errorMessage = new ExceptionMessage(9999, 'TEST_CODE', 'Test message'); $context = ['key' => 'value']; $exception = new ConcreteTestException($errorMessage, null, $context); $this->assertSame(['code' => 'TEST_CODE', 'key' => 'value'], $exception->getContext()); + $this->assertSame('TEST_CODE', $exception->getErrorCode()); + $this->assertSame(9999, $exception->getCode()); } public function testAddContext(): void @@ -44,22 +48,25 @@ public function testAddContext(): void public function testExceptionWithPrevious(): void { $previousException = new \Exception('Previous exception'); - $errorMessage = new ExceptionMessage('TEST_CODE', 'Test message'); + $errorMessage = new ExceptionMessage(9999, 'TEST_CODE', 'Test message'); $exception = new ConcreteTestException($errorMessage, $previousException); $this->assertSame($previousException, $exception->getPrevious()); + $this->assertSame(9999, $exception->getCode()); } - protected function assertExceptionStructure(AbstractException $exception, string $expectedCode, string $expectedMessage): void + protected function assertExceptionStructure(AbstractException $exception, string $expectedErrorCode, string $expectedMessage, int $expectedCode): void { $this->assertInstanceOf(AbstractException::class, $exception); $this->assertSame($expectedMessage, $exception->getMessage()); $this->assertArrayHasKey('code', $exception->getContext()); - $this->assertSame($expectedCode, $exception->getContext()['code']); + $this->assertSame($expectedErrorCode, $exception->getContext()['code']); + $this->assertSame($expectedErrorCode, $exception->getErrorCode()); + $this->assertSame($expectedCode, $exception->getCode()); } } -// Concrete implementation of AbstractException for testing +// Implementação concreta de AbstractException para teste final class ConcreteTestException extends AbstractException { public function addTestContext(string $key, mixed $value): self diff --git a/tests/Auth/AuthenticationExceptionTest.php b/tests/Auth/AuthenticationExceptionTest.php index 43f85ba..ebd30d2 100644 --- a/tests/Auth/AuthenticationExceptionTest.php +++ b/tests/Auth/AuthenticationExceptionTest.php @@ -12,18 +12,18 @@ final class AuthenticationExceptionTest extends AbstractExceptionTest public function testInvalidCredentials(): void { $exception = AuthenticationException::invalidCredentials(); - $this->assertExceptionStructure($exception, 'INVALID_CREDENTIALS', 'Invalid credentials provided'); + $this->assertExceptionStructure($exception, 'INVALID_CREDENTIALS', 'Invalid credentials provided', 1001); } public function testAccountLocked(): void { $exception = AuthenticationException::accountLocked(); - $this->assertExceptionStructure($exception, 'ACCOUNT_LOCKED', 'Account is locked'); + $this->assertExceptionStructure($exception, 'ACCOUNT_LOCKED', 'Account is locked', 1002); } public function testTwoFactorRequired(): void { $exception = AuthenticationException::twoFactorRequired(); - $this->assertExceptionStructure($exception, 'TWO_FACTOR_REQUIRED', 'Two-factor authentication is required'); + $this->assertExceptionStructure($exception, 'TWO_FACTOR_REQUIRED', 'Two-factor authentication is required', 1003); } } diff --git a/tests/Auth/AuthorizationExceptionTest.php b/tests/Auth/AuthorizationExceptionTest.php index 98c00b7..da2077b 100644 --- a/tests/Auth/AuthorizationExceptionTest.php +++ b/tests/Auth/AuthorizationExceptionTest.php @@ -13,13 +13,13 @@ public function testInsufficientPermissions(): void { $action = 'delete_user'; $exception = AuthorizationException::insufficientPermissions($action); - $this->assertExceptionStructure($exception, 'INSUFFICIENT_PERMISSIONS', "Insufficient permissions for action: {$action}"); + $this->assertExceptionStructure($exception, 'INSUFFICIENT_PERMISSIONS', "Insufficient permissions for action: {$action}", 1101); } public function testRoleRequired(): void { $role = 'admin'; $exception = AuthorizationException::roleRequired($role); - $this->assertExceptionStructure($exception, 'ROLE_REQUIRED', "Required role not present: {$role}"); + $this->assertExceptionStructure($exception, 'ROLE_REQUIRED', "Required role not present: {$role}", 1102); } } diff --git a/tests/Cache/CacheExceptionTest.php b/tests/Cache/CacheExceptionTest.php index 1781b8b..bbab713 100644 --- a/tests/Cache/CacheExceptionTest.php +++ b/tests/Cache/CacheExceptionTest.php @@ -13,20 +13,20 @@ public function testItemNotFound(): void { $key = 'user_profile_1'; $exception = CacheException::itemNotFound($key); - $this->assertExceptionStructure($exception, 'CACHE_ITEM_NOT_FOUND', "Cache item not found: {$key}"); + $this->assertExceptionStructure($exception, 'CACHE_ITEM_NOT_FOUND', "Cache item not found: {$key}", 1201); } public function testStorageError(): void { $details = 'Redis connection failed'; $exception = CacheException::storageError($details); - $this->assertExceptionStructure($exception, 'CACHE_STORAGE_ERROR', "Cache storage error: {$details}"); + $this->assertExceptionStructure($exception, 'CACHE_STORAGE_ERROR', "Cache storage error: {$details}", 1202); } public function testInvalidTtl(): void { $ttl = -1; $exception = CacheException::invalidTtl($ttl); - $this->assertExceptionStructure($exception, 'INVALID_TTL', "Invalid TTL value: {$ttl}"); + $this->assertExceptionStructure($exception, 'INVALID_TTL', "Invalid TTL value: {$ttl}", 1203); } } diff --git a/tests/Config/ConfigurationExceptionTest.php b/tests/Config/ConfigurationExceptionTest.php index 57e07bf..1ea0741 100644 --- a/tests/Config/ConfigurationExceptionTest.php +++ b/tests/Config/ConfigurationExceptionTest.php @@ -13,7 +13,7 @@ public function testMissingKey(): void { $key = 'database.host'; $exception = ConfigurationException::missingKey($key); - $this->assertExceptionStructure($exception, 'MISSING_CONFIG_KEY', "Missing configuration key: {$key}"); + $this->assertExceptionStructure($exception, 'MISSING_CONFIG_KEY', "Missing configuration key: {$key}", 1301); } public function testInvalidValue(): void @@ -21,13 +21,13 @@ public function testInvalidValue(): void $key = 'app.debug'; $value = 'not_a_boolean'; $exception = ConfigurationException::invalidValue($key, $value); - $this->assertExceptionStructure($exception, 'INVALID_CONFIG_VALUE', "Invalid configuration value for key '{$key}': " . var_export($value, true)); + $this->assertExceptionStructure($exception, 'INVALID_CONFIG_VALUE', "Invalid configuration value for key '{$key}': " . var_export($value, true), 1302); } public function testEnvironmentNotSet(): void { $envVar = 'APP_KEY'; $exception = ConfigurationException::environmentNotSet($envVar); - $this->assertExceptionStructure($exception, 'ENVIRONMENT_NOT_SET', "Environment variable not set: {$envVar}"); + $this->assertExceptionStructure($exception, 'ENVIRONMENT_NOT_SET', "Environment variable not set: {$envVar}", 1303); } } diff --git a/tests/Container/ContainerExceptionTest.php b/tests/Container/ContainerExceptionTest.php index 5569fe9..1827c3a 100644 --- a/tests/Container/ContainerExceptionTest.php +++ b/tests/Container/ContainerExceptionTest.php @@ -2,7 +2,6 @@ declare(strict_types=1); - namespace KaririCode\Exception\Tests\Container; use KaririCode\Exception\Container\ContainerException; @@ -14,13 +13,13 @@ public function testServiceNotFound(): void { $serviceId = 'App\Service\EmailService'; $exception = ContainerException::serviceNotFound($serviceId); - $this->assertExceptionStructure($exception, 'SERVICE_NOT_FOUND', "Service not found in container: {$serviceId}"); + $this->assertExceptionStructure($exception, 'SERVICE_NOT_FOUND', "Service not found in container: {$serviceId}", 1401); } public function testCircularDependency(): void { $serviceId = 'App\Service\UserService'; $exception = ContainerException::circularDependency($serviceId); - $this->assertExceptionStructure($exception, 'CIRCULAR_DEPENDENCY', "Circular dependency detected for service: {$serviceId}"); + $this->assertExceptionStructure($exception, 'CIRCULAR_DEPENDENCY', "Circular dependency detected for service: {$serviceId}", 1402); } } diff --git a/tests/Database/DatabaseExceptionTest.php b/tests/Database/DatabaseExceptionTest.php index 4d428ce..7ed92a8 100644 --- a/tests/Database/DatabaseExceptionTest.php +++ b/tests/Database/DatabaseExceptionTest.php @@ -13,7 +13,7 @@ public function testConnectionError(): void { $details = 'Connection refused'; $exception = DatabaseException::connectionError($details); - $this->assertExceptionStructure($exception, 'DB_CONNECTION_ERROR', "Database connection error: {$details}"); + $this->assertExceptionStructure($exception, 'DB_CONNECTION_ERROR', "Database connection error: {$details}", 1501); } public function testQueryError(): void @@ -21,12 +21,12 @@ public function testQueryError(): void $query = 'SELECT * FROM users'; $error = 'Table "users" not found'; $exception = DatabaseException::queryError($query, $error); - $this->assertExceptionStructure($exception, 'DB_QUERY_ERROR', "Database query error: {$error}"); + $this->assertExceptionStructure($exception, 'DB_QUERY_ERROR', "Database query error: {$error}", 1502); } public function testDeadlockDetected(): void { $exception = DatabaseException::deadlockDetected(); - $this->assertExceptionStructure($exception, 'DB_DEADLOCK', 'Database deadlock detected'); + $this->assertExceptionStructure($exception, 'DB_DEADLOCK', 'Database deadlock detected', 1503); } } diff --git a/tests/Event/EventExceptionTest.php b/tests/Event/EventExceptionTest.php index 8e98d04..d68689f 100644 --- a/tests/Event/EventExceptionTest.php +++ b/tests/Event/EventExceptionTest.php @@ -13,13 +13,13 @@ public function testListenerNotCallable(): void { $eventName = 'user.registered'; $exception = EventException::listenerNotCallable($eventName); - $this->assertExceptionStructure($exception, 'LISTENER_NOT_CALLABLE', "Event listener is not callable for event: {$eventName}"); + $this->assertExceptionStructure($exception, 'LISTENER_NOT_CALLABLE', "Event listener is not callable for event: {$eventName}", 1601); } public function testEventDispatchFailed(): void { $eventName = 'email.sent'; $exception = EventException::eventDispatchFailed($eventName); - $this->assertExceptionStructure($exception, 'EVENT_DISPATCH_FAILED', "Failed to dispatch event: {$eventName}"); + $this->assertExceptionStructure($exception, 'EVENT_DISPATCH_FAILED', "Failed to dispatch event: {$eventName}", 1602); } } diff --git a/tests/ExceptionMessageTest.php b/tests/ExceptionMessageTest.php index 62814ca..fcd5453 100644 --- a/tests/ExceptionMessageTest.php +++ b/tests/ExceptionMessageTest.php @@ -11,20 +11,22 @@ final class ExceptionMessageTest extends TestCase { public function testExceptionMessageCreation(): void { - $code = 'TEST_CODE'; + $code = 9999; + $errorCode = 'TEST_CODE'; $message = 'Test message'; - $exceptionMessage = new ExceptionMessage($code, $message); + $exceptionMessage = new ExceptionMessage($code, $errorCode, $message); $this->assertSame($code, $exceptionMessage->getCode()); + $this->assertSame($errorCode, $exceptionMessage->getErrorCode()); $this->assertSame($message, $exceptionMessage->getMessage()); } public function testExceptionMessageImmutability(): void { - $exceptionMessage = new ExceptionMessage('CODE', 'Message'); + $exceptionMessage = new ExceptionMessage(9999, 'CODE', 'Message'); $this->expectException(\Error::class); $reflectionProperty = new \ReflectionProperty($exceptionMessage, 'code'); - $reflectionProperty->setValue($exceptionMessage, 'NEW_CODE'); + $reflectionProperty->setValue($exceptionMessage, 1234); } } diff --git a/tests/ExternalService/ExternalServiceExceptionTest.php b/tests/ExternalService/ExternalServiceExceptionTest.php index af13c8c..2b74546 100644 --- a/tests/ExternalService/ExternalServiceExceptionTest.php +++ b/tests/ExternalService/ExternalServiceExceptionTest.php @@ -14,20 +14,35 @@ public function testApiError(): void $service = 'PaymentGateway'; $error = 'Invalid API key'; $exception = ExternalServiceException::apiError($service, $error); - $this->assertExceptionStructure($exception, 'API_ERROR', "Error from external service '{$service}': {$error}"); + $this->assertExceptionStructure( + $exception, + 'API_ERROR', + "Error from external service '{$service}': {$error}", + 1701 + ); } public function testServiceUnavailable(): void { $service = 'EmailService'; $exception = ExternalServiceException::serviceUnavailable($service); - $this->assertExceptionStructure($exception, 'SERVICE_UNAVAILABLE', "External service unavailable: {$service}"); + $this->assertExceptionStructure( + $exception, + 'SERVICE_UNAVAILABLE', + "External service unavailable: {$service}", + 1702 + ); } public function testInvalidResponse(): void { $service = 'WeatherAPI'; $exception = ExternalServiceException::invalidResponse($service); - $this->assertExceptionStructure($exception, 'INVALID_RESPONSE', "Invalid response from external service: {$service}"); + $this->assertExceptionStructure( + $exception, + 'INVALID_RESPONSE', + "Invalid response from external service: {$service}", + 1703 + ); } } diff --git a/tests/File/FileExceptionTest.php b/tests/File/FileExceptionTest.php index 92f45ad..86178e2 100644 --- a/tests/File/FileExceptionTest.php +++ b/tests/File/FileExceptionTest.php @@ -13,27 +13,27 @@ public function testNotFound(): void { $path = '/path/to/file.txt'; $exception = FileException::notFound($path); - $this->assertExceptionStructure($exception, 'FILE_NOT_FOUND', "File not found: {$path}"); + $this->assertExceptionStructure($exception, 'FILE_NOT_FOUND', "File not found: {$path}", 1801); } public function testPermissionDenied(): void { $path = '/path/to/file.txt'; $exception = FileException::permissionDenied($path); - $this->assertExceptionStructure($exception, 'PERMISSION_DENIED', "Permission denied for file: {$path}"); + $this->assertExceptionStructure($exception, 'PERMISSION_DENIED', "Permission denied for file: {$path}", 1802); } public function testUnreadable(): void { $path = '/path/to/file.txt'; $exception = FileException::unreadable($path); - $this->assertExceptionStructure($exception, 'FILE_UNREADABLE', "File is not readable: {$path}"); + $this->assertExceptionStructure($exception, 'FILE_UNREADABLE', "File is not readable: {$path}", 1803); } public function testUploadFailed(): void { $filename = 'upload.txt'; $exception = FileException::uploadFailed($filename); - $this->assertExceptionStructure($exception, 'UPLOAD_FAILED', "Failed to upload file: {$filename}"); + $this->assertExceptionStructure($exception, 'UPLOAD_FAILED', "Failed to upload file: {$filename}", 1804); } } diff --git a/tests/Input/InputExceptionTest.php b/tests/Input/InputExceptionTest.php index a9d156b..7ad2498 100644 --- a/tests/Input/InputExceptionTest.php +++ b/tests/Input/InputExceptionTest.php @@ -13,14 +13,24 @@ public function testInvalidFormat(): void { $field = 'email'; $exception = InputException::invalidFormat($field); - $this->assertExceptionStructure($exception, 'INVALID_FORMAT', "Invalid format for field: {$field}"); + $this->assertExceptionStructure( + $exception, + 'INVALID_FORMAT', + "Invalid format for field: {$field}", + 1901 + ); } public function testMissingRequired(): void { $field = 'username'; $exception = InputException::missingRequired($field); - $this->assertExceptionStructure($exception, 'MISSING_REQUIRED', "Missing required field: {$field}"); + $this->assertExceptionStructure( + $exception, + 'MISSING_REQUIRED', + "Missing required field: {$field}", + 1902 + ); } public function testExceedsMaxLength(): void @@ -28,6 +38,11 @@ public function testExceedsMaxLength(): void $field = 'description'; $maxLength = 255; $exception = InputException::exceedsMaxLength($field, $maxLength); - $this->assertExceptionStructure($exception, 'EXCEEDS_MAX_LENGTH', "Field '{$field}' exceeds maximum length of {$maxLength}"); + $this->assertExceptionStructure( + $exception, + 'EXCEEDS_MAX_LENGTH', + "Field '{$field}' exceeds maximum length of {$maxLength}", + 1903 + ); } } diff --git a/tests/Localization/LocalizationExceptionTest.php b/tests/Localization/LocalizationExceptionTest.php index 3f80f70..207e44c 100644 --- a/tests/Localization/LocalizationExceptionTest.php +++ b/tests/Localization/LocalizationExceptionTest.php @@ -14,13 +14,23 @@ public function testMissingTranslation(): void $key = 'welcome_message'; $locale = 'fr_FR'; $exception = LocalizationException::missingTranslation($key, $locale); - $this->assertExceptionStructure($exception, 'MISSING_TRANSLATION', "Missing translation for key '{$key}' in locale '{$locale}'"); + $this->assertExceptionStructure( + $exception, + 'MISSING_TRANSLATION', + "Missing translation for key '{$key}' in locale '{$locale}'", + 2001 + ); } public function testInvalidLocale(): void { $locale = 'invalid_locale'; $exception = LocalizationException::invalidLocale($locale); - $this->assertExceptionStructure($exception, 'INVALID_LOCALE', "Invalid locale: {$locale}"); + $this->assertExceptionStructure( + $exception, + 'INVALID_LOCALE', + "Invalid locale: {$locale}", + 2002 + ); } } diff --git a/tests/Middleware/MiddlewareExceptionTest.php b/tests/Middleware/MiddlewareExceptionTest.php index 67d03f5..e58d423 100644 --- a/tests/Middleware/MiddlewareExceptionTest.php +++ b/tests/Middleware/MiddlewareExceptionTest.php @@ -13,13 +13,23 @@ public function testInvalidMiddleware(): void { $middlewareName = 'AuthMiddleware'; $exception = MiddlewareException::invalidMiddleware($middlewareName); - $this->assertExceptionStructure($exception, 'INVALID_MIDDLEWARE', "Invalid middleware: {$middlewareName}"); + $this->assertExceptionStructure( + $exception, + 'INVALID_MIDDLEWARE', + "Invalid middleware: {$middlewareName}", + 2101 + ); } public function testMiddlewareExecutionFailed(): void { $middlewareName = 'RateLimitMiddleware'; $exception = MiddlewareException::middlewareExecutionFailed($middlewareName); - $this->assertExceptionStructure($exception, 'MIDDLEWARE_EXECUTION_FAILED', "Execution failed for middleware: {$middlewareName}"); + $this->assertExceptionStructure( + $exception, + 'MIDDLEWARE_EXECUTION_FAILED', + "Execution failed for middleware: {$middlewareName}", + 2102 + ); } } diff --git a/tests/Network/HttpExceptionTest.php b/tests/Network/HttpExceptionTest.php index 19146be..0df11fd 100644 --- a/tests/Network/HttpExceptionTest.php +++ b/tests/Network/HttpExceptionTest.php @@ -13,13 +13,23 @@ public function testClientError(): void { $statusCode = 404; $exception = HttpException::clientError($statusCode); - $this->assertExceptionStructure($exception, 'HTTP_CLIENT_ERROR', "HTTP client error with status code: {$statusCode}"); + $this->assertExceptionStructure( + $exception, + 'HTTP_CLIENT_ERROR', + "HTTP client error with status code: {$statusCode}", + 2203 + ); } public function testServerError(): void { $statusCode = 500; $exception = HttpException::serverError($statusCode); - $this->assertExceptionStructure($exception, 'HTTP_SERVER_ERROR', "HTTP server error with status code: {$statusCode}"); + $this->assertExceptionStructure( + $exception, + 'HTTP_SERVER_ERROR', + "HTTP server error with status code: {$statusCode}", + 2204 + ); } } diff --git a/tests/Network/NetworkExceptionTest.php b/tests/Network/NetworkExceptionTest.php index 9548805..e5acc0c 100644 --- a/tests/Network/NetworkExceptionTest.php +++ b/tests/Network/NetworkExceptionTest.php @@ -13,13 +13,23 @@ public function testConnectionFailed(): void { $host = 'example.com'; $exception = NetworkException::connectionFailed($host); - $this->assertExceptionStructure($exception, 'CONNECTION_FAILED', "Failed to connect to host: {$host}"); + $this->assertExceptionStructure( + $exception, + 'CONNECTION_FAILED', + "Failed to connect to host: {$host}", + 2201 + ); } public function testTimeout(): void { $operation = 'HTTP request'; $exception = NetworkException::timeout($operation); - $this->assertExceptionStructure($exception, 'TIMEOUT', "Network operation timed out: {$operation}"); + $this->assertExceptionStructure( + $exception, + 'TIMEOUT', + "Network operation timed out: {$operation}", + 2202 + ); } } diff --git a/tests/Queue/QueueExceptionTest.php b/tests/Queue/QueueExceptionTest.php index 9080088..d244833 100644 --- a/tests/Queue/QueueExceptionTest.php +++ b/tests/Queue/QueueExceptionTest.php @@ -13,20 +13,35 @@ public function testJobPushFailed(): void { $jobClass = 'App\Jobs\SendEmailJob'; $exception = QueueException::jobPushFailed($jobClass); - $this->assertExceptionStructure($exception, 'JOB_PUSH_FAILED', "Failed to push job to queue: {$jobClass}"); + $this->assertExceptionStructure( + $exception, + 'JOB_PUSH_FAILED', + "Failed to push job to queue: {$jobClass}", + 2301 + ); } public function testJobProcessingFailed(): void { $jobId = 'job_123456'; $exception = QueueException::jobProcessingFailed($jobId); - $this->assertExceptionStructure($exception, 'JOB_PROCESSING_FAILED', "Failed to process job: {$jobId}"); + $this->assertExceptionStructure( + $exception, + 'JOB_PROCESSING_FAILED', + "Failed to process job: {$jobId}", + 2302 + ); } public function testQueueConnectionFailed(): void { $connection = 'redis'; $exception = QueueException::queueConnectionFailed($connection); - $this->assertExceptionStructure($exception, 'QUEUE_CONNECTION_FAILED', "Failed to connect to queue: {$connection}"); + $this->assertExceptionStructure( + $exception, + 'QUEUE_CONNECTION_FAILED', + "Failed to connect to queue: {$connection}", + 2303 + ); } } diff --git a/tests/Routing/RoutingExceptionTest.php b/tests/Routing/RoutingExceptionTest.php index 2bc2fb4..00025a9 100644 --- a/tests/Routing/RoutingExceptionTest.php +++ b/tests/Routing/RoutingExceptionTest.php @@ -13,7 +13,12 @@ public function testRouteNotFound(): void { $uri = '/unknown/path'; $exception = RoutingException::routeNotFound($uri); - $this->assertExceptionStructure($exception, 'ROUTE_NOT_FOUND', "Route not found for URI: {$uri}"); + $this->assertExceptionStructure( + $exception, + 'ROUTE_NOT_FOUND', + "Route not found for URI: {$uri}", + 2401 + ); } public function testMethodNotAllowed(): void @@ -21,6 +26,11 @@ public function testMethodNotAllowed(): void $method = 'POST'; $uri = '/get-only-path'; $exception = RoutingException::methodNotAllowed($method, $uri); - $this->assertExceptionStructure($exception, 'METHOD_NOT_ALLOWED', "Method {$method} not allowed for URI: {$uri}"); + $this->assertExceptionStructure( + $exception, + 'METHOD_NOT_ALLOWED', + "Method {$method} not allowed for URI: {$uri}", + 2402 + ); } } diff --git a/tests/Runtime/RuntimeExceptionTest.php b/tests/Runtime/RuntimeExceptionTest.php index 90e0300..c6ce5d0 100644 --- a/tests/Runtime/RuntimeExceptionTest.php +++ b/tests/Runtime/RuntimeExceptionTest.php @@ -13,19 +13,34 @@ public function testUnexpectedValue(): void { $details = 'Unexpected null value'; $exception = RuntimeException::unexpectedValue($details); - $this->assertExceptionStructure($exception, 'UNEXPECTED_VALUE', "Unexpected value: {$details}"); + $this->assertExceptionStructure( + $exception, + 'UNEXPECTED_VALUE', + "Unexpected value: {$details}", + 2501 + ); } public function testOutOfMemory(): void { $exception = RuntimeException::outOfMemory(); - $this->assertExceptionStructure($exception, 'OUT_OF_MEMORY', 'Out of memory error'); + $this->assertExceptionStructure( + $exception, + 'OUT_OF_MEMORY', + 'Out of memory error', + 2502 + ); } public function testClassNotFound(): void { $className = 'App\NonExistentClass'; $exception = RuntimeException::classNotFound($className); - $this->assertExceptionStructure($exception, 'CLASS_NOT_FOUND', "Class not found: {$className}"); + $this->assertExceptionStructure( + $exception, + 'CLASS_NOT_FOUND', + "Class not found: {$className}", + 2503 + ); } } diff --git a/tests/Security/EncryptionExceptionTest.php b/tests/Security/EncryptionExceptionTest.php index 08358f4..bfd8135 100644 --- a/tests/Security/EncryptionExceptionTest.php +++ b/tests/Security/EncryptionExceptionTest.php @@ -12,12 +12,22 @@ final class EncryptionExceptionTest extends AbstractExceptionTest public function testEncryptionFailed(): void { $exception = EncryptionException::encryptionFailed(); - $this->assertExceptionStructure($exception, 'ENCRYPTION_FAILED', 'Encryption operation failed'); + $this->assertExceptionStructure( + $exception, + 'ENCRYPTION_FAILED', + 'Encryption operation failed', + 2601 + ); } public function testDecryptionFailed(): void { $exception = EncryptionException::decryptionFailed(); - $this->assertExceptionStructure($exception, 'DECRYPTION_FAILED', 'Decryption operation failed'); + $this->assertExceptionStructure( + $exception, + 'DECRYPTION_FAILED', + 'Decryption operation failed', + 2602 + ); } } diff --git a/tests/Security/SecurityExceptionTest.php b/tests/Security/SecurityExceptionTest.php index 9fd025d..d99c750 100644 --- a/tests/Security/SecurityExceptionTest.php +++ b/tests/Security/SecurityExceptionTest.php @@ -12,18 +12,33 @@ final class SecurityExceptionTest extends AbstractExceptionTest public function testUnauthorized(): void { $exception = SecurityException::unauthorized(); - $this->assertExceptionStructure($exception, 'UNAUTHORIZED', 'Unauthorized access'); + $this->assertExceptionStructure( + $exception, + 'UNAUTHORIZED', + 'Unauthorized access', + 2701 + ); } public function testCsrfTokenMismatch(): void { $exception = SecurityException::csrfTokenMismatch(); - $this->assertExceptionStructure($exception, 'CSRF_TOKEN_MISMATCH', 'CSRF token mismatch'); + $this->assertExceptionStructure( + $exception, + 'CSRF_TOKEN_MISMATCH', + 'CSRF token mismatch', + 2702 + ); } public function testRateLimitExceeded(): void { $exception = SecurityException::rateLimitExceeded(); - $this->assertExceptionStructure($exception, 'RATE_LIMIT_EXCEEDED', 'Rate limit exceeded'); + $this->assertExceptionStructure( + $exception, + 'RATE_LIMIT_EXCEEDED', + 'Rate limit exceeded', + 2703 + ); } } diff --git a/tests/Session/SessionExceptionTest.php b/tests/Session/SessionExceptionTest.php index ea32e3a..96635c4 100644 --- a/tests/Session/SessionExceptionTest.php +++ b/tests/Session/SessionExceptionTest.php @@ -12,12 +12,22 @@ final class SessionExceptionTest extends AbstractExceptionTest public function testSessionStartFailed(): void { $exception = SessionException::sessionStartFailed(); - $this->assertExceptionStructure($exception, 'SESSION_START_FAILED', 'Failed to start session'); + $this->assertExceptionStructure( + $exception, + 'SESSION_START_FAILED', + 'Failed to start session', + 2801 + ); } public function testInvalidSessionId(): void { $exception = SessionException::invalidSessionId(); - $this->assertExceptionStructure($exception, 'INVALID_SESSION_ID', 'Invalid session ID'); + $this->assertExceptionStructure( + $exception, + 'INVALID_SESSION_ID', + 'Invalid session ID', + 2802 + ); } } diff --git a/tests/System/SystemExceptionTest.php b/tests/System/SystemExceptionTest.php index 5be4b35..36b318d 100644 --- a/tests/System/SystemExceptionTest.php +++ b/tests/System/SystemExceptionTest.php @@ -13,20 +13,35 @@ public function testResourceUnavailable(): void { $resource = 'database'; $exception = SystemException::resourceUnavailable($resource); - $this->assertExceptionStructure($exception, 'RESOURCE_UNAVAILABLE', "System resource unavailable: {$resource}"); + $this->assertExceptionStructure( + $exception, + 'RESOURCE_UNAVAILABLE', + "System resource unavailable: {$resource}", + 2901 + ); } public function testEnvironmentError(): void { $details = 'Missing .env file'; $exception = SystemException::environmentError($details); - $this->assertExceptionStructure($exception, 'ENVIRONMENT_ERROR', "Environment error: {$details}"); + $this->assertExceptionStructure( + $exception, + 'ENVIRONMENT_ERROR', + "Environment error: {$details}", + 2902 + ); } public function testExtensionNotLoaded(): void { $extension = 'gd'; $exception = SystemException::extensionNotLoaded($extension); - $this->assertExceptionStructure($exception, 'EXTENSION_NOT_LOADED', "PHP extension not loaded: {$extension}"); + $this->assertExceptionStructure( + $exception, + 'EXTENSION_NOT_LOADED', + "PHP extension not loaded: {$extension}", + 2903 + ); } } diff --git a/tests/Template/TemplateExceptionTest.php b/tests/Template/TemplateExceptionTest.php index f4241be..24de2c6 100644 --- a/tests/Template/TemplateExceptionTest.php +++ b/tests/Template/TemplateExceptionTest.php @@ -13,13 +13,23 @@ public function testTemplateNotFound(): void { $templateName = 'user/profile.html.twig'; $exception = TemplateException::templateNotFound($templateName); - $this->assertExceptionStructure($exception, 'TEMPLATE_NOT_FOUND', "Template not found: {$templateName}"); + $this->assertExceptionStructure( + $exception, + 'TEMPLATE_NOT_FOUND', + "Template not found: {$templateName}", + 3001 + ); } public function testRenderingFailed(): void { $templateName = 'email/welcome.html.twig'; $exception = TemplateException::renderingFailed($templateName); - $this->assertExceptionStructure($exception, 'RENDERING_FAILED', "Failed to render template: {$templateName}"); + $this->assertExceptionStructure( + $exception, + 'RENDERING_FAILED', + "Failed to render template: {$templateName}", + 3002 + ); } } diff --git a/tests/Validation/RuleViolationExceptionTest.php b/tests/Validation/RuleViolationExceptionTest.php index 97b3352..1f9a4aa 100644 --- a/tests/Validation/RuleViolationExceptionTest.php +++ b/tests/Validation/RuleViolationExceptionTest.php @@ -4,8 +4,8 @@ namespace KaririCode\Exception\Tests\Validation; -use KaririCode\Exception\Validation\RuleViolationException; use KaririCode\Exception\Tests\AbstractExceptionTest; +use KaririCode\Exception\Validation\RuleViolationException; final class RuleViolationExceptionTest extends AbstractExceptionTest { @@ -14,6 +14,11 @@ public function testCreate(): void $rule = 'email'; $field = 'user_email'; $exception = RuleViolationException::create($rule, $field); - $this->assertExceptionStructure($exception, 'RULE_VIOLATION', "Validation rule '{$rule}' violated for field '{$field}'"); + $this->assertExceptionStructure( + $exception, + 'RULE_VIOLATION', + "Validation rule '{$rule}' violated for field '{$field}'", + 3102 + ); } } diff --git a/tests/Validation/ValidationExceptionTest.php b/tests/Validation/ValidationExceptionTest.php index a63cd58..828b729 100644 --- a/tests/Validation/ValidationExceptionTest.php +++ b/tests/Validation/ValidationExceptionTest.php @@ -4,22 +4,31 @@ namespace KaririCode\Exception\Tests\Validation; -use KaririCode\Exception\Validation\ValidationException; -use KaririCode\Exception\Tests\AbstractExceptionTest; use KaririCode\Exception\ExceptionMessage; +use KaririCode\Exception\Tests\AbstractExceptionTest; +use KaririCode\Exception\Validation\ValidationException; final class ValidationExceptionTest extends AbstractExceptionTest { public function testCreate(): void { $exception = ValidationException::create(); - $this->assertExceptionStructure($exception, 'VALIDATION_FAILED', 'Validation failed'); + $this->assertExceptionStructure( + $exception, + 'VALIDATION_FAILED', + 'Validation failed', + 3101 + ); } public function testAddValidationError(): void { $exception = ValidationException::create(); - $errorMessage = new ExceptionMessage('FIELD_ERROR', 'Field has an error'); + $errorMessage = new ExceptionMessage( + 3103, + 'FIELD_ERROR', + 'Field has an error' + ); $exception->addError('field_name', $errorMessage); $errors = $exception->getValidationErrors(); From fd75dbd026833ea2959de76116821c5974d1b75e Mon Sep 17 00:00:00 2001 From: Walmir Silva Date: Wed, 16 Oct 2024 18:26:55 -0300 Subject: [PATCH 7/7] feat(docs): add README files in English and Portuguese for Exception component - Added README.md (English version) with detailed instructions for using the Exception component - Added README.pt-br.md (Portuguese version) with equivalent content for Brazilian developers --- README.md | 282 +++++++++++++++++- README.pt-br.md | 651 +++++++++++++++++++++++++++++++++++++++++- createDirectory.php | 68 ----- tests/application.php | 5 - 4 files changed, 917 insertions(+), 89 deletions(-) delete mode 100644 createDirectory.php delete mode 100644 tests/application.php diff --git a/README.md b/README.md index 5cfc13b..21dac99 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,284 @@ -# KaririCode Framework: Sanitizer Component +# KaririCode Framework: Exception Component [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![pt-br](https://img.shields.io/badge/lang-pt--br-green.svg)](README.pt-br.md) ![PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![PHPUnit](https://img.shields.io/badge/PHPUnit-3776AB?style=for-the-badge&logo=php&logoColor=white) +A comprehensive and flexible exception handling component for PHP, part of the KaririCode Framework. It provides a structured approach to error management, enhancing the robustness and maintainability of your applications. + +## Table of Contents + +- [Features](#features) +- [Installation](#installation) +- [Usage](#usage) + - [Basic Usage](#basic-usage) + - [Advanced Usage](#advanced-usage) +- [Error Code Range Table](#error-code-range-table) +- [Available Exception Types](#available-exception-types) +- [Integration with Other KaririCode Components](#integration-with-other-kariricode-components) +- [Development and Testing](#development-and-testing) +- [License](#license) +- [Support and Community](#support-and-community) + +## Features + +- Hierarchical exception structure for better error categorization +- Context-aware exceptions for richer error information +- Static factory methods for easy exception creation +- Integration with KaririCode's error handling and logging systems +- Extensible architecture allowing custom exception types +- Comprehensive set of pre-defined exception types for common scenarios + +## Installation + +You can install the Exception component via Composer: + +```bash +composer require kariricode/exception +``` + +### Requirements + +- PHP 8.1 or higher +- Composer + +## Usage + +### Basic Usage + +#### Using Pre-defined Exceptions in Your Code + +The KaririCode Exception component provides a variety of pre-defined exceptions that you can use to handle common error scenarios in a professional and structured manner. Below is an example of how to use these exceptions in an object-oriented context. + +```php +getAttribute('userId'); + + $userData = $this->userService->getUserData($userId); + return $this->responseBuilder($response) + ->setData($userData) + ->setHeader('Content-Type', 'application/json') + ->setStatus(200) + ->build(); + } +} + +// UserService.php +namespace YourApp\Service; + +use YourApp\Repository\UserRepository; +use KaririCode\Contract\Log\Logger; + +class UserService +{ + private UserRepository $userRepository; + private Logger $logger; + + public function __construct(UserRepository $userRepository, Logger $logger) + { + $this->userRepository = $userRepository; + $this->logger = $logger; + } + + public function getUserData(int $userId): array + { + return $this->userRepository->findUserById($userId); + } +} + +// UserRepository.php +namespace YourApp\Repository; + +use KaririCode\Contract\Database\EntityManager; +use KaririCode\Exception\Database\DatabaseException; + +class UserRepository +{ + private EntityManager $entityManager; + + public function __construct(EntityManager $entityManager) + { + $this->entityManager = $entityManager; + } + + public function findUserById(int $userId): array + { + $sql = 'SELECT * FROM users WHERE id = ?'; + $userData = $this->entityManager->query($sql, [$userId]); + + if ($userData === false) { + throw DatabaseException::queryError($sql, $this->entityManager->getLastError()); + } + + return $userData; + } +} + +``` + +### Advanced Usage + +Create custom exceptions by extending the base classes: + +```php +orderRepository->getUserOrderLimit($userId); + + if ($totalAmount > $userOrderLimit) { + $this->logger->warning('Order exceeds user limit', [ + 'userId' => $userId, + 'orderAmount' => $totalAmount, + 'userLimit' => $userOrderLimit, + ]); + + throw OrderException::orderLimitExceeded($totalAmount, $userOrderLimit); + } + + $this->orderRepository->createOrder($userId, $items, $totalAmount); + + } +} +``` + +## Error Code Range Table + +Here is a proposed table for the **error code ranges**. Each range is assigned to a group of related errors, allowing better organization and identification of errors in the system. + +### Error Code Range Table + +| Range | Error Group | Description | +| --------------- | --------------------------- | ----------------------------------------------------- | +| **1000 - 1099** | **Authentication Errors** | Errors related to authentication and login | +| **1100 - 1199** | **Authorization Errors** | Errors related to permissions and roles | +| **1200 - 1299** | **Cache Errors** | Errors related to cache operations | +| **1300 - 1399** | **Configuration Errors** | Errors related to configuration settings | +| **1400 - 1499** | **Container Errors** | Errors related to dependency injection and services | +| **1500 - 1599** | **Database Errors** | Errors related to database connections, queries, etc. | +| **1600 - 1699** | **Event Errors** | Errors related to event handling and dispatching | +| **1700 - 1799** | **External Service Errors** | Errors related to external API calls and services | +| **1800 - 1899** | **File System Errors** | Errors related to file operations (reading, writing) | +| **1900 - 1999** | **Input/Validation Errors** | Errors related to invalid input or validation | +| **2000 - 2099** | **Localization Errors** | Errors related to localization and translations | +| **2100 - 2199** | **Middleware Errors** | Errors related to middleware processing | +| **2200 - 2299** | **Network Errors** | Errors related to network operations | +| **2300 - 2399** | **Queue Errors** | Errors related to queuing systems | +| **2400 - 2499** | **Routing Errors** | Errors related to routing and HTTP methods | +| **2500 - 2599** | **Runtime Errors** | General runtime errors | +| **2600 - 2699** | **Encryption Errors** | Errors related to encryption and decryption | +| **2700 - 2799** | **Security Errors** | Errors related to security, access control, etc. | +| **2800 - 2899** | **Session Errors** | Errors related to session handling | +| **2900 - 2999** | **System Errors** | Errors related to system resources and environment | +| **3000 - 3099** | **Template Errors** | Errors related to template rendering and loading | +| **3100 - 3199** | **Validation Errors** | Errors related to data validation | +| **4000 - 4099** | **Business Logic Errors** | Custom errors for business logic violations | + +### Explanation of Each Range: + +1. **1000 - 1099: Authentication Errors** + + - Errors related to user authentication, such as invalid credentials, locked accounts, or missing two-factor authentication. + +2. **1100 - 1199: Authorization Errors** + + - Errors related to insufficient permissions or missing roles during authorization processes. + +3. **... (Same as previous ranges)** + +4. **3100 - 3199: Validation Errors** + + - Errors related to data validation. + +5. **4000 - 4099: Business Logic Errors** + - Custom error codes for business logic violations specific to your application. + +This structure allows you to easily categorize and expand error codes in the future, keeping the error-handling system organized. + +## Available Exception Types + +Each exception type is designed to handle specific error scenarios. For detailed information on each exception type, please refer to the [documentation](https://kariricode.org/docs/exception). + +## Integration with Other KaririCode Components + +The Exception component is designed to work seamlessly with other KaririCode components: + +- **KaririCode\Logger**: For advanced error logging and reporting. +- **KaririCode\Http**: For handling HTTP-related exceptions. +- **KaririCode\Database**: For database-specific exceptions. + +## Development and Testing + +For development and testing purposes, this package uses Docker and Docker Compose to ensure consistency across different environments. A Makefile is provided for convenience. + ### Prerequisites - Docker @@ -32,6 +307,7 @@ ``` 4. Install dependencies: + ```bash make composer-install ``` @@ -59,10 +335,10 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Support and Community -- **Documentation**: [https://kariricode.org/docs/sanitizer](https://kariricode.org/docs/sanitizer) +- **Documentation**: [https://kariricode.org/docs/exception](https://kariricode.org/docs/exception) - **Issue Tracker**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-exception/issues) - **Community**: [KaririCode Club Community](https://kariricode.club) --- -Built with ❤️ by the KaririCode team. Empowering developers to create more secure and robust PHP applications. +Built with ❤️ by the KaririCode team. Empowering developers to handle errors effectively and build more resilient PHP applications. diff --git a/README.pt-br.md b/README.pt-br.md index 82a1d42..f5bfd30 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -1,14 +1,638 @@ -# Framework KaririCode: Componente Sanitizer +# KaririCode Framework: Exception Component [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![pt-br](https://img.shields.io/badge/lang-pt--br-green.svg)](README.pt-br.md) ![PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![PHPUnit](https://img.shields.io/badge/PHPUnit-3776AB?style=for-the-badge&logo=php&logoColor=white) +Um componente abrangente e flexível de tratamento de exceções para PHP, parte do KaririCode Framework. Ele fornece uma abordagem estruturada para o gerenciamento de erros, melhorando a robustez e a manutenção das suas aplicações. + +## Índice + +- [Funcionalidades](#funcionalidades) +- [Instalação](#instalação) +- [Uso](#uso) + - [Uso Básico](#uso-básico) + - [Uso Avançado](#uso-avançado) +- [Tabela de Faixas de Código de Erro](#tabela-de-faixas-de-código-de-erro) +- [Tipos de Exceção Disponíveis](#tipos-de-exceção-disponíveis) +- [Integração com Outros Componentes do KaririCode](#integração-com-outros-componentes-do-kariricode) +- [Desenvolvimento e Testes](#desenvolvimento-e-testes) +- [Licença](#licença) +- [Suporte e Comunidade](#suporte-e-comunidade) + +## Funcionalidades + +- Estrutura hierárquica de exceções para melhor categorização de erros +- Exceções conscientes de contexto para informações de erro mais ricas +- Métodos de fábrica estáticos para fácil criação de exceções +- Integração com os sistemas de tratamento de erros e logs do KaririCode +- Arquitetura extensível permitindo tipos de exceção personalizados +- Conjunto abrangente de tipos de exceção pré-definidos para cenários comuns + +## Instalação + +Você pode instalar o componente de Exceção via Composer: + +```bash +composer require kariricode/exception +``` + +### Requisitos + +- PHP 8.1 ou superior +- Composer + +## Uso + +### Uso Básico + +#### Usando Exceções Pré-definidas no Seu Código + +O componente KaririCode Exception oferece uma variedade de exceções pré-definidas que você pode usar para lidar com cenários comuns de erro de maneira profissional e estruturada. Abaixo está um exemplo de como usar essas exceções em um contexto orientado a objetos. + +```php +getAttribute('userId'); + + $userData = $this->userService->getUserData($userId); + return $this->responseBuilder($response) + ->setData($userData) + ->setHeader('Content-Type', 'application/json') + ->setStatus(200) + ->build(); + } +} + +// UserService.php +namespace YourApp\Service; + +use YourApp\Repository\UserRepository; +use KaririCode\Contract\Log\Logger; + +class UserService +{ + private UserRepository $userRepository; + private Logger $logger; + + public function __construct(UserRepository $userRepository, Logger $logger) + { + $this->userRepository = $userRepository; + $this->logger = $logger; + } + + public function getUserData(int $userId): array + { + return $this->userRepository->findUserById($userId); + } +} + +// UserRepository.php +namespace YourApp\Repository; + +use KaririCode\Contract\Database\EntityManager; +use KaririCode\Exception\Database\DatabaseException; + +class UserRepository +{ + private EntityManager $entityManager; + + public function __construct(EntityManager $entityManager) + { + $this->entityManager = $entityManager; + } + + public function findUserById(int $userId): array + { + $sql = 'SELECT * FROM users WHERE id = ?'; + $userData = $this->entityManager->query($sql, [$userId]); + + if ($userData === false) { + throw DatabaseException::queryError($sql, $this->entityManager->getLastError()); + } + + return $userData; + } +} + +``` + +### Uso Avançado + +Crie exceções personalizadas estendendo as classes base: + +```php +orderRepository->getUserOrderLimit($userId); + + if ($totalAmount > $userOrderLimit) { + $this->logger->warning('Pedido excede o limite do usuário', [ + 'userId' => $userId, + 'orderAmount' => $totalAmount, + 'userLimit' => $userOrderLimit, + ]); + + throw OrderException::orderLimitExceeded($totalAmount, $userOrderLimit); + } + + $this->orderRepository->createOrder($userId, $items, $totalAmount); + + } +} +``` + +## Tabela de Faixas de Código de Erro + +Aqui está uma tabela proposta para as **faixas de código de erro**. Cada faixa é atribuída a um grupo de erros relacionados, permitindo melhor organização e identificação de erros no sistema. + +### Tabela de Faixas de Código de Erro + +| Faixa | Grupo de Erro | Descrição | +| --------------- | -------------------------------- | ------------------------------------------------------- | +| **1000 - 1099** | **Erros de Autenticação** | Erros relacionados à autenticação e login | +| **1100 - 1199** | **Erros de Autorização** | Erros relacionados a permissões e funções | +| **1200 - 1299** | **Erros de Cache** | Erros relacionados a operações de cache | +| **1300 - 1399** | **Erros de Configuração** | Erros relacionados a configurações | +| **1400 - 1499** | **Erros de Container** | Erros relacionados à injeção de dependências e serviços | +| **1500 - 1599** | **Erros de Banco de Dados** | Erros relacionados a conexões, consultas, etc. | +| **1600 - 1699** | **Erros de Evento** | Erros relacionados ao manuseio e despacho de eventos | +| **1700 - 1799** | **Erros de Serviços Externos** | Erros relacionados a chamadas e serviços externos | +| **1800 - 1899** | **Erros de Sistema de Arquivos** | Erros relacionados a operações de arquivos | +| **1900 - 1999** | **Erros de Validação/Entrada** | Erros relacionados a validação ou entrada inválida | +| **2000 - 2099** | **Erros de Localização** | Erros relacionados à localização e traduções | +| **2100 - 2199** | **Erros de Middleware** | Erros relacionados ao processamento de middleware | +| **2200 - 2299** | **Erros de Rede** | Erros relacionados a operações de rede | +| **2300 - 2399** | **Erros de Fila** | Erros relacionados a sistemas de fila | +| **2400 - 2499** | **Erros de Roteamento** | Erros relacionados a roteamento e métodos HTTP | + +| **2500 - 2599** | **Erros de Tempo de Execução** | Erros gerais de tempo de execução | +| **2600 - 2699** | **Erros de Criptografia** | Erros relacionados a criptografia e descriptografia | +| **2700 - 2799** | **Erros de Segurança** | Erros relacionados à segurança e controle de acesso | +| **2800 - 2899** | **Erros de Sessão** | Erros relacionados ao gerenciamento de sessões | +| **2900 - 2999** | **Erros de Sistema** | Erros relacionados a recursos do sistema e ambiente | +| **3000 - 3099** | **Erros de Template** | Erros relacionados a renderização e carregamento de templates | +| **3100 - 3199** | **Erros de Validação** | Erros relacionados à validação de dados | +| **4000 - 4099** | **Erros de Lógica de Negócios** | Erros personalizados para violações de lógica de negócios | + +### Explicação de Cada Faixa: + +1. **1000 - 1099: Erros de Autenticação** + + - Erros relacionados à autenticação do usuário, como credenciais inválidas, contas bloqueadas ou autenticação de dois fatores ausente. + +2. **1100 - 1199: Erros de Autorização** + + - Erros relacionados a permissões insuficientes ou funções ausentes durante processos de autorização. + +3. **... (Mesma descrição das faixas anteriores)** + +4. **3100 - 3199: Erros de Validação** + + - Erros relacionados à validação de dados. + +5. **4000 - 4099: Erros de Lógica de Negócios** + - Códigos de erro personalizados para violações de lógica de negócios específicas da sua aplicação. + +Essa estrutura permite que você categorize e expanda facilmente os códigos de erro no futuro, mantendo o sistema de tratamento de erros organizado. + +## Tipos de Exceção Disponíveis + +Cada tipo de exceção é projetado para lidar com cenários específicos de erro. Para informações detalhadas sobre cada tipo de exceção, consulte a [documentação](https://kariricode.org/docs/exception). + +## Integração com Outros Componentes do KaririCode + +O componente de Exceção foi projetado para funcionar perfeitamente com outros componentes do KaririCode: + +- **KaririCode\Logger**: Para logs e relatórios de erros avançados. +- **KaririCode\Http**: Para tratamento de exceções relacionadas a HTTP. +- **KaririCode\Database**: Para exceções específicas de banco de dados. + +## Desenvolvimento e Testes + +Para fins de desenvolvimento e testes, este pacote utiliza Docker e Docker Compose para garantir consistência entre diferentes ambientes. Um Makefile é fornecido para conveniência. + +### Pré-requisitos + +- Docker +- Docker Compose +- Make (opcional, mas recomendado para facilitar a execução de comandos) + +### Configuração de Desenvolvimento + +1. Clone o repositório: + + ```bash + git clone https://github.com/KaririCode-Framework/kariricode-exception.git + cd kariricode-exception + ``` + +2. Configure o ambiente: + + ```bash + make setup-env + ``` + +3. Inicie os containers do Docker: + + ```bash + make up + ``` + +4. Instale as dependências: + + ```bash + make composer-install + ``` + +### Comandos Make Disponíveis + +- `make up`: Inicia todos os serviços em segundo plano +- `make down`: Para e remove todos os containers +- `make build`: Constrói as imagens Docker +- `make shell`: Acessa o shell do container PHP +- `make test`: Executa os testes +- `make coverage`: Executa a cobertura dos testes com formatação visual +- `make cs-fix`: Executa o PHP CS Fixer para corrigir o estilo do código +- `make quality`: Executa todos os comandos de qualidade (cs-check, test, security-check) + +Para uma lista completa de comandos disponíveis, execute: + +```bash +make help +``` + +## Licença + +Este projeto é licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para mais detalhes. + +## Suporte e Comunidade + +- **Documentação**: [https://kariricode.org/docs/exception](https://kariricode.org/docs/exception) +- **Rastreador de Problemas**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-exception/issues) +- **Comunidade**: [KaririCode Club Community](https://kariricode.club) + +--- + +Desenvolvido com ❤️ pela equipe KaririCode. Capacitando desenvolvedores a lidar com erros de forma eficaz e construir aplicações PHP mais resilientes.Aqui está o README traduzido para o português: + +--- + +# KaririCode Framework: Componente de Exceções + +[![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![pt-br](https://img.shields.io/badge/lang-pt--br-green.svg)](README.pt-br.md) + +![PHP](https://img.shields.io/badge/PHP-777BB4?style=for-the-badge&logo=php&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![PHPUnit](https://img.shields.io/badge/PHPUnit-3776AB?style=for-the-badge&logo=php&logoColor=white) + +Um componente abrangente e flexível de tratamento de exceções para PHP, parte do KaririCode Framework. Ele fornece uma abordagem estruturada para o gerenciamento de erros, melhorando a robustez e a manutenção das suas aplicações. + +## Índice + +- [Funcionalidades](#funcionalidades) +- [Instalação](#instalação) +- [Uso](#uso) + - [Uso Básico](#uso-básico) + - [Uso Avançado](#uso-avançado) +- [Tabela de Faixas de Código de Erro](#tabela-de-faixas-de-código-de-erro) +- [Tipos de Exceção Disponíveis](#tipos-de-exceção-disponíveis) +- [Integração com Outros Componentes do KaririCode](#integração-com-outros-componentes-do-kariricode) +- [Desenvolvimento e Testes](#desenvolvimento-e-testes) +- [Licença](#licença) +- [Suporte e Comunidade](#suporte-e-comunidade) + +## Funcionalidades + +- Estrutura hierárquica de exceções para melhor categorização de erros +- Exceções conscientes de contexto para informações de erro mais ricas +- Métodos de fábrica estáticos para fácil criação de exceções +- Integração com os sistemas de tratamento de erros e logs do KaririCode +- Arquitetura extensível permitindo tipos de exceção personalizados +- Conjunto abrangente de tipos de exceção pré-definidos para cenários comuns + +## Instalação + +Você pode instalar o componente de Exceção via Composer: + +```bash +composer require kariricode/exception +``` + +### Requisitos + +- PHP 8.1 ou superior +- Composer + +## Uso + +### Uso Básico + +#### Usando Exceções Pré-definidas no Seu Código + +O componente KaririCode Exception oferece uma variedade de exceções pré-definidas que você pode usar para lidar com cenários comuns de erro de maneira profissional e estruturada. Abaixo está um exemplo de como usar essas exceções em um contexto orientado a objetos. + +```php +getAttribute('userId'); + + $userData = $this->userService->getUserData($userId); + return $this->responseBuilder($response) + ->setData($userData) + ->setHeader('Content-Type', 'application/json') + ->setStatus(200) + ->build(); + } +} + +// UserService.php +namespace YourApp\Service; + +use YourApp\Repository\UserRepository; +use KaririCode\Contract\Log\Logger; + +class UserService +{ + private UserRepository $userRepository; + private Logger $logger; + + public function __construct(UserRepository $userRepository, Logger $logger) + { + $this->userRepository = $userRepository; + $this->logger = $logger; + } + + public function getUserData(int $userId): array + { + return $this->userRepository->findUserById($userId); + } +} + +// UserRepository.php +namespace YourApp\Repository; + +use KaririCode\Contract\Database\EntityManager; +use KaririCode\Exception\Database\DatabaseException; + +class UserRepository +{ + private EntityManager $entityManager; + + public function __construct(EntityManager $entityManager) + { + $this->entityManager = $entityManager; + } + + public function findUserById(int $userId): array + { + $sql = 'SELECT * FROM users WHERE id = ?'; + $userData = $this->entityManager->query($sql, [$userId]); + + if ($userData === false) { + throw DatabaseException::queryError($sql, $this->entityManager->getLastError()); + } + + return $userData; + } +} + +``` + +### Uso Avançado + +Crie exceções personalizadas estendendo as classes base: + +```php +orderRepository->getUserOrderLimit($userId); + + if ($totalAmount > $userOrderLimit) { + $this->logger->warning('Pedido excede o limite do usuário', [ + 'userId' => $userId, + 'orderAmount' => $totalAmount, + 'userLimit' => $userOrderLimit, + ]); + + throw OrderException::orderLimitExceeded($totalAmount, $userOrderLimit); + } + + $this->orderRepository->createOrder($userId, $items, $totalAmount); + + } +} +``` + +## Tabela de Faixas de Código de Erro + +Aqui está uma tabela proposta para as **faixas de código de erro**. Cada faixa é atribuída a um grupo de erros relacionados, permitindo melhor organização e identificação de erros no sistema. + +### Tabela de Faixas de Código de Erro + +| Faixa | Grupo de Erro | Descrição | +| --------------- | -------------------------------- | ------------------------------------------------------- | +| **1000 - 1099** | **Erros de Autenticação** | Erros relacionados à autenticação e login | +| **1100 - 1199** | **Erros de Autorização** | Erros relacionados a permissões e funções | +| **1200 - 1299** | **Erros de Cache** | Erros relacionados a operações de cache | +| **1300 - 1399** | **Erros de Configuração** | Erros relacionados a configurações | +| **1400 - 1499** | **Erros de Container** | Erros relacionados à injeção de dependências e serviços | +| **1500 - 1599** | **Erros de Banco de Dados** | Erros relacionados a conexões, consultas, etc. | +| **1600 - 1699** | **Erros de Evento** | Erros relacionados ao manuseio e despacho de eventos | +| **1700 - 1799** | **Erros de Serviços Externos** | Erros relacionados a chamadas e serviços externos | +| **1800 - 1899** | **Erros de Sistema de Arquivos** | Erros relacionados a operações de arquivos | +| **1900 - 1999** | **Erros de Validação/Entrada** | Erros relacionados a validação ou entrada inválida | +| **2000 - 2099** | **Erros de Localização** | Erros relacionados à localização e traduções | +| **2100 - 2199** | **Erros de Middleware** | Erros relacionados ao processamento de middleware | +| **2200 - 2299** | **Erros de Rede** | Erros relacionados a operações de rede | +| **2300 - 2399** | **Erros de Fila** | Erros relacionados a sistemas de fila | +| **2400 - 2499** | **Erros de Roteamento** | Erros relacionados a roteamento e métodos HTTP | + +| **2500 - 2599** | **Erros de Tempo de Execução** | Erros gerais de tempo de execução | +| **2600 - 2699** | **Erros de Criptografia** | Erros relacionados a criptografia e descriptografia | +| **2700 - 2799** | **Erros de Segurança** | Erros relacionados à segurança e controle de acesso | +| **2800 - 2899** | **Erros de Sessão** | Erros relacionados ao gerenciamento de sessões | +| **2900 - 2999** | **Erros de Sistema** | Erros relacionados a recursos do sistema e ambiente | +| **3000 - 3099** | **Erros de Template** | Erros relacionados a renderização e carregamento de templates | +| **3100 - 3199** | **Erros de Validação** | Erros relacionados à validação de dados | +| **4000 - 4099** | **Erros de Lógica de Negócios** | Erros personalizados para violações de lógica de negócios | + +### Explicação de Cada Faixa: + +1. **1000 - 1099: Erros de Autenticação** + + - Erros relacionados à autenticação do usuário, como credenciais inválidas, contas bloqueadas ou autenticação de dois fatores ausente. + +2. **1100 - 1199: Erros de Autorização** + + - Erros relacionados a permissões insuficientes ou funções ausentes durante processos de autorização. + +3. **... (Mesma descrição das faixas anteriores)** + +4. **3100 - 3199: Erros de Validação** + + - Erros relacionados à validação de dados. + +5. **4000 - 4099: Erros de Lógica de Negócios** + - Códigos de erro personalizados para violações de lógica de negócios específicas da sua aplicação. + +Essa estrutura permite que você categorize e expanda facilmente os códigos de erro no futuro, mantendo o sistema de tratamento de erros organizado. + +## Tipos de Exceção Disponíveis + +Cada tipo de exceção é projetado para lidar com cenários específicos de erro. Para informações detalhadas sobre cada tipo de exceção, consulte a [documentação](https://kariricode.org/docs/exception). + +## Integração com Outros Componentes do KaririCode + +O componente de Exceção foi projetado para funcionar perfeitamente com outros componentes do KaririCode: + +- **KaririCode\Logger**: Para logs e relatórios de erros avançados. +- **KaririCode\Http**: Para tratamento de exceções relacionadas a HTTP. +- **KaririCode\Database**: Para exceções específicas de banco de dados. + +## Desenvolvimento e Testes + +Para fins de desenvolvimento e testes, este pacote utiliza Docker e Docker Compose para garantir consistência entre diferentes ambientes. Um Makefile é fornecido para conveniência. + ### Pré-requisitos - Docker - Docker Compose -- Make (opcional, mas recomendado para execução mais fácil de comandos) +- Make (opcional, mas recomendado para facilitar a execução de comandos) ### Configuração de Desenvolvimento @@ -25,13 +649,14 @@ make setup-env ``` -3. Inicie os contêineres Docker: +3. Inicie os containers do Docker: ```bash make up ``` 4. Instale as dependências: + ```bash make composer-install ``` @@ -39,12 +664,12 @@ ### Comandos Make Disponíveis - `make up`: Inicia todos os serviços em segundo plano -- `make down`: Para e remove todos os contêineres -- `make build`: Constrói imagens Docker -- `make shell`: Acessa o shell do contêiner PHP -- `make test`: Executa testes -- `make coverage`: Executa cobertura de testes com formatação visual -- `make cs-fix`: Executa PHP CS Fixer para corrigir o estilo do código +- `make down`: Para e remove todos os containers +- `make build`: Constrói as imagens Docker +- `make shell`: Acessa o shell do container PHP +- `make test`: Executa os testes +- `make coverage`: Executa a cobertura dos testes com formatação visual +- `make cs-fix`: Executa o PHP CS Fixer para corrigir o estilo do código - `make quality`: Executa todos os comandos de qualidade (cs-check, test, security-check) Para uma lista completa de comandos disponíveis, execute: @@ -55,14 +680,14 @@ make help ## Licença -Este projeto está licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes. +Este projeto é licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para mais detalhes. ## Suporte e Comunidade -- **Documentação**: [https://kariricode.org/docs/sanitizer](https://kariricode.org/docs/sanitizer) +- **Documentação**: [https://kariricode.org/docs/exception](https://kariricode.org/docs/exception) - **Rastreador de Problemas**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-exception/issues) -- **Comunidade**: [Comunidade KaririCode Club](https://kariricode.club) +- **Comunidade**: [KaririCode Club Community](https://kariricode.club) --- -Construído com ❤️ pela equipe KaririCode. Capacitando desenvolvedores para criar aplicações PHP mais seguras e robustas. +Desenvolvido com ❤️ pela equipe KaririCode. Capacitando desenvolvedores a lidar com erros de forma eficaz e construir aplicações PHP mais resilientes. diff --git a/createDirectory.php b/createDirectory.php deleted file mode 100644 index 8247e17..0000000 --- a/createDirectory.php +++ /dev/null @@ -1,68 +0,0 @@ -