From 04e7da1324803f2a766fc44453500b49c3da512d Mon Sep 17 00:00:00 2001 From: Walmir Silva Date: Sat, 26 Oct 2024 16:06:08 -0300 Subject: [PATCH] docs: update usage examples in README (en and pt-br) - Improved code examples for basic and advanced usage of ProcessorPipeline - Adjustments to integration instructions with other KaririCode components - Updates for consistency and clarity between English and Portuguese versions - Modified `register` method to return `static` instead of `void`, enabling builder pattern in the pipeline --- README.md | 204 ++++++++++++++++++++++---- README.pt-br.md | 296 ++++++++++++++++++++++++++++---------- src/ProcessorRegistry.php | 4 +- tests/application.php | 182 +++++++++-------------- 4 files changed, 466 insertions(+), 220 deletions(-) diff --git a/README.md b/README.md index 8900c95..27bbc08 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# KaririCode Framework: ProcessorPipeline Component +# KaririCode Framework: Processor Pipeline 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) @@ -62,49 +62,142 @@ require_once 'vendor/autoload.php'; 1. Define your processors: ```php +register('user', 'emailNormalizer', new EmailNormalizer()); -$registry->register('user', 'emailValidator', new EmailValidator()); + public function process(mixed $input): mixed + { + if (!filter_var($input, FILTER_VALIDATE_EMAIL)) { + $this->resultCollection->addError( + self::class, + 'invalidFormat', + "Invalid email format: $input" + ); + } + return $input; + } +} +// Function to handle pipeline execution +function executePipeline(ProcessorBuilder $builder, ProcessorRegistry $registry, array $processorSpecs, string $input): void +{ + $resultCollection = new ProcessingResultCollection(); + $context = 'example_context'; + + $registry->register($context, 'upper_case', new UpperCaseProcessor()) + ->register($context, 'trim', new TrimProcessor()) + ->register($context, 'email_transform', new EmailTransformerProcessor()) + ->register($context, 'email_validate', new EmailValidatorProcessor($resultCollection)); + + try { + $pipeline = $builder->buildPipeline($context, $processorSpecs); + $output = $pipeline->process($input); + + // Displaying the results + echo "Original Input: '$input'\n"; + echo "Pipeline Output: '$output'\n"; + + // Display errors if any + if ($resultCollection->hasErrors()) { + echo "\nProcessing Errors:\n"; + print_r($resultCollection->getErrors()); + } else { + echo "\nNo processing errors encountered.\n"; + } + } catch (\Exception $e) { + echo "Error executing the pipeline: " . $e->getMessage() . "\n"; + } +} + +// Register processors to a context in the registry. +$registry = new ProcessorRegistry(); $builder = new ProcessorBuilder($registry); -``` -3. Build and use a pipeline: +// Execute scenario 1 - Valid input +$processorSpecs = [ + 'upper_case' => false, + 'trim' => true, + 'email_transform' => true, + 'email_validate' => true, +]; +$input = " Example@Email.COM "; -```php -$pipeline = $builder->buildPipeline('user', ['emailNormalizer', 'emailValidator']); +echo "Scenario 1 - Valid Input\n"; +executePipeline($builder, $registry, $processorSpecs, $input); + +// Execute scenario 2 - Invalid input +$input = " InvalidEmail@@@ "; -$email = ' JOHN.DOE@example.com '; -$normalizedEmail = $pipeline->process($email); -$isValid = $pipeline->process($normalizedEmail); +echo "\nScenario 2 - Invalid Input:\n"; +executePipeline($builder, $registry, $processorSpecs, $input); +``` + +### Test Output -echo "Normalized: $normalizedEmail\n"; -echo "Valid: " . ($isValid ? 'Yes' : 'No') . "\n"; +```bash +php ./tests/application.php +Scenario 1 - Valid Input +Original Input: ' Example@Email.COM ' +Pipeline Output: 'example@email.com' + +No processing errors encountered. + +Scenario 2 - Invalid Input: +Original Input: ' InvalidEmail@@@ ' +Pipeline Output: 'invalidemail@@@' + +Processing Errors: +Array +( + [EmailValidatorProcessor] => Array + ( + [0] => Array + ( + [errorKey] => invalidFormat + [message] => Invalid email format: invalidemail@@@ + ) + + ) +) ``` ### Advanced Usage @@ -151,16 +244,67 @@ The ProcessorPipeline component is designed to work seamlessly with other Kariri Example using ProcessorPipeline with Validator: +1. Define your data class with validation attributes: + +```php +use KaririCode\Validator\Attribute\Validate; + +class UserProfile +{ + #[Validate( + processors: [ + 'required', + 'length' => ['minLength' => 3, 'maxLength' => 20], + ], + messages: [ + 'required' => 'Username is required', + 'length' => 'Username must be between 3 and 20 characters', + ] + )] + private string $username = ''; + + #[Validate( + processors: ['required', 'email'], + messages: [ + 'required' => 'Email is required', + 'email' => 'Invalid email format', + ] + )] + private string $email = ''; + + // Getters and setters... +} +``` + +2. Set up the validator and use it: + ```php -use KaririCode\Validator\Validators\EmailValidator; -use KaririCode\Validator\Validators\NotEmptyValidator; +use KaririCode\ProcessorPipeline\ProcessorRegistry; +use KaririCode\Validator\Validator; +use KaririCode\Validator\Processor\Logic\RequiredValidator; +use KaririCode\Validator\Processor\Input\LengthValidator; +use KaririCode\Validator\Processor\Input\EmailValidator; -$registry->register('validation', 'email', new EmailValidator()); -$registry->register('validation', 'notEmpty', new NotEmptyValidator()); +$registry = new ProcessorRegistry(); +$registry->register('validator', 'required', new RequiredValidator()) + ->register('validator', 'length', new LengthValidator()) + ->register('validator', 'email', new EmailValidator()); + +$validator = new Validator($registry); + +$userProfile = new UserProfile(); +$userProfile->setUsername('wa'); // Too short +$userProfile->setEmail('invalid-email'); // Invalid format -$validationPipeline = $builder->buildPipeline('validation', ['notEmpty', 'email']); +$result = $validator->validate($userProfile); -$isValid = $validationPipeline->process($userInput); +if ($result->hasErrors()) { + foreach ($result->getErrors() as $property => $errors) { + foreach ($errors as $error) { + echo "$property: {$error['message']}\n"; + } + } +} ``` ## Development and Testing diff --git a/README.pt-br.md b/README.pt-br.md index ca198c4..f18b757 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -1,10 +1,10 @@ -# KaririCode Framework: Componente ProcessorPipeline +# KaririCode Framework: Processor Pipeline 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 robusto e flexível para criar e gerenciar pipelines de processamento no KaririCode Framework, fornecendo recursos avançados para lidar com tarefas complexas de processamento de dados em aplicações PHP. +Um componente robusto e flexível para criar e gerenciar pipelines de processamento no KaririCode Framework, oferecendo recursos avançados para lidar com tarefas complexas de processamento de dados em aplicações PHP. ## Índice @@ -13,7 +13,7 @@ Um componente robusto e flexível para criar e gerenciar pipelines de processame - [Uso](#uso) - [Uso Básico](#uso-básico) - [Uso Avançado](#uso-avançado) -- [Integração com Outros Componentes KaririCode](#integração-com-outros-componentes-kariricode) +- [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) @@ -21,24 +21,24 @@ Um componente robusto e flexível para criar e gerenciar pipelines de processame ## Funcionalidades -- Criação e gerenciamento fácil de pipelines de processamento +- Criação e gestão fáceis de pipelines de processamento - Suporte para processadores simples e configuráveis -- Registro de processadores baseado em contexto para gerenciamento organizado -- Integração perfeita com outros componentes KaririCode (Serializer, Validator, Normalizer) -- Arquitetura extensível permitindo processadores personalizados -- Construído sobre as interfaces KaririCode\Contract para máxima flexibilidade +- Registro de processadores baseado em contexto para uma gestão organizada +- Integração transparente com outros componentes do KaririCode (Serializer, Validator, Normalizer) +- Arquitetura extensível que permite processadores personalizados +- Construído sobre as interfaces do KaririCode\Contract para máxima flexibilidade ## Instalação O componente ProcessorPipeline pode ser facilmente instalado via Composer, que é o gerenciador de dependências recomendado para projetos PHP. -Para instalar o componente ProcessorPipeline em seu projeto, execute o seguinte comando no terminal: +Para instalar o componente ProcessorPipeline no seu projeto, execute o seguinte comando no terminal: ```bash composer require kariricode/processor-pipeline ``` -Este comando adicionará automaticamente o ProcessorPipeline ao seu projeto e instalará todas as dependências necessárias. +Esse comando adicionará automaticamente o ProcessorPipeline ao seu projeto e instalará todas as dependências necessárias. ### Requisitos @@ -47,9 +47,9 @@ Este comando adicionará automaticamente o ProcessorPipeline ao seu projeto e in ### Instalação Manual -Se você preferir não usar o Composer, você pode fazer o download do código-fonte diretamente do [repositório GitHub](https://github.com/KaririCode-Framework/kariricode-processor-pipeline) e incluí-lo manualmente em seu projeto. No entanto, recomendamos fortemente o uso do Composer para uma gestão mais fácil de dependências e atualizações. +Se preferir não usar o Composer, você pode baixar o código-fonte diretamente do [repositório GitHub](https://github.com/KaririCode-Framework/kariricode-processor-pipeline) e incluí-lo manualmente no seu projeto. No entanto, recomendamos fortemente o uso do Composer para facilitar o gerenciamento de dependências e atualizações. -Após a instalação, você pode começar a usar o ProcessorPipeline em seu projeto PHP imediatamente. Certifique-se de incluir o autoloader do Composer em seu script: +Após a instalação, você pode começar a usar o ProcessorPipeline no seu projeto PHP imediatamente. Certifique-se de incluir o autoloader do Composer em seu script: ```php require_once 'vendor/autoload.php'; @@ -62,118 +62,264 @@ require_once 'vendor/autoload.php'; 1. Defina seus processadores: ```php +register('usuario', 'normalizadorEmail', new NormalizadorEmail()); -$registro->register('usuario', 'validadorEmail', new ValidadorEmail()); + public function process(mixed $input): mixed + { + if (!filter_var($input, FILTER_VALIDATE_EMAIL)) { + $this->resultCollection->addError( + self::class, + 'invalidFormat', + "Formato de email inválido: $input" + ); + } + return $input; + } +} -$construtor = new ProcessorBuilder($registro); -``` +// Função para executar o pipeline +function executePipeline(ProcessorBuilder $builder, ProcessorRegistry $registry, array $processorSpecs, string $input): void +{ + $resultCollection = new ProcessingResultCollection(); + $context = 'exemplo_contexto'; + + $registry->register($context, 'upper_case', new UpperCaseProcessor()) + ->register($context, 'trim', new TrimProcessor()) + ->register($context, 'email_transform', new EmailTransformerProcessor()) + ->register($context, 'email_validate', new EmailValidatorProcessor($resultCollection)); + + try { + $pipeline = $builder->buildPipeline($context, $processorSpecs); + $output = $pipeline->process($input); + + // Exibindo os resultados + echo "Entrada Original: '$input'\n"; + echo "Saída do Pipeline: '$output'\n"; + + // Exibir erros, se houver + if ($resultCollection->hasErrors()) { + echo "\nErros de Processamento:\n"; + print_r($resultCollection->getErrors()); + } else { + echo "\nNenhum erro de processamento encontrado.\n"; + } + } catch (\Exception $e) { + echo "Erro ao executar o pipeline: " . $e->getMessage() . "\n"; + } +} -3. Construa e use um pipeline: +// Registrar processadores em um contexto no registro. +$registry = new ProcessorRegistry(); +$builder = new ProcessorBuilder($registry); -```php -$pipeline = $construtor->buildPipeline('usuario', ['normalizadorEmail', 'validadorEmail']); +// Executar cenário 1 - Entrada válida +$processorSpecs = [ + 'upper_case' => false, + 'trim' => true, + 'email_transform' => true, + 'email_validate' => true, +]; +$input = " Exemplo@Email.COM "; + +echo "Cenário 1 - Entrada Válida\n"; +executePipeline($builder, $registry, $processorSpecs, $input); + +// Executar cenário 2 - Entrada inválida +$input = " EmailInválido@@@ "; -$email = ' JOAO.SILVA@exemplo.com '; -$emailNormalizado = $pipeline->process($email); -$ehValido = $pipeline->process($emailNormalizado); +echo "\nCenário 2 - Entrada Inválida:\n"; +executePipeline($builder, $registry, $processorSpecs, $input); +``` + +### Saída de Teste -echo "Normalizado: $emailNormalizado\n"; -echo "Válido: " . ($ehValido ? 'Sim' : 'Não') . "\n"; +```bash +php ./tests/application.php +Cenário 1 - Entrada Válida +Entrada Original: ' Exemplo@Email.COM ' +Saída do Pipeline: 'exemplo@email.com' + +Nenhum erro de processamento encontrado. + +Cenário 2 - Entrada Inválida: +Entrada Original: ' EmailInválido@@@ ' +Saída do Pipeline: 'emailinvalido@@@' + +Erros de Processamento: +Array +( + [EmailValidatorProcessor] => Array + ( + [0] => Array + ( + [chaveErro] => formatoInvalido + [mensagem] => Formato de email inválido: emailinvalido@@@ + ) + + ) +) ``` ### Uso Avançado #### Processadores Configuráveis -Crie processadores configuráveis para maior flexibilidade: +Crie processadores configuráveis para mais flexibilidade: ```php use KaririCode\Contract\Processor\ConfigurableProcessor; -class ValidadorIdade implements ConfigurableProcessor +class AgeValidator implements ConfigurableProcessor { - private int $idadeMinima = 0; - private int $idadeMaxima = 120; + private int $minAge = 0; + private int $maxAge = 120; - public function configure(array $opcoes): void + public function configure(array $options): void { - if (isset($opcoes['idadeMinima'])) { - $this->idadeMinima = $opcoes['idadeMinima']; + if (isset($options['minAge'])) { + $this->minAge = $options['minAge']; } - if (isset($opcoes['idadeMaxima'])) { - $this->idadeMaxima = $opcoes['idadeMaxima']; + if (isset($options['maxAge'])) { + $this->maxAge = $options['maxAge']; } } public function process(mixed $input): bool { - return is_numeric($input) && $input >= $this->idadeMinima && $input <= $this->idadeMaxima; + return is_numeric($input) && $input >= $this->minAge && $input <= $this->maxAge; } } -$registro->register('usuario', 'validadorIdade', new ValidadorIdade()); -$pipeline = $construtor->buildPipeline('usuario', ['validadorIdade' => ['idadeMinima' => 18, 'idadeMaxima' => 100]]); +$registry->register('usuario', 'ageValidator', new AgeValidator()); +$pipeline = $builder->buildPipeline('usuario', ['ageValidator' => ['minAge' => 18, 'maxAge' => 100]]); ``` -## Integração com Outros Componentes KaririCode +## Integração com Outros Componentes do KaririCode -O componente ProcessorPipeline é projetado para trabalhar perfeitamente com outros componentes KaririCode: +O componente ProcessorPipeline foi projetado para funcionar perfeitamente com outros componentes do KaririCode: - **KaririCode\Serializer**: Use processadores para transformar dados antes ou depois da serialização. - **KaririCode\Validator**: Crie pipelines de validação para estruturas de dados complexas. - **KaririCode\Normalizer**: Construa pipelines de normalização para limpeza e padronização de dados. -Exemplo usando ProcessorPipeline com Validator: +Exemplo de uso do ProcessorPipeline com Validator: + +1. Defina sua classe de dados com atributos de validação: ```php -use KaririCode\Validator\Validators\EmailValidator; -use KaririCode\Validator\Validators\NotEmptyValidator; +use KaririCode\Validator\Attribute\Validate; -$registro->register('validacao', 'email', new EmailValidator()); -$registro->register('validacao', 'naoVazio', new NotEmptyValidator()); +class UserProfile +{ + #[Validate( + processors: [ + 'required', + 'length' => ['minLength' => 3, 'maxLength' => 20], + ], + messages: [ + 'required' => 'Nome de usuário é obrigatório', + 'length' => 'Nome de usuário deve ter entre 3 e 20 caracteres', + ] + )] + private string $username = ''; + + #[Validate( + processors: ['required', 'email'], + messages: [ + 'required' => 'Email é obrigatório', + 'email' => 'Formato de email inválido', + ] + ) + +] + private string $email = ''; + + // Getters e setters... +} +``` + +2. Configure o validador e utilize-o: + +```php +use KaririCode\ProcessorPipeline\ProcessorRegistry; +use KaririCode\Validator\Validator; +use KaririCode\Validator\Processor\Logic\RequiredValidator; +use KaririCode\Validator\Processor\Input\LengthValidator; +use KaririCode\Validator\Processor\Input\EmailValidator; + +$registry = new ProcessorRegistry(); +$registry->register('validator', 'required', new RequiredValidator()) + ->register('validator', 'length', new LengthValidator()) + ->register('validator', 'email', new EmailValidator()); -$pipelineValidacao = $construtor->buildPipeline('validacao', ['naoVazio', 'email']); +$validator = new Validator($registry); -$ehValido = $pipelineValidacao->process($entradaUsuario); +$userProfile = new UserProfile(); +$userProfile->setUsername('wa'); // Muito curto +$userProfile->setEmail('email-invalido'); // Formato inválido + +$result = $validator->validate($userProfile); + +if ($result->hasErrors()) { + foreach ($result->getErrors() as $property => $errors) { + foreach ($errors as $error) { + echo "$property: {$error['message']}\n"; + } + } +} ``` ## Desenvolvimento e Testes -Para fins de desenvolvimento e teste, este pacote utiliza Docker e Docker Compose para garantir consistência entre diferentes ambientes. Um Makefile é fornecido para conveniência. +Para fins de desenvolvimento e teste, este pacote usa Docker e Docker Compose para garantir a 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) +- Make (opcional, mas recomendado para execução mais fácil de comandos) -### Configuração para Desenvolvimento +### Configuração de Desenvolvimento 1. Clone o repositório: @@ -188,7 +334,7 @@ Para fins de desenvolvimento e teste, este pacote utiliza Docker e Docker Compos make setup-env ``` -3. Inicie os containers Docker: +3. Inicie os contêineres Docker: ```bash make up @@ -199,18 +345,18 @@ Para fins de desenvolvimento e teste, este pacote utiliza Docker e Docker Compos make composer-install ``` -### Comandos Make Disponíveis +### Comandos Disponíveis no Make -- `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 de 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) +- `make up`: Iniciar todos os serviços em segundo plano +- `make down`: Parar e remover todos os contêineres +- `make build`: Construir as imagens Docker +- `make shell`: Acessar o shell do contêiner PHP +- `make test`: Executar os testes +- `make coverage`: Executar cobertura de teste com formatação visual +- `make cs-fix`: Executar o PHP CS Fixer para corrigir o estilo de código +- `make quality`: Executar todos os comandos de qualidade (cs-check, test, security-check) -Para uma lista completa de comandos disponíveis, execute: +Para uma lista completa dos comandos disponíveis, execute: ```bash make help @@ -218,19 +364,19 @@ make help ## Licença -Este projeto está licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para mais detalhes. +Este projeto é licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes. ## Suporte e Comunidade - **Documentação**: [https://kariricode.org/docs/processor-pipeline](https://kariricode.org/docs/processor-pipeline) -- **Rastreador de Problemas**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-processor-pipeline/issues) +- **Relatório de Problemas**: [GitHub Issues](https://github.com/KaririCode-Framework/kariricode-processor-pipeline/issues) - **Comunidade**: [Comunidade KaririCode Club](https://kariricode.club) ## Agradecimentos -- A equipe do KaririCode Framework e contribuidores. +- Equipe e colaboradores do KaririCode Framework. - Inspirado por padrões de pipeline e cadeias de processamento em arquitetura de software. --- -Construído com ❤️ pela equipe KaririCode. Capacitando desenvolvedores a criar aplicações PHP mais robustas e flexíveis. +Feito com ❤️ pela equipe KaririCode. Capacitando desenvolvedores a criar aplicações PHP mais robustas e flexíveis. diff --git a/src/ProcessorRegistry.php b/src/ProcessorRegistry.php index 02c09b7..6f81fc1 100644 --- a/src/ProcessorRegistry.php +++ b/src/ProcessorRegistry.php @@ -17,13 +17,15 @@ public function __construct( ) { } - public function register(string $context, string $name, Processor $processor): void + public function register(string $context, string $name, Processor $processor): static { if (!$this->processors->containsKey($context)) { $this->processors->put($context, new HashMap()); } $contextMap = $this->processors->get($context); $contextMap->put($name, $processor); + + return $this; } public function get(string $context, string $name): Processor diff --git a/tests/application.php b/tests/application.php index 8392b24..be08349 100644 --- a/tests/application.php +++ b/tests/application.php @@ -4,151 +4,105 @@ require_once __DIR__ . '/../vendor/autoload.php'; -use KaririCode\Contract\Processor\ConfigurableProcessor; use KaririCode\Contract\Processor\Processor; use KaririCode\ProcessorPipeline\ProcessorBuilder; use KaririCode\ProcessorPipeline\ProcessorRegistry; +use KaririCode\ProcessorPipeline\Result\ProcessingResultCollection; -// Defining the User entity -class User +// Example of actual processors. +class UpperCaseProcessor implements Processor { - public function __construct( - private string $email, - private string $name, - private int $age - ) { - } - - public function getEmail(): string - { - return $this->email; - } - - public function setEmail(string $email): void - { - $this->email = $email; - } - - public function getName(): string + public function process(mixed $input): mixed { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function getAge(): int - { - return $this->age; - } - - public function setAge(int $age): void - { - $this->age = $age; + return strtoupper((string) $input); } } -// Defining specific processors -class EmailNormalizer implements Processor +class TrimProcessor implements Processor { - public function process(mixed $input): string + public function process(mixed $input): mixed { - return strtolower(trim($input)); + return trim((string) $input); } } -class EmailValidator implements Processor +class EmailTransformerProcessor implements Processor { - public function process(mixed $input): bool + public function process(mixed $input): mixed { - return false !== filter_var($input, FILTER_VALIDATE_EMAIL); + return strtolower((string) $input); } } -class NameCapitalizer implements Processor +class EmailValidatorProcessor implements Processor { - public function process(mixed $input): string + public function __construct(private ProcessingResultCollection $resultCollection) { - return ucwords(strtolower($input)); } -} - -class AgeValidator implements ConfigurableProcessor -{ - private int $minAge = 0; - private int $maxAge = 120; - public function configure(array $options): void + public function process(mixed $input): mixed { - if (isset($options['minAge'])) { - $this->minAge = $options['minAge']; - } - if (isset($options['maxAge'])) { - $this->maxAge = $options['maxAge']; + if (!filter_var($input, FILTER_VALIDATE_EMAIL)) { + $this->resultCollection->addError( + self::class, + 'invalidFormat', + "Invalid email format: $input" + ); } + + return $input; } +} - public function process(mixed $input): bool - { - return is_numeric($input) && $input >= $this->minAge && $input <= $this->maxAge; +// Function to handle pipeline execution +function executePipeline(ProcessorBuilder $builder, ProcessorRegistry $registry, array $processorSpecs, string $input): void +{ + $resultCollection = new ProcessingResultCollection(); + $context = 'example_context'; + + $registry->register($context, 'upper_case', new UpperCaseProcessor()) + ->register($context, 'trim', new TrimProcessor()) + ->register($context, 'email_transform', new EmailTransformerProcessor()) + ->register($context, 'email_validate', new EmailValidatorProcessor($resultCollection)); + + try { + $pipeline = $builder->buildPipeline($context, $processorSpecs); + $output = $pipeline->process($input); + + // Displaying the results + echo "Original Input: '$input'\n"; + echo "Pipeline Output: '$output'\n"; + + // Display errors if any + if ($resultCollection->hasErrors()) { + echo "\nProcessing Errors:\n"; + print_r($resultCollection->getErrors()); + } else { + echo "\nNo processing errors encountered.\n"; + } + } catch (Exception $e) { + echo 'Error executing the pipeline: ' . $e->getMessage() . "\n"; } } -// Configuring the processor registry +// Register processors to a context in the registry. $registry = new ProcessorRegistry(); -$registry->register('user', 'emailNormalizer', new EmailNormalizer()); -$registry->register('user', 'emailValidator', new EmailValidator()); -$registry->register('user', 'nameCapitalizer', new NameCapitalizer()); -$registry->register('user', 'ageValidator', new AgeValidator()); - -// Creating the ProcessorBuilder $builder = new ProcessorBuilder($registry); -// Function to process user data -function processUser(User $user, ProcessorBuilder $builder): array -{ - $result = []; - - // Processing the email - $emailNormalizerPipeline = $builder->buildPipeline('user', ['emailNormalizer']); - $normalizedEmail = $emailNormalizerPipeline->process($user->getEmail()); - $user->setEmail($normalizedEmail); - $emailValidatorPipeline = $builder->buildPipeline('user', ['emailValidator']); - $result['email'] = [ - 'value' => $user->getEmail(), - 'isValid' => $emailValidatorPipeline->process($user->getEmail()), - ]; - - // Processing the name - $namePipeline = $builder->buildPipeline('user', ['nameCapitalizer']); - $capitalizedName = $namePipeline->process($user->getName()); - $user->setName($capitalizedName); - $result['name'] = $user->getName(); - - // Processing the age - $agePipeline = $builder->buildPipeline('user', ['ageValidator' => ['minAge' => 18, 'maxAge' => 100]]); - $result['age'] = [ - 'value' => $user->getAge(), - 'isValid' => $agePipeline->process($user->getAge()), - ]; - - return $result; -} +// Execute scenario 1 - Valid input +$processorSpecs = [ + 'upper_case' => false, + 'trim' => true, + 'email_transform' => true, + 'email_validate' => true, +]; +$input = ' Example@Email.COM '; + +echo "Scenario 1 - Valid Input\n"; +executePipeline($builder, $registry, $processorSpecs, $input); + +// Execute scenario 2 - Invalid input +$input = ' InvalidEmail@@@ '; -// Usage example -$user = new User( - email: ' JOHN.DOE@example.com ', - name: 'jOHn doE', - age: 25 -); - -$processedData = processUser($user, $builder); -print_r($processedData); - -// Printing the modified user -echo "\nUser after processing:\n"; -echo 'Email: ' . $user->getEmail() . "\n"; -echo 'Name: ' . $user->getName() . "\n"; -echo 'Age: ' . $user->getAge() . "\n"; +echo "\nScenario 2 - Invalid Input (English)\n"; +executePipeline($builder, $registry, $processorSpecs, $input);