sierratecnologia / operador
Operador para ajudar no desenvolvimento de tasks
Fund package maintenance!
ricasolucoes
ricasolucoes.com.br/open-source/support-us
Installs: 201
Dependents: 3
Suggesters: 1
Security: 0
Stars: 0
Watchers: 0
Forks: 0
pkg:composer/sierratecnologia/operador
Requires
- php: ^7.2|^8.0
- lorisleiva/laravel-actions: ^1.1
- privatejustice/tramite: ^0.4.0
This package is auto-updated.
Last update: 2025-11-06 01:20:09 UTC
README
[](https://scrutinizer-ci.com/g/sierratecnologia/operador/?branch=master)[](https://scrutinizer-ci.com/g/sierratecnologia/operador/?branch=master)[](https://packagist.org/packages/sierratecnologia/operador) [](https://packagist.org/packages/sierratecnologia/operador) [](https://packagist.org/packages/sierratecnologia/operador) [](https://packagist.org/packages/sierratecnologia/operador)
Índice
- Introdução
- Instalação
- Arquitetura e Estrutura Interna
- Principais Componentes
- Uso Prático
- Integração com o Ecossistema SierraTecnologia
- Extensão e Customização
- Exemplos Reais
- Guia de Contribuição
- Ferramentas de Qualidade
Introdução
O que é o Operador?
Operador é uma biblioteca Laravel robusta e extensível desenvolvida pela SierraTecnologia para auxiliar no desenvolvimento, orquestração e execução de tarefas automatizadas, actions e processos em batch. A biblioteca oferece uma arquitetura sofisticada baseada em padrões de design consagrados, permitindo a criação de workflows complexos de forma simples e organizada.
Objetivo e Filosofia do Projeto
O Operador foi desenvolvido com os seguintes objetivos:
- Orquestração de Tarefas: Simplificar a execução de múltiplas ações de forma sequencial ou paralela
- Modularidade: Permitir a criação de componentes reutilizáveis e independentes
- Rastreabilidade: Oferecer monitoramento detalhado do progresso de execução
- Extensibilidade: Facilitar a criação de actions, workers e pipelines customizados
- Integração: Integrar-se perfeitamente com o ecossistema Laravel e SierraTecnologia
A filosofia central é proporcionar uma camada de abstração que permita aos desenvolvedores focar na lógica de negócio, enquanto o Operador gerencia a complexidade de orquestração, execução e rastreamento.
Benefícios de Uso
- Produtividade: Reduz significativamente o tempo de desenvolvimento de automações complexas
- Padronização: Estabelece convenções claras para criação de tarefas e actions
- Manutenibilidade: Código organizado e bem estruturado facilita manutenção
- Reusabilidade: Componentes podem ser reutilizados em diferentes contextos
- Rastreamento: Monitoramento em tempo real do progresso de execução
- Flexibilidade: Suporta múltiplos tipos de workers e estratégias de execução
Ecossistema SierraTecnologia
O Operador se encaixa perfeitamente no ecossistema SierraTecnologia, trabalhando em conjunto com:
- Muleta: Traits e contratos utilitários
- Pedreiro: Modelos base customizados
- Tramite: Sistema de tramitação e workflows
- Outros pacotes: Integração transparente com toda a stack SierraTecnologia
Instalação
Requisitos Mínimos
- PHP: ^7.2 ou ^8.0+
- Laravel: ^7.0 ou superior
- Composer: ^2.0
- Extensões PHP: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite
Instalação via Composer
Execute o seguinte comando no terminal do seu projeto Laravel:
composer require sierratecnologia/operador
Registro Automático do Service Provider
O Operador utiliza o auto-discovery do Laravel. O service provider será registrado automaticamente:
// Registrado automaticamente via composer.json extra.laravel.providers Operador\OperadorProvider
Publicação de Configurações (Opcional)
Se necessário, publique as configurações e assets:
php artisan vendor:publish --provider="Operador\OperadorProvider"
Executar Migrações
Execute as migrações para criar as tabelas necessárias:
php artisan migrate
As seguintes tabelas serão criadas:
bot_runners- Execução de runnersbot_internet_urls- URLs descobertasbot_internet_url_links- Relacionamento entre URLsbot_internet_url_forms- Formulários encontradosbot_internet_url_form_fields- Campos de formuláriosreferences- Referências dinâmicasreferenceables- Polimorfismo de referências
Configuração do Ambiente
Se for utilizar integração com Laravel Forge, configure as variáveis de ambiente:
FORGE_TOKEN=seu_token_aqui FORGE_SITE_ID=seu_site_id FORGE_SERVER_ID=seu_server_id
Arquitetura e Estrutura Interna
Estrutura de Diretórios
src/
├── Actions/ # Actions - padrão principal de execução
│ ├── Action.php # Classe base de actions
│ ├── ActionCollection.php # Orquestração de múltiplas actions
│ ├── Agir/ # Actions executivas (Excel, Export, Ban/Unban)
│ ├── Collect/ # Actions de coleta (Database, Repository)
│ ├── Instagram/ # Integração com Instagram
│ ├── Hooks/ # Webhooks (NewCommit, etc.)
│ └── Models/ # Actions específicas de modelos
│
├── Components/ # Componentes da aplicação
│ ├── TaskComponent.php # Base para todas as tasks
│ ├── Processing/ # Processamento de dados
│ ├── Worker/ # Workers especializados
│ │ ├── Explorer/ # Web crawling e scraping
│ │ ├── Logging/ # Processamento de logs
│ │ ├── Deploy/ # Deploy de aplicações
│ │ ├── Sync/ # Sincronização de dados
│ │ ├── Reports/ # Geração de relatórios
│ │ └── Life/ # Health checks
│ ├── View/ # Componentes de visualização
│ ├── Feactures/ # Features avançadas (Assistente, Training)
│ └── Interactions/ # Interações com usuário
│
├── Contracts/ # Interfaces e contratos
│ ├── ActionInterface.php # Interface de actions
│ ├── RunnerInterface.php # Interface de runners
│ ├── TaskInterface.php # Interface de tasks
│ ├── Pipeline.php # Pipeline base
│ ├── Stage.php # Stage base
│ └── Attributes/ # Atributos de metadados
│
├── Models/ # Modelos Eloquent
│ ├── Runner.php # Executor de actions
│ ├── Task.php # Tarefa genérica
│ ├── Job.php # Job da fila
│ └── FailedJob.php # Jobs que falharam
│
├── Pipelines/ # Pipelines de processamento
│ ├── Pipeline.php # Pipeline padrão
│ ├── Stages/ # Stages de pipeline
│ └── Handlers/ # Handlers de tipos de dados
│
├── Services/ # Serviços especializados
│ ├── QueueService.php # Gerenciamento de filas
│ └── ForgeService.php # Integração com Laravel Forge
│
├── Facades/ # Laravel Facades
├── Http/Controllers/ # Controllers HTTP
└── OperadorProvider.php # Service Provider principal
Namespaces
O Operador utiliza PSR-4 autoloading:
"autoload": { "psr-4": { "Operador\\": "src/" } }
Padrões Arquiteturais Adotados
O Operador emprega diversos padrões de design reconhecidos:
1. Strategy Pattern
Actions funcionam como estratégias intercambiáveis de processamento. Cada action implementa ActionInterface e pode ser executada de forma uniforme.
2. Pipeline Pattern
Processamento sequencial de dados através de stages, onde cada stage transforma o payload:
Input → Stage1 → Stage2 → Stage3 → Output
3. Builder Pattern
Construção fluente de runners e collections:
$runner->usingAction($action)->usingTarget($target)->execute();
4. Observer Pattern
Board executa callbacks para cada integração/componente, permitindo processamento customizado.
5. Service Provider Pattern
Integração com Laravel através de OperadorProvider.
6. Facade Pattern
Acesso simplificado a serviços através de facades Laravel.
Comunicação Entre Camadas
┌─────────────────────────────────────────────────────┐
│ ActionCollection │
│ (Orquestrador principal de actions) │
└──────────────────┬──────────────────────────────────┘
│
├─► Stage 0 (Paralelo)
│ ├─► Runner 1 → Action 1 → Worker 1
│ ├─► Runner 2 → Action 2 → Worker 2
│ └─► Runner 3 → Action 3 → Worker 3
│
├─► Stage 1 (Após Stage 0)
│ └─► Runner 4 → Action 4 → Worker 4
│
└─► Stage N
└─► Runner N → Action N → Worker N
Convenções e Boas Práticas
- Nomenclatura: Classes de actions devem ser verbos no infinitivo (exemplo:
ExportToExcel,SearchFollows) - Responsabilidade Única: Cada action deve ter uma única responsabilidade bem definida
- Imutabilidade: Pipelines devem retornar novos payloads transformados ao invés de modificar o original
- Rastreabilidade: Sempre utilize
OutputableTraitpara logging consistente - Tipagem: Utilize type hints e return types em todos os métodos públicos
Principais Componentes
1. TaskComponent
Classe base para todas as tasks e actions do Operador.
Localização: src/Components/TaskComponent.php
use Operador\Components\TaskComponent; class TaskComponent extends ActionBase { // Tipos de actions disponíveis const SPIDER = 1; // Exploração web const ROUTINE = 2; // Rotinas periódicas const HOOK = 3; // Webhooks/triggers const SYNC = 4; // Sincronização const LIFE = 5; // Health checks public $cod; // Código único da action public $classAfetada; // Classe/modelo afetado public $classAExecutar; // Classe executora public $type; // Tipo da action }
Métodos Principais:
loadActions(): Carrega todas as actions registradasgetActionByCode(string $cod): Obtém action por códigogetModels(): Lista todos os modelos disponíveisgetOnlyActionsForModel($model): Filtra actions para um modelo específico
Exemplo de Uso:
// Obter action por código $action = TaskComponent::getActionByCode('scanDomain'); // Listar actions para um modelo específico $actions = TaskComponent::getOnlyActionsForModel(Domain::class);
2. Action e ActionCollection
Action
Classe base para criar actions executáveis.
Localização: src/Actions/Action.php
use Operador\Actions\Action; class MinhaAction extends Action { public function execute() { // Lógica da action $this->info('Executando MinhaAction'); // Processar dados $resultado = $this->processar(); $this->notice('Action executada com sucesso'); return $resultado; } }
ActionCollection
Orquestrador que gerencia múltiplas actions em stages.
Localização: src/Actions/ActionCollection.php
use Operador\Actions\ActionCollection; $collection = new ActionCollection(); // Adicionar actions ao Stage 0 (executam em paralelo) $collection->newAction($action1, $stage = 0, $actorNumber = 0); $collection->newAction($action2, $stage = 0, $actorNumber = 1); // Adicionar action ao Stage 1 (executa após Stage 0) $collection->newAction($action3, $stage = 1, $actorNumber = 0); // Preparar, executar e finalizar $collection->prepare(); $collection->execute(); $collection->done(); // Monitorar progresso echo "Progresso: " . $collection->getPorcDone() . "%"; echo "Actions executadas: " . $collection->executedActions; echo "Total de stages: " . $collection->totalStages();
Principais Métodos:
newAction(ActionInterface $action, int $stage, int $actorNumber): Adiciona actionnewActionCollection(ActionCollection $collection, int $stage): Adiciona outra collectionprepare(): Prepara runners para execuçãoexecute(): Executa todos os runners sequencialmente por stagedone(): Finaliza execuçãorun(): Executa prepare() + execute() + done()getPorcDone(): Retorna porcentagem de conclusão (0-100)getTotalActionsCount(): Total de actionsgetTotalTargetsCount(): Total de targets
3. Runner
Modelo que executa uma action contra um target específico.
Localização: src/Models/Runner.php
use Operador\Models\Runner; $runner = Runner::makeWithOutput($output); $runner->usingAction($action) ->usingTarget($modelInstance) ->prepare() ->execute() ->done();
Estrutura do Banco de Dados:
Schema::create('bot_runners', function (Blueprint $table) { $table->id(); $table->string('action_code'); // Código da action $table->string('target_id'); // ID do target $table->string('progress'); // Progresso da execução $table->string('task'); // Descrição da task $table->string('stage'); // Stage atual $table->timestamps(); });
4. Workers Especializados
Spider - Web Crawler
Explora sites, extrai links e armazena informações.
Localização: src/Components/Worker/Explorer/Spider.php
use Operador\Components\Worker\Explorer\Spider; // Criar spider para explorar domínio $spider = new Spider('https://exemplo.com.br', $follow = true); // Executar exploração $spider->execute();
Funcionalidades:
- Extração automática de links
- Identificação de formulários
- Análise de estrutura do site
- Armazenamento de URLs descobertas
- Suporte a crawling recursivo
Logging - Processamento de Logs
Processa logs de diferentes servidores web.
Localização: src/Components/Worker/Logging/Logging.php
Plugins Suportados:
- Apache
- Nginx
- IIS
- PHP Error Logs
use Operador\Components\Worker\Logging\Logging; $logging = new Logging(); $logs = $logging->findForLogsInServer();
Deploy Worker
Gerencia deploy de aplicações.
Localização: src/Components/Worker/Deploy/DeployBusinessAmbiente.php
Sync Worker
Sincroniza dados entre sistemas.
Localização: src/Components/Worker/Sync/Project.php
5. Pipeline
Sistema de processamento sequencial através de stages.
Localização: src/Pipelines/Pipeline.php
use Operador\Pipelines\PipelineBase; use Operador\Pipelines\TimesTwoStage; use Operador\Pipelines\AddOneStage; $pipeline = (new PipelineBase) ->pipe(new TimesTwoStage()) // Multiplica por 2 ->pipe(new AddOneStage()); // Adiciona 1 $resultado = $pipeline->process(10); // (10 * 2) + 1 = 21
Criando Stage Customizado:
use Operador\Contracts\Stage; use Operador\Contracts\StageInterface; class MeuStage extends Stage implements StageInterface { public function __invoke($payload) { // Processar payload $payloadTransformado = $this->processar($payload); // Retornar payload transformado return $payloadTransformado; } private function processar($payload) { // Lógica de processamento return $payload; } }
6. Board
Orquestrador de integrações e componentes.
Localização: src/Components/View/Board.php
use Operador\Components\View\Board; $board = new Board(); // Executar para cada integração $board->executeForEachIntegration(function ($integration) { $integration->sincronizar(); }); // Executar para cada componente (suporta recursão) $board->executeForEachComponent(function ($component, $callback) { $dados = $integration->obterDados($component); foreach ($dados as $item) { // Processar subcomponentes recursivamente $callback($item); } });
Boards Especializados:
BusinessBoard: Board de negóciosMidiasSocialBoard: Mídias sociaisInfraBoard: InfraestruturaMarketingBoard: MarketingPhotoBoard: Fotos e imagensPersonalBoard: Tarefas pessoais
7. Services
QueueService
Gerenciamento de filas Laravel.
Localização: src/Services/QueueService.php
use Operador\Services\QueueService; $queueService = new QueueService(); // Jobs ativos $active = $queueService->activeJobs(); // Jobs agendados $upcoming = $queueService->upcomingJobs(); // Jobs que falharam $failed = $queueService->failedJobs(); // Reiniciar queue $queueService->restart(); // Retentar todos os jobs $queueService->retryAll(); // Retentar job específico $queueService->retry($jobId); // Cancelar job $queueService->cancel($jobId, $table);
ForgeService
Integração com Laravel Forge.
Localização: src/Services/ForgeService.php
use Operador\Services\ForgeService; $forgeService = new ForgeService(); // Obter configurações do servidor $settings = $forgeService->getSettings(); // Gerenciar firewall $firewalls = $forgeService->getFirewalls(); // Gerenciar sites $sites = $forgeService->getSites(); $site = $forgeService->getSite($siteId); // Gerenciar jobs agendados $jobs = $forgeService->getJobs(); $forgeService->createJob($dados); $forgeService->deleteJob($jobId); // Gerenciar workers $workers = $forgeService->getWorkers(); $forgeService->createWorker($dados); $forgeService->deleteWorker($workerId);
Uso Prático
Exemplo 1: Executar Action Simples
use Operador\Components\TaskComponent; use Operador\Models\Runner; use Symfony\Component\Console\Output\ConsoleOutput; // Obter action registrada $action = TaskComponent::getActionByCode('scanDomain'); // Obter modelo target $domain = Domain::find(1); // Criar output para logging $output = new ConsoleOutput(); // Criar e executar runner $runner = Runner::makeWithOutput($output) ->usingAction($action) ->usingTarget($domain) ->run(); // prepare() + execute() + done()
Exemplo 2: Executar Múltiplas Actions em Stages
use Operador\Actions\ActionCollection; use Operador\Components\TaskComponent; // Criar collection $collection = new ActionCollection(); // Stage 0: Coletar dados (em paralelo) $coletarUsuarios = TaskComponent::getActionByCode('coletarUsuarios'); $coletarPosts = TaskComponent::getActionByCode('coletarPosts'); $collection->newAction($coletarUsuarios, 0, 0); $collection->newAction($coletarPosts, 0, 1); // Stage 1: Processar dados (após Stage 0) $processarDados = TaskComponent::getActionByCode('processarDados'); $collection->newAction($processarDados, 1, 0); // Stage 2: Gerar relatório (após Stage 1) $gerarRelatorio = TaskComponent::getActionByCode('gerarRelatorio'); $collection->newAction($gerarRelatorio, 2, 0); // Executar todos os stages sequencialmente $collection->run(); // Monitorar progresso echo "Progresso total: " . $collection->getPorcDone() . "%\n"; echo "Actions executadas: {$collection->executedActions} de {$collection->getTotalActionsCount()}\n";
Exemplo 3: Criar Action Customizada
namespace App\Actions; use Operador\Actions\Action; use Operador\Contracts\ActionInterface; class ExportarRelatorioAction extends Action implements ActionInterface { public function execute() { $this->info('Iniciando exportação de relatório...'); try { // Obter dados $dados = $this->obterDados(); $this->notice("Coletados {$dados->count()} registros"); // Processar dados $processados = $this->processar($dados); // Gerar arquivo $arquivo = $this->gerarArquivo($processados); $this->info("Relatório gerado: {$arquivo}"); return [ 'success' => true, 'file' => $arquivo, 'records' => $dados->count() ]; } catch (\Exception $e) { $this->error("Erro ao exportar relatório: {$e->getMessage()}"); return [ 'success' => false, 'error' => $e->getMessage() ]; } } private function obterDados() { return User::with('posts', 'comments')->get(); } private function processar($dados) { return $dados->map(function ($user) { return [ 'nome' => $user->name, 'email' => $user->email, 'posts' => $user->posts->count(), 'comentarios' => $user->comments->count(), ]; }); } private function gerarArquivo($dados) { $filename = 'relatorio_' . date('Y-m-d_H-i-s') . '.json'; $path = storage_path("app/reports/{$filename}"); file_put_contents($path, json_encode($dados, JSON_PRETTY_PRINT)); return $path; } }
Registrar Action no TaskComponent:
// Em um Service Provider ou no próprio TaskComponent protected static function getRoutines($actions = []) { $actions[] = self::insertAction( 'exportarRelatorio', // Código único \App\Models\User::class, // Classe afetada \App\Actions\ExportarRelatorioAction::class, // Classe executora self::ROUTINE // Tipo ); return parent::getRoutines($actions); }
Exemplo 4: Usar Pipeline
use Operador\Pipelines\PipelineBase; // Criar stages customizados class ValidarDadosStage extends Stage { public function __invoke($payload) { // Validar dados if (empty($payload['email'])) { throw new \Exception('Email é obrigatório'); } return $payload; } } class EnriquecerDadosStage extends Stage { public function __invoke($payload) { // Adicionar informações extras $payload['created_at'] = now(); $payload['ip'] = request()->ip(); return $payload; } } class SalvarDadosStage extends Stage { public function __invoke($payload) { // Salvar no banco $user = User::create($payload); // Retornar usuário criado return $user; } } // Construir pipeline $pipeline = (new PipelineBase) ->pipe(new ValidarDadosStage()) ->pipe(new EnriquecerDadosStage()) ->pipe(new SalvarDadosStage()); // Processar dados $dados = [ 'name' => 'João Silva', 'email' => 'joao@exemplo.com' ]; $usuario = $pipeline->process($dados);
Exemplo 5: Spider para Explorar Site
use Operador\Components\Worker\Explorer\Spider; // Explorar site e extrair todos os links $spider = new Spider('https://sierratecnologia.com.br', $follow = true); // Executar exploração $spider->execute(); // As URLs serão armazenadas automaticamente em: // - bot_internet_urls (URLs descobertas) // - bot_internet_url_links (relacionamentos) // - bot_internet_url_forms (formulários encontrados)
Exemplo 6: Usar Board para Integrações
use Operador\Components\View\Boards\MidiasSocialBoard; $board = new MidiasSocialBoard(); // Executar rotinas para todas as integrações $board->executeForEachIntegration(function ($integration) { echo "Processando integração: " . get_class($integration) . "\n"; // Sincronizar dados $integration->sincronizar(); // Coletar novos posts $posts = $integration->coletarPosts(); echo "Coletados {$posts->count()} posts\n"; }); // Processar componentes de forma recursiva $board->executeForEachComponent(function ($component, $callback) { echo "Processando componente: {$component->getName()}\n"; // Obter dados do componente $dados = $component->obterDados(); // Processar cada item foreach ($dados as $item) { // Processar subcomponentes recursivamente $callback($item); } });
Exemplo 7: Gerenciar Filas com QueueService
use Operador\Services\QueueService; $queueService = new QueueService(); // Listar jobs ativos $activeJobs = $queueService->activeJobs(); foreach ($activeJobs as $job) { echo "Job {$job->id}: {$job->queue} - Tentativas: {$job->attempts}\n"; } // Listar jobs que falharam $failedJobs = $queueService->failedJobs(); foreach ($failedJobs as $job) { echo "Job falhou: {$job->id} - {$job->exception}\n"; } // Retentar job específico if (!empty($failedJobs)) { $jobId = $failedJobs[0]->id; $queueService->retry($jobId); echo "Job {$jobId} reenfileirado\n"; } // Reiniciar toda a fila $queueService->restart(); echo "Fila reiniciada\n";
Integração com o Ecossistema SierraTecnologia
Bibliotecas Complementares
O Operador integra-se nativamente com outras bibliotecas da SierraTecnologia:
Muleta
Fornece traits e contratos utilitários usados pelo Operador:
use Muleta\Traits\OutputableTrait; // Usado em Actions para logging consistente class MinhaAction extends Action { use OutputableTrait; public function execute() { $this->info('Informação'); $this->notice('Aviso'); $this->error('Erro'); } }
Pedreiro
Modelos base customizados:
use Pedreiro\Models\Base; // Runner e outros models estendem Base class Runner extends Base { // Herda funcionalidades do Pedreiro }
Tramite
Sistema de tramitação e workflows:
"require": { "privatejustice/tramite": "^0.4.0" }
Integração para gerenciamento de fluxos de trabalho complexos.
Padrões de Versionamento
A SierraTecnologia segue o Versionamento Semântico (SemVer):
MAJOR.MINOR.PATCH
- MAJOR: Mudanças incompatíveis com versões anteriores
- MINOR: Novas funcionalidades compatíveis
- PATCH: Correções de bugs compatíveis
Exemplo: 1.2.3
1= versão major2= versão minor (novas features)3= versão patch (bugfixes)
Testes Automatizados e CI/CD
O Operador utiliza GitHub Actions para CI/CD:
Workflows Configurados
-
Tests (
.github/workflows/run-tests.yml)- Executa PHPUnit em múltiplas versões de PHP
- Matrix testing: PHP 7.4, 8.0, 8.1, 8.2
- Testa em Ubuntu e Windows
-
PHP CS Fixer (
.github/workflows/php-cs-fixer.yml)- Verifica e corrige automaticamente code style
- Padrão PSR-12
- Auto-commit de correções
-
Psalm (
.github/workflows/psalm.yml)- Análise estática de código
- Nível de erro: 7
- Detecta bugs potenciais
Como Diferentes Equipes Podem Aplicar
Equipe de Backend
// Criar actions para processar dados class ProcessarPedidosAction extends Action { public function execute() { $pedidos = Pedido::pendentes()->get(); foreach ($pedidos as $pedido) { $this->processar($pedido); } } }
Equipe de DevOps
// Usar ForgeService para automação $forgeService = new ForgeService(); // Deploy automático $forgeService->createJob([ 'command' => 'cd /home/forge/site && git pull origin main', 'frequency' => 'hourly' ]);
Equipe de Data
// Pipeline de processamento de dados $pipeline = (new PipelineBase) ->pipe(new ExtrairDadosStage()) ->pipe(new TransformarDadosStage()) ->pipe(new CarregarDadosStage()); $resultado = $pipeline->process($fonte);
Equipe de Marketing
// Board de mídias sociais $board = new MidiasSocialBoard(); $board->executeForEachIntegration(function ($integration) { $integration->publicarPost([ 'titulo' => 'Novidade!', 'conteudo' => 'Confira nosso novo produto' ]); });
Extensão e Customização
Criar Actions Customizadas
Passo 1: Criar Classe da Action
namespace App\Operador\Actions; use Operador\Actions\Action; use Operador\Contracts\ActionInterface; class MinhaActionCustomizada extends Action implements ActionInterface { /** * Parâmetros da action */ protected $parametro1; protected $parametro2; /** * Construtor */ public function __construct($parametro1, $parametro2) { $this->parametro1 = $parametro1; $this->parametro2 = $parametro2; } /** * Método principal de execução */ public function execute() { $this->info('Iniciando MinhaActionCustomizada'); try { // Sua lógica aqui $resultado = $this->processar(); $this->notice('Action executada com sucesso'); return $resultado; } catch (\Exception $e) { $this->error("Erro: {$e->getMessage()}"); throw $e; } } /** * Lógica de processamento */ private function processar() { // Implementar lógica return true; } }
Passo 2: Registrar Action
// Em App\Providers\OperadorServiceProvider use Operador\Components\TaskComponent; class OperadorServiceProvider extends ServiceProvider { public function boot() { // Estender TaskComponent para registrar action TaskComponent::macro('getMinhasActions', function () { return [ TaskComponent::insertAction( 'minhaActionCustomizada', // Código único \App\Models\MeuModelo::class, // Modelo afetado \App\Operador\Actions\MinhaActionCustomizada::class, // Classe TaskComponent::ROUTINE // Tipo ) ]; }); } }
Passo 3: Usar Action
use Operador\Components\TaskComponent; use Operador\Models\Runner; // Obter action $action = TaskComponent::getActionByCode('minhaActionCustomizada'); // Executar $runner = Runner::makeWithOutput($output) ->usingAction($action) ->usingTarget($modelo) ->run();
Criar Workers Customizados
namespace App\Operador\Workers; class MeuWorkerCustomizado { /** * Output para logging */ protected $output; /** * Target sendo processado */ protected $target; /** * Construtor */ public function __construct($output, $target) { $this->output = $output; $this->target = $target; } /** * Executar worker */ public function execute(): bool { $this->output->writeln('<info>Executando MeuWorkerCustomizado</info>'); // Sua lógica aqui $this->processar(); $this->output->writeln('<notice>Worker executado com sucesso</notice>'); return true; } /** * Processar target */ private function processar() { // Implementar lógica de processamento } }
Criar Stages de Pipeline Customizados
namespace App\Operador\Stages; use Operador\Contracts\Stage; use Operador\Contracts\StageInterface; class MeuStageCustomizado extends Stage implements StageInterface { /** * Processar payload */ public function __invoke($payload) { // Validar payload $this->validar($payload); // Transformar payload $payloadTransformado = $this->transformar($payload); // Retornar payload transformado return $payloadTransformado; } /** * Validar payload */ private function validar($payload) { if (!isset($payload['campo_obrigatorio'])) { throw new \Exception('Campo obrigatório não encontrado'); } } /** * Transformar payload */ private function transformar($payload) { // Adicionar timestamp $payload['processed_at'] = now(); // Adicionar metadados $payload['metadata'] = [ 'stage' => 'MeuStageCustomizado', 'version' => '1.0.0' ]; return $payload; } }
Usar Stage Customizado:
use Operador\Pipelines\PipelineBase; use App\Operador\Stages\MeuStageCustomizado; $pipeline = (new PipelineBase) ->pipe(new MeuStageCustomizado()) ->pipe(new OutroStage()); $resultado = $pipeline->process($dados);
Criar Boards Customizados
namespace App\Operador\Boards; use Operador\Components\View\Board; class MeuBoardCustomizado extends Board { /** * Definir integrações */ public function getIntegrations(): array { return array_merge(parent::getIntegrations(), [ new MinhaIntegracaoCustomizada(), new OutraIntegracao(), ]); } /** * Definir actions disponíveis */ public function getActions(): array { return array_merge(parent::getActions(), [ \App\Actions\MinhaAction::class, \App\Actions\OutraAction::class, ]); } /** * Definir componentes */ public function getComponents(): array { return array_merge(parent::getComponents(), [ 'meu_componente' => \App\Components\MeuComponente::class, ]); } /** * Executar rotinas customizadas */ public function executeRoutines(): void { parent::executeRoutines(); // Suas rotinas customizadas $this->minhaRotinaCustomizada(); } /** * Rotina customizada */ private function minhaRotinaCustomizada() { // Implementar lógica } }
Substituir Classes Padrão via IoC
// Em App\Providers\AppServiceProvider public function register() { // Substituir Runner padrão $this->app->bind( \Operador\Models\Runner::class, \App\Operador\Models\MeuRunnerCustomizado::class ); // Substituir ActionCollection $this->app->bind( \Operador\Actions\ActionCollection::class, \App\Operador\Actions\MinhaCollectionCustomizada::class ); }
Boas Práticas para Manutenção
- Documentação: Sempre documente suas classes e métodos customizados
- Testes: Escreva testes unitários para actions e workers customizados
- Versionamento: Mantenha compatibilidade com a API do Operador
- Logging: Utilize
OutputableTraitpara logging consistente - Tratamento de Erros: Sempre capture e trate exceções adequadamente
- Code Style: Siga os padrões PSR-12
- Type Hints: Utilize type hints e return types
Exemplos Reais
Exemplo 1: Sistema de Processamento de Pedidos
Cenário: E-commerce que precisa processar pedidos automaticamente em múltiplos estágios.
Solução com Operador:
namespace App\Actions\Pedidos; use Operador\Actions\ActionCollection; use Operador\Components\TaskComponent; class ProcessarPedidosAutomaticamente { public function executar() { $collection = new ActionCollection(); // Stage 0: Validar pedidos $validarPedidos = TaskComponent::getActionByCode('validarPedidos'); $collection->newAction($validarPedidos, 0); // Stage 1: Processar pagamentos $processarPagamentos = TaskComponent::getActionByCode('processarPagamentos'); $collection->newAction($processarPagamentos, 1); // Stage 2: Gerar notas fiscais $gerarNotasFiscais = TaskComponent::getActionByCode('gerarNotasFiscais'); $collection->newAction($gerarNotasFiscais, 2); // Stage 3: Enviar para logística $enviarLogistica = TaskComponent::getActionByCode('enviarLogistica'); $collection->newAction($enviarLogistica, 3); // Stage 4: Notificar clientes $notificarClientes = TaskComponent::getActionByCode('notificarClientes'); $collection->newAction($notificarClientes, 4); // Executar pipeline completo $collection->run(); return [ 'success' => true, 'progress' => $collection->getPorcDone(), 'actions_executed' => $collection->executedActions ]; } }
Resultado:
- ✅ Processamento automatizado de pedidos
- ✅ Execução sequencial garantida
- ✅ Rastreamento de progresso em tempo real
- ✅ Fácil manutenção e extensão
Exemplo 2: Sincronização de Dados de Múltiplas APIs
Cenário: Sistema que precisa sincronizar dados de Instagram, Facebook e Twitter.
Antes (Sem Operador):
// Código desorganizado e difícil de manter class SincronizarMidiasSociais { public function executar() { // Instagram try { $instagramApi = new InstagramApi(); $posts = $instagramApi->getPosts(); foreach ($posts as $post) { Post::updateOrCreate(['instagram_id' => $post->id], $post->toArray()); } } catch (\Exception $e) { Log::error("Erro Instagram: " . $e->getMessage()); } // Facebook try { $facebookApi = new FacebookApi(); $posts = $facebookApi->getPosts(); foreach ($posts as $post) { Post::updateOrCreate(['facebook_id' => $post->id], $post->toArray()); } } catch (\Exception $e) { Log::error("Erro Facebook: " . $e->getMessage()); } // Twitter try { $twitterApi = new TwitterApi(); $posts = $twitterApi->getTweets(); foreach ($posts as $post) { Post::updateOrCreate(['twitter_id' => $post->id], $post->toArray()); } } catch (\Exception $e) { Log::error("Erro Twitter: " . $e->getMessage()); } } }
Depois (Com Operador):
use Operador\Components\View\Boards\MidiasSocialBoard; class SincronizarMidiasSociais { public function executar() { $board = new MidiasSocialBoard(); // Executar sincronização para todas as integrações $board->executeForEachIntegration(function ($integration) { $this->info("Sincronizando {$integration->getName()}"); // Coletar posts $posts = $integration->coletarPosts(); // Salvar no banco foreach ($posts as $post) { Post::updateOrCreate( [$integration->getName() . '_id' => $post->id], $post->toArray() ); } $this->notice("Sincronizados {$posts->count()} posts de {$integration->getName()}"); }); } }
Benefícios:
- ✅ Código 70% mais conciso
- ✅ Fácil adicionar novas integrações
- ✅ Logging consistente
- ✅ Tratamento de erros centralizado
- ✅ Manutenção simplificada
Exemplo 3: Web Scraping e Análise de Concorrência
Cenário: Sistema de inteligência de mercado que monitora sites concorrentes.
Solução com Operador:
use Operador\Components\Worker\Explorer\Spider; use Operador\Actions\ActionCollection; class MonitorarConcorrentes { protected $concorrentes = [ 'https://concorrente1.com.br', 'https://concorrente2.com.br', 'https://concorrente3.com.br', ]; public function executar() { $collection = new ActionCollection(); // Stage 0: Explorar sites (paralelo) foreach ($this->concorrentes as $index => $url) { $spider = new Spider($url, $follow = true); $explorarAction = new ExplorarSiteAction($spider); $collection->newAction($explorarAction, 0, $index); } // Stage 1: Extrair preços $extrairPrecos = TaskComponent::getActionByCode('extrairPrecos'); $collection->newAction($extrairPrecos, 1); // Stage 2: Analisar mudanças $analisarMudancas = TaskComponent::getActionByCode('analisarMudancas'); $collection->newAction($analisarMudancas, 2); // Stage 3: Gerar alertas $gerarAlertas = TaskComponent::getActionByCode('gerarAlertas'); $collection->newAction($gerarAlertas, 3); // Executar $collection->run(); return [ 'sites_explorados' => count($this->concorrentes), 'progress' => $collection->getPorcDone() ]; } }
Resultados:
- ✅ Monitoramento automatizado de concorrentes
- ✅ Exploração paralela de múltiplos sites
- ✅ Detecção automática de mudanças de preços
- ✅ Alertas em tempo real
Exemplo 4: Pipeline de Processamento de Imagens
Cenário: Sistema de galeria que processa uploads de imagens.
Solução com Pipeline:
use Operador\Pipelines\PipelineBase; // Stages customizados class ValidarImagemStage extends Stage { public function __invoke($payload) { if ($payload['size'] > 10 * 1024 * 1024) { throw new \Exception('Imagem maior que 10MB'); } if (!in_array($payload['mime'], ['image/jpeg', 'image/png'])) { throw new \Exception('Formato inválido'); } return $payload; } } class RedimensionarImagemStage extends Stage { public function __invoke($payload) { $imagem = Image::make($payload['path']); // Criar thumbnails $payload['thumbnails'] = [ 'small' => $this->resize($imagem, 150, 150), 'medium' => $this->resize($imagem, 300, 300), 'large' => $this->resize($imagem, 800, 800), ]; return $payload; } private function resize($imagem, $width, $height) { $filename = uniqid() . '.jpg'; $path = storage_path("app/thumbnails/{$width}x{$height}/{$filename}"); $imagem->fit($width, $height)->save($path); return $path; } } class OtimizarImagemStage extends Stage { public function __invoke($payload) { // Otimizar imagem original $optimizer = OptimizerChainFactory::create(); $optimizer->optimize($payload['path']); // Otimizar thumbnails foreach ($payload['thumbnails'] as $thumbnail) { $optimizer->optimize($thumbnail); } return $payload; } } class SalvarBancoDadosStage extends Stage { public function __invoke($payload) { $imagem = Imagem::create([ 'path' => $payload['path'], 'thumbnails' => $payload['thumbnails'], 'size' => $payload['size'], 'mime' => $payload['mime'], ]); return $imagem; } } // Usar pipeline class ProcessarUploadImagem { public function executar($file) { $pipeline = (new PipelineBase) ->pipe(new ValidarImagemStage()) ->pipe(new RedimensionarImagemStage()) ->pipe(new OtimizarImagemStage()) ->pipe(new SalvarBancoDadosStage()); $dados = [ 'path' => $file->store('images'), 'size' => $file->getSize(), 'mime' => $file->getMimeType(), ]; return $pipeline->process($dados); } }
Benefícios:
- ✅ Pipeline de processamento claro e organizado
- ✅ Fácil adicionar ou remover etapas
- ✅ Cada stage tem responsabilidade única
- ✅ Facilita testes unitários
Guia de Contribuição
Como Contribuir
Agradecemos seu interesse em contribuir para o Operador! Siga as instruções abaixo:
1. Fork do Repositório
# Fork via GitHub # Depois clone seu fork git clone https://github.com/seu-usuario/operador.git cd operador
2. Configurar Ambiente Local
# Instalar dependências composer install # Copiar .env.example (se houver) cp .env.example .env # Executar migrações php artisan migrate
3. Criar Branch para Feature/Fix
Siga a convenção de nomenclatura:
# Features git checkout -b feature/nome-da-feature # Bugfixes git checkout -b fix/nome-do-bug # Refatoração git checkout -b refactor/nome-da-refatoracao # Documentação git checkout -b docs/nome-da-documentacao
4. Fazer Alterações
- Escreva código seguindo PSR-12
- Adicione testes para novas funcionalidades
- Mantenha a cobertura de testes
- Documente métodos públicos
5. Executar Testes e Verificações
# Executar testes ./vendor/bin/phpunit # Verificar code style ./vendor/bin/php-cs-fixer fix --dry-run --diff # Análise estática ./vendor/bin/psalm # GrumPHP (se configurado) ./vendor/bin/grumphp run
6. Commit das Alterações
Siga o padrão de mensagens de commit:
# Formato: tipo(escopo): descrição # Exemplos: git commit -m "feat(actions): adicionar suporte a retry em actions" git commit -m "fix(runner): corrigir memory leak em execução paralela" git commit -m "docs(readme): atualizar exemplo de pipeline" git commit -m "test(spider): adicionar testes para Spider::explore" git commit -m "refactor(collection): simplificar lógica de stages"
Tipos de Commit:
feat: Nova funcionalidadefix: Correção de bugdocs: Documentaçãotest: Testesrefactor: Refatoraçãostyle: Formatação de códigoperf: Melhoria de performancechore: Tarefas gerais
7. Push e Pull Request
# Push para seu fork git push origin feature/nome-da-feature # Criar Pull Request via GitHub # Descreva claramente as mudanças # Referencie issues relacionadas
Padrões de Código
PSR-12
O Operador segue rigorosamente o padrão PSR-12:
<?php namespace Operador\Actions; use Operador\Contracts\ActionInterface; class MinhaAction implements ActionInterface { /** * Descrição do método * * @param string $parametro * @return bool */ public function execute(string $parametro): bool { // Código aqui return true; } }
Convenções de Nomenclatura
- Classes: PascalCase (exemplo:
ActionCollection) - Métodos: camelCase (exemplo:
executeAction) - Variáveis: camelCase (exemplo:
$actualStage) - Constantes: UPPER_SNAKE_CASE (exemplo:
SPIDER) - Namespaces: PascalCase (exemplo:
Operador\Actions)
Documentação de Código
/** * Executa action contra target específico * * Este método prepara o worker, executa a action e * registra o progresso no banco de dados. * * @param ActionInterface $action Action a ser executada * @param Base $target Target/modelo a ser processado * @return bool True se executado com sucesso * @throws \Exception Se worker não puder ser instanciado */ public function execute(ActionInterface $action, Base $target): bool { // Implementação }
Executar Testes Localmente
PHPUnit
# Executar todos os testes ./vendor/bin/phpunit # Executar com cobertura ./vendor/bin/phpunit --coverage-html coverage # Executar teste específico ./vendor/bin/phpunit tests/Unit/Actions/ActionCollectionTest.php # Executar com filtro ./vendor/bin/phpunit --filter testExecute
PHP CS Fixer
# Verificar problemas de estilo ./vendor/bin/php-cs-fixer fix --dry-run --diff # Corrigir automaticamente ./vendor/bin/php-cs-fixer fix # Verificar arquivo específico ./vendor/bin/php-cs-fixer fix src/Actions/Action.php --dry-run
Psalm (Análise Estática)
# Executar análise ./vendor/bin/psalm # Com relatório detalhado ./vendor/bin/psalm --show-info=true # Gerar baseline (ignorar erros existentes) ./vendor/bin/psalm --set-baseline=psalm-baseline.xml
Política de Licença
O Operador é licenciado sob ANCAP License.
Ao contribuir, você concorda que suas contribuições serão licenciadas sob a mesma licença.
Autores e Contato
Mantenedor Principal: SierraTecnologia
Email:
- Suporte: help@sierratecnologia.com.br
- Contribuições: contributing@sierratecnologia.com.br
Links:
- Website: https://sierratecnologia.com.br
- GitHub: https://github.com/sierratecnologia/operador
- Issues: https://github.com/sierratecnologia/operador/issues
- Packagist: https://packagist.org/packages/sierratecnologia/operador
Processo de Review
-
Automated Checks: GitHub Actions executará automaticamente:
- Testes PHPUnit
- PHP CS Fixer
- Psalm
-
Code Review: Mantenedores revisarão:
- Qualidade do código
- Testes adequados
- Documentação
- Aderência aos padrões
-
Aprovação: Após aprovação, o PR será merged
Versionamento Semântico
O Operador segue Semantic Versioning 2.0.0:
MAJOR.MINOR.PATCH
1.2.3
│ │ └─ Patch: Correções de bugs
│ └─── Minor: Novas funcionalidades (compatível)
└───── Major: Mudanças incompatíveis (breaking changes)
Ferramentas de Qualidade
GitHub Actions Workflows
O Operador utiliza GitHub Actions para garantir qualidade contínua do código.
1. Tests Workflow
Arquivo: .github/workflows/run-tests.yml
Executa testes automatizados em múltiplos ambientes:
- Sistemas Operacionais: Ubuntu e Windows
- Versões PHP: 7.4, 8.0, 8.1, 8.2
- Versões Laravel: 7.x, 8.x, 9.x, 10.x
- Estratégias de Dependências: prefer-lowest e prefer-stable
# Executar localmente ./vendor/bin/phpunit # Com cobertura ./vendor/bin/phpunit --coverage-html coverage # Visualizar cobertura open coverage/index.html
2. PHP CS Fixer Workflow
Arquivo: .github/workflows/php-cs-fixer.yml
Verifica e corrige automaticamente o estilo de código segundo PSR-12:
# Verificar problemas (dry-run) ./vendor/bin/php-cs-fixer fix --dry-run --diff --config=.php_cs # Corrigir automaticamente ./vendor/bin/php-cs-fixer fix --config=.php_cs # Verificar arquivo específico ./vendor/bin/php-cs-fixer fix src/Actions/Action.php --dry-run
Regras Configuradas (.php_cs):
- Padrão PSR-2/PSR-12
- Permissão de constantes uppercase
- Flexibilidade em espaçamento de argumentos
3. Psalm Workflow
Arquivo: .github/workflows/psalm.yml
Análise estática de código para detectar bugs potenciais:
# Executar análise ./vendor/bin/psalm # Com informações detalhadas ./vendor/bin/psalm --show-info=true # Gerar relatório JSON ./vendor/bin/psalm --report=psalm-report.json # Limpar cache ./vendor/bin/psalm --clear-cache
Configuração (psalm.xml):
- Nível de Erro: 7 (rigoroso)
- Diretórios Analisados:
src/ - Ignora:
vendor/
Configuração Local de Desenvolvimento
GrumPHP
Hooks Git automáticos para garantir qualidade antes do commit:
# Instalar hooks ./vendor/bin/grumphp git:init # Executar manualmente ./vendor/bin/grumphp run # Bypass (use com cautela) git commit --no-verify
Verificações Configuradas (grumphp.yml):
- Tamanho de arquivo (max 10MB)
- Formato de mensagem de commit
- Blacklist de código (var_dump, die, exit)
- Nomenclatura de branches
- Psalm
PHPUnit
Configuração: phpunit.xml
<phpunit colors="true"> <testsuites> <testsuite name="Operador Tests"> <directory>./tests/</directory> </testsuite> </testsuites> </phpunit>
Executar Testes:
# Todos os testes ./vendor/bin/phpunit # Suite específica ./vendor/bin/phpunit --testsuite "Operador Tests" # Teste específico ./vendor/bin/phpunit tests/Unit/Actions/ActionCollectionTest.php # Com filtro de método ./vendor/bin/phpunit --filter testExecuteActionsInStages # Com cobertura de código ./vendor/bin/phpunit --coverage-html coverage --coverage-filter src/
Badges de Qualidade
Adicione ao README os badges de status:
[](https://github.com/sierratecnologia/operador/actions) [](https://github.com/sierratecnologia/operador/actions) [](https://github.com/sierratecnologia/operador/actions)
Integração com Scrutinizer CI
O Operador também utiliza Scrutinizer CI para análise adicional de qualidade.
Configuração: .scrutinizer.yml
# Visualizar no Scrutinizer
https://scrutinizer-ci.com/g/sierratecnologia/operador/
Integração com CodeClimate
Configuração: .codeclimate.yml
Análise de:
- Complexidade ciclomática
- Duplicação de código
- Manutenibilidade
- Cobertura de testes
Comandos Úteis de Desenvolvimento
# Instalar dependências de desenvolvimento composer install # Atualizar dependências composer update # Verificar dependências desatualizadas composer outdated # Validar composer.json composer validate # Dump autoload composer dump-autoload # Executar todas as verificações de qualidade ./vendor/bin/grumphp run # Limpar caches php artisan cache:clear php artisan config:clear php artisan route:clear php artisan view:clear
Checklist de Qualidade
Antes de criar Pull Request, verifique:
- ✅ Todos os testes passando (
./vendor/bin/phpunit) - ✅ Code style correto (
./vendor/bin/php-cs-fixer fix --dry-run) - ✅ Análise estática sem erros (
./vendor/bin/psalm) - ✅ Novos testes adicionados para novas funcionalidades
- ✅ Documentação atualizada
- ✅ Mensagem de commit seguindo padrões
- ✅ GrumPHP validado (
./vendor/bin/grumphp run) - ✅ Sem código comentado ou debug (var_dump, dd, etc.)
- ✅ Sem conflitos de merge
About SierraTecnologia
A SierraTecnologia é uma organização brasileira focada no desenvolvimento de soluções tecnológicas inovadoras e de alta qualidade para o ecossistema Laravel e PHP.
Nossa Missão
Criar ferramentas e bibliotecas que aumentem a produtividade dos desenvolvedores, estabeleçam padrões de excelência e simplifiquem tarefas complexas.
Nossos Valores
- Qualidade: Código limpo, testado e bem documentado
- Inovação: Soluções criativas para problemas reais
- Comunidade: Contribuição ativa com o open source
- Excelência: Comprometimento com as melhores práticas
Outras Bibliotecas
Conheça outros projetos da SierraTecnologia:
- Muleta: Traits e contratos utilitários
- Pedreiro: Modelos base e helpers
- Tramite: Sistema de tramitação e workflows
- Fabrica: Infraestrutura e domain models
- E mais...
Contato
- 🌐 Website: https://sierratecnologia.com.br
- 📧 Email: help@sierratecnologia.com.br
- 💼 GitHub: https://github.com/sierratecnologia
- 📦 Packagist: https://packagist.org/packages/sierratecnologia/
Licença
O Operador é um software open-source licenciado sob a ANCAP License.
Desenvolvido com ❤️ pela SierraTecnologia