diff --git a/.gitignore b/.gitignore index 3847c0df..5a1aeace 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ yarn-error.log /.nova /.vscode /.zed +/.kanbn +lang/php_*.json diff --git a/app/Console/Commands/CleanCommandLogs.php b/app/Console/Commands/CleanCommandLogs.php new file mode 100644 index 00000000..ded735cf --- /dev/null +++ b/app/Console/Commands/CleanCommandLogs.php @@ -0,0 +1,41 @@ +subDays($days); + + try { + $deletedCount = CommandLog::where('executed_at', '<', $thresholdDate)->delete(); + $outputMessage = "{$deletedCount} registros antigos de logs foram excluídos. Registros mais antigos que {$days} dias foram excluídos."; + + $this->logCommandExecution($outputMessage, true); + $this->info($outputMessage); + } catch (\Exception $e) { + // Registro de falha no log + $this->logCommandExecution($e->getMessage(), false); + $this->error("Falha ao limpar logs de comandos antigos: {$e->getMessage()}"); + } + } +} diff --git a/app/Console/Commands/CleanDeletedRecordsBackup.php b/app/Console/Commands/CleanDeletedRecordsBackup.php new file mode 100644 index 00000000..83926a45 --- /dev/null +++ b/app/Console/Commands/CleanDeletedRecordsBackup.php @@ -0,0 +1,44 @@ +logCommandExecution("Backup de registros excluídos está desativado. Nenhuma ação necessária.", true); + $this->info('Backup de registros excluídos está desativado. Nenhuma ação necessária.'); + return; + } + + // Obtém o número de dias configurados + $days = config('app.keep_deleted_backup_for'); + $thresholdDate = Carbon::now()->subDays($days); // Data limite + + try { + $deletedCount = DB::table('deleted_records') + ->where('deleted_at', '<', $thresholdDate) + ->delete(); + $this->logCommandExecution("{$deletedCount} Backups antigos removidos com sucesso. Registros mais antigos que {$days} dias foram excluídos.", true); + $this->info("{$deletedCount} Backups antigos removidos com sucesso. Registros mais antigos que {$days} dias foram excluídos."); + } catch (\Exception $e) { + // Registro de falha no log + $this->logCommandExecution($e->getMessage(), false); + $this->error("Falha ao limpar backups antigos: {$e->getMessage()}"); + } + + + // Realiza a limpeza de backups antigos + } +} diff --git a/app/Console/Commands/GrgsDev/AppendAttributes.php b/app/Console/Commands/GrgsDev/AppendAttributes.php new file mode 100644 index 00000000..0a9d7f99 --- /dev/null +++ b/app/Console/Commands/GrgsDev/AppendAttributes.php @@ -0,0 +1,88 @@ +error("O arquivo appTranslatedAttributes.php não foi encontrado."); + return Command::FAILURE; + } + + // Incluir o arquivo de traduções + $translatedAttributes = include $inputFilePath; + + // Verifica se o array de traduções é válido + if (!is_array($translatedAttributes)) { + $this->error("O arquivo appTranslatedAttributes.php não contém um array válido."); + return Command::FAILURE; + } + + // Loop através de cada idioma (locale) e suas traduções + foreach ($translatedAttributes as $locale => $attributes) { + // Caminho do arquivo validation.php para o idioma atual + $validationFilePath = base_path("lang/{$locale}/validation.php"); + + // Verificar se o arquivo validation.php existe + if (!File::exists($validationFilePath)) { + $this->error("O arquivo validation.php para o idioma '{$locale}' não foi encontrado."); + continue; + } + + // Incluir o conteúdo de validation.php + $validationArray = include $validationFilePath; + + // Verificar se a chave 'attributes' existe, se não, pula o idioma + if (!isset($validationArray['attributes'])) { + $this->error("A chave 'attributes' não foi encontrada no arquivo validation.php para o idioma '{$locale}'."); + continue; + } + + // Pegar os atributos existentes em 'attributes' + $existingAttributes = $validationArray['attributes']; + + // Adicionar as chaves novas (que não existem em attributes) ao array existente + foreach ($attributes as $key => $value) { + if (!array_key_exists($key, $existingAttributes)) { + $existingAttributes[$key] = $value; + } + } + + // Ordenar o array 'attributes' em ordem alfabética + ksort($existingAttributes); + + // Atualizar apenas a chave 'attributes' no array de validation.php + $validationArray['attributes'] = $existingAttributes; + + // Lê o conteúdo original do arquivo validation.php para não modificar sua estrutura + $originalContent = File::get($validationFilePath); + + // Atualiza somente a chave 'attributes' no arquivo + $updatedAttributesExport = var_export($existingAttributes, true); + $updatedContent = preg_replace( + '/\'attributes\'\s*=>\s*\[[^\]]*\]/s', + "'attributes' => {$updatedAttributesExport}", + $originalContent + ); + + // Escreve o conteúdo atualizado no arquivo, mantendo o restante da estrutura + File::put($validationFilePath, $updatedContent); + + $this->info("Atributos atualizados para o idioma '{$locale}' em lang/{$locale}/validation.php"); + } + + return Command::SUCCESS; + } +} diff --git a/app/Console/Commands/GrgsDev/ExtractAttributes.php b/app/Console/Commands/GrgsDev/ExtractAttributes.php new file mode 100644 index 00000000..7807db04 --- /dev/null +++ b/app/Console/Commands/GrgsDev/ExtractAttributes.php @@ -0,0 +1,88 @@ +error("O diretório 'app/Http/Requests' não foi encontrado."); + return Command::FAILURE; + } + + // Função para ler todos os arquivos .php recursivamente + $phpFiles = $this->getPhpFiles($directory); + + $attributes = []; + + // Percorrer todos os arquivos encontrados + foreach ($phpFiles as $file) { + $content = File::get($file); + + // Usar regex para encontrar o método rules() + if (preg_match('/public function rules\(\)\s*\{(.*?)\}/s', $content, $matches)) { + $rulesContent = $matches[1]; + + // Encontrar as chaves dentro do array de rules() + if (preg_match_all('/\'([^\']+)\'\s*=>/', $rulesContent, $ruleMatches)) { + $keys = $ruleMatches[1]; + $attributes = array_merge($attributes, $keys); + } + } + } + + // Remover duplicatas e ordenar o array + $attributes = array_unique($attributes); + sort($attributes); + + // Gerar o arquivo de saída no formato esperado + $output = "info("Atributos extraídos com sucesso em " . base_path('documentation/translations/appAttributes.php')); + + return Command::SUCCESS; + } + + // Função para obter todos os arquivos .php recursivamente + protected function getPhpFiles($directory) + { + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)); + $regexIterator = new RegexIterator($iterator, '/^.+\.php$/i', RegexIterator::GET_MATCH); + + $files = []; + foreach ($regexIterator as $file) { + $files[] = $file[0]; + } + + return $files; + } +} diff --git a/app/Console/Commands/GrgsDev/GenerateApiController.php b/app/Console/Commands/GrgsDev/GenerateApiController.php new file mode 100644 index 00000000..4769cb0a --- /dev/null +++ b/app/Console/Commands/GrgsDev/GenerateApiController.php @@ -0,0 +1,1362 @@ +argument('model'); + $jsonPath = base_path("documentation/models/json/{$modelName}.json"); + + if (!File::exists($jsonPath)) { + $this->error("JSON file for model {$modelName} not found at path {$jsonPath}."); + return; + } + + $jsonContent = json_decode(File::get($jsonPath), true); + + if (!$jsonContent) { + $this->error('Invalid JSON content.'); + return; + } + + $attributes = $jsonContent['attributes'] ?? []; + $relations = $jsonContent['relations'] ?? []; + $softDeletes = $jsonContent['softDeletes'] ?? false; + $timestamps = $jsonContent['timestamps'] ?? true; + $version = $jsonContent['version'] ?? 'V1'; + $logsActivity = $jsonContent['logsActivity'] ?? false; + $clearsResponseCache = $jsonContent['clearsResponseCache'] ?? false; + $useIsActive = $jsonContent['useIsActive'] ?? false; + $useApprovedStatus = $jsonContent['useApprovedStatus'] ?? false; + + // Gerar API Controller + $this->generateApiController($modelName, $timestamps, $softDeletes, $relations, $version, $attributes, $useIsActive, $useApprovedStatus, $logsActivity); + $this->generateConcretController($modelName, $version); + + $this->info("Controller for {$modelName} generated successfully."); + } + + protected function generateApiController($modelName, $timestamps, $softDeletes, $relations, $version, $attributes, $useIsActive, $useApprovedStatus, $logsActivity) + { + $className = "{$modelName}Controller"; + $namespace = "App\\Http\\Controllers\\Api\\{$version}\\AbstractContracts\\{$modelName}"; + $filePath = app_path("Http/Controllers/Api/{$version}/AbstractContracts/{$modelName}/{$className}.php"); + $modelSnaked = Str::snake($modelName); + $modelCamel = Str::camel($modelName); + + $useUploadService = ''; + $updateUpload = ''; + $changeClearUpload = ''; + $removeOldUpload = ''; + $removeCreatedUpload = ''; + $useChangeUpload = ''; + $hasBoolean = false; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file' || $attribute['type'] === 'image' || $attribute['type'] === 'video') { + $name = $attribute['name']; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + $modelSnaked = Str::snake($modelName); + $modelCamel = Str::camel($modelName); + + $useChangeUpload .= "use App\Http\Requests\Api\\{$version}\\{$modelName}\Change{$modelName}{$capitalLetter}Request;\n"; + } + if ($attribute['type'] === 'boolean') { + $hasBoolean = true; + } + } + $createTranslated = $this->generateStoreTranslatedCode($attributes); + $createIsActiveApproved = ''; + $useAuthFacade = ''; + if ($useIsActive || $useApprovedStatus) { + $useAuthFacade = "use Illuminate\Support\Facades\Auth;\nuse App\Services\StatusService;"; + $createIsActiveApproved = $this->generateCreateIsActiveApprovedCode($modelName, $useIsActive, $useApprovedStatus); + } + $updateTranslated = $this->generateTranslatedWithComparisonCode($attributes); + $saveTranslated = $this->generateSaveTranslationsCode($attributes); + $createUpload = $this->generateCreateUploadLogic($attributes, $modelName); + if ($createUpload) { + $useUploadService = 'use App\Services\UploadService;'; + $removeCreatedUpload = $this->generateRemoveCreateUploadLogic($attributes); + $updateUpload = $this->generateUpdateUploadLogic($attributes, $modelName); + $removeOldUpload = $this->generateRemoveOldUploadLogic($attributes); + + $changeClearUpload = $this->generateClearChangeUploadLogic($attributes, $modelName); + } + $changeActiveDeactiveLogic = ''; + $useChangeIsActiveRequest = ''; + $changeApprovedStatusLogic = ''; + $useChangeApprovedStatusRequest = ''; + $booleanActiveDeactiveLogic = ''; + if ($hasBoolean) { + $booleanActiveDeactiveLogic = $this->generateBooleanActiveInactiveLogic($attributes, $modelName); + } + if ($useIsActive) { + $name = 'is_active'; + $capitalLetter = ucwords(Str::camel($name)); + $modelSnaked = Str::snake($modelName); + $modelCamel = Str::camel($modelName); + $useChangeIsActiveRequest = "use App\Http\Requests\Api\\{$version}\\{$modelName}\Change{$modelName}{$capitalLetter}Request;"; + $changeActiveDeactiveLogic = $this->generateActiveInactiveLogic($modelName); + } + if ($useApprovedStatus) { + $name = 'approved_status'; + $capitalLetter = ucwords(Str::camel($name)); + $modelSnaked = Str::snake($modelName); + $modelCamel = Str::camel($modelName); + $useChangeApprovedStatusRequest = "use App\Http\Requests\Api\\{$version}\\{$modelName}\Change{$modelName}{$capitalLetter}Request;"; + $changeApprovedStatusLogic = $this->generateApprovedStatusLogic($modelName); + } + + $relationMethods = []; + foreach ($relations as $relation) { + if ($relation['type'] === 'belongsToMany') { + $relationMethods[] = $this->generateAttachDetachMethods($relation['name'], $modelName, $modelSnaked, $modelCamel); + } + } + $relationMethods = implode("\n\n", $relationMethods); + + $softDeleteMethods = $softDeletes ? $this->generateSoftDeleteMethods($modelName, $modelSnaked, $modelCamel, $modelName) : ''; + + $indexComment = $this->generateApiDocumentation($modelName, $attributes, $relations, $timestamps, $softDeletes, $logsActivity, $useIsActive, $useApprovedStatus); + $showIncludeDoc = $this->generateApiShowDocumentation($relations, $logsActivity, $useIsActive, $useApprovedStatus); + $classTemplate = <<paginate(request('per_page'))->withQueryString(); + return {$modelName}Resource::collection(\$query); + } + + /** + * Show {$modelName} by ID. + * @urlParam {$modelSnaked}_id int required No-example + {$showIncludeDoc} + */ + public function show(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$modelName}::class, \${$modelCamel}Id, {$modelName}::ALLOWEDINCLUDES(), {$modelName}::DEFAULTINCLUDES()); + if (request()->wantsJson()) { + return \$this->sendResponse(new {$modelName}Resource(\$item)); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } + + /** + * Store {$modelName}. + */ + public function store(Store{$modelName}Request \$request) + { + \$data = []; + foreach (\$request->all() as \$key => \$value) { + if (!is_null(\$value)) { + \$data[\$key] = \$value; + } + } + {$createTranslated} + {$createUpload} + DB::beginTransaction(); + try { + \$item = {$modelName}::create(\$data); + {$createIsActiveApproved} + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + {$removeCreatedUpload} + throw \$th; + } + if (request()->wantsJson()) { + return \$this->sendResponse(new {$modelName}Resource(\$item)); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } + + /** + * Update {$modelName} by ID. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function update(Update{$modelName}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$modelName}::class, \${$modelCamel}Id); + \$data = []; + foreach (\$request->all() as \$key => \$value) { + if (!is_null(\$value) && \$item->{\$key} !== \$value) { + \$data[\$key] = \$value; + } + } + {$updateTranslated} + {$updateUpload} + DB::beginTransaction(); + try { + if (!empty(\$data)) { + \$item->update(\$data); + } + {$saveTranslated} + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + {$removeCreatedUpload} + throw \$th; + } + {$removeOldUpload} + if (request()->wantsJson()) { + return \$this->sendResponse(new {$modelName}Resource(\$item)); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } + + /** + * Delete {$modelName} by ID. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function destroy(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$modelName}::class, \${$modelCamel}Id); + DB::beginTransaction(); + try { + \$item->delete(); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + if (request()->wantsJson()) { + return \$this->sendSuccess(); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } + + {$softDeleteMethods} + + {$changeClearUpload} + + {$booleanActiveDeactiveLogic} + + {$changeActiveDeactiveLogic} + + {$changeApprovedStatusLogic} + + {$relationMethods} +} +EOD; + if (!File::isDirectory(dirname($filePath))) { + File::makeDirectory(dirname($filePath), 0755, true); + } + + File::put($filePath, $classTemplate); + $this->info("Abstract Controller {$modelName}Controller gerado com sucesso."); + } + + protected function generateAttachDetachMethods($relationName, $modelName, $modelSnaked, $modelCamel) + { + return <<{$relationName}()->attach(\$request->input('{$relationName}')); + return \$this->sendSuccess(); +} + +/** + * Remove {$relationName} from {$modelName}. + * @urlParam {$modelSnaked}_id int required No-example + */ +public function detach{$relationName}({$modelName} \$model, Request \$request) +{ + \$model->{$relationName}()->detach(\$request->input('{$relationName}')); + return \$this->sendSuccess(); +} +EOD; + } + + protected function generateSoftDeleteMethods($model, $modelSnaked, $modelCamel, $modelName) + { + return <<restore(); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + if (request()->wantsJson()) { + return \$this->sendSuccess(); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } + + /** + * Force Delete {$model}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function forceDelete(\${$modelCamel}Id) + { + \$item = QueryService::getOrFailTrashedById({$modelName}::class, \${$modelCamel}Id); + DB::beginTransaction(); + try { + \$item->forceDelete(); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + if (request()->wantsJson()) { + return \$this->sendSuccess(); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } +EOD; + } + + protected function generateCreateUploadLogic($attributes, $model) + { + + $uploadLogic = ""; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file' || $attribute['type'] === 'image' || $attribute['type'] === 'video') { + $name = $attribute['name']; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + + $uploadLogic .= " + // UPLOAD de {$attribute['name']} + \$storage{$capitalLetter} = {$model}::{$nameUpper}_STORAGE; + \$savedName{$capitalLetter} = ''; + \$originalFileName = ''; + \$fileSize = 0; + \$fileExtension = ''; + \$uploadData = []; + try { + if (\$request->hasFile('$name')) { + \$uploadData = UploadService::putFile(\$request->file('$name'), \$storage{$capitalLetter}); + } else { + if (!empty(\$request->{$name}) && strpos(\$request->{$name}, ';base64')) { + \$uploadData = UploadService::putFile(\$request->{$name}, \$storage{$capitalLetter}); + } + } + if (\$uploadData) { + \$savedName{$capitalLetter} = \$uploadData['saved_name']; + \$originalFileName = \$uploadData['original_name']; + \$fileSize = \$uploadData['size']; + \$fileExtension = \$uploadData['extension']; + } + } catch (\Throwable \$th) { + throw \$th; + } + if (\$savedName{$capitalLetter}) { + \$data['{$name}'] = \$savedName{$capitalLetter}; + \$data['{$name}_file_name'] = \$originalFileName; + \$data['{$name}_file_size'] = \$fileSize; + \$data['{$name}_file_extension'] = \$fileExtension; + }"; + } + } + return $uploadLogic; + } + + protected function generateRemoveCreateUploadLogic($attributes) + { + + $uploadLogic = ""; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file' || $attribute['type'] === 'image' || $attribute['type'] === 'video') { + $name = $attribute['name']; + $capitalLetter = ucwords(Str::camel($name)); + + $uploadLogic .= " + if (\$savedName{$capitalLetter}) { + UploadService::removeFile(\$savedName{$capitalLetter}, \$storage{$capitalLetter}); + }"; + } + } + return $uploadLogic; + } + + protected function generateUpdateUploadLogic($attributes, $model) + { + + $uploadLogic = ""; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file' || $attribute['type'] === 'image' || $attribute['type'] === 'video') { + $name = $attribute['name']; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + + $uploadLogic .= " + // UPLOAD de {$attribute['name']} + \$oldSavedName{$capitalLetter} = \$item->{$name}; + \$storage{$capitalLetter} = {$model}::{$nameUpper}_STORAGE; + \$savedName{$capitalLetter} = ''; + \$originalFileName = ''; + \$fileSize = 0; + \$fileExtension = ''; + \$uploadData = []; + try { + if (\$request->hasFile('$name')) { + \$uploadData = UploadService::putFile(\$request->file('$name'), \$storage{$capitalLetter}); + } else { + if (!empty(\$request->{$name}) && strpos(\$request->{$name}, ';base64')) { + \$uploadData = UploadService::putFile(\$request->{$name}, \$storage{$capitalLetter}); + } + } + if (\$uploadData) { + \$savedName{$capitalLetter} = \$uploadData['saved_name']; + \$originalFileName = \$uploadData['original_name']; + \$fileSize = \$uploadData['size']; + \$fileExtension = \$uploadData['extension']; + } + } catch (\Throwable \$th) { + throw \$th; + } + if (\$savedName{$capitalLetter}) { + \$data['{$name}'] = \$savedName{$capitalLetter}; + \$data['{$name}_file_name'] = \$originalFileName; + \$data['{$name}_file_size'] = \$fileSize; + \$data['{$name}_file_extension'] = \$fileExtension; + }"; + } + } + return $uploadLogic; + } + + protected function generateRemoveOldUploadLogic($attributes) + { + + $uploadLogic = ""; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file' || $attribute['type'] === 'image' || $attribute['type'] === 'video') { + $name = $attribute['name']; + $capitalLetter = ucwords(Str::camel($name)); + + $uploadLogic .= " + if (\$savedName{$capitalLetter} && \$oldSavedName{$capitalLetter}) { + UploadService::removeFile(\$oldSavedName{$capitalLetter}, \$storage{$capitalLetter}); + }"; + } + } + return $uploadLogic; + } + + protected function generateClearChangeUploadLogic($attributes, $model) + { + + $uploadLogic = ""; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file' || $attribute['type'] === 'image' || $attribute['type'] === 'video') { + $name = $attribute['name']; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + $modelSnaked = Str::snake($model); + $modelCamel = Str::camel($model); + + $uploadLogic .= " + /** + * Change {$name}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function change{$capitalLetter}(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + \$oldSavedName{$capitalLetter} = \$item->{$name}; + \$storage{$capitalLetter} = {$model}::{$nameUpper}_STORAGE; + \$savedName{$capitalLetter} = ''; + \$originalFileName = ''; + \$fileSize = 0; + \$fileExtension = ''; + \$uploadData = []; + + try { + if (\$request->hasFile('$name')) { + \$uploadData = UploadService::putFile(\$request->file('$name'), \$storage{$capitalLetter}); + } else { + if (!empty(\$request->{$name}) && strpos(\$request->{$name}, ';base64')) { + \$uploadData = UploadService::putFile(\$request->{$name}, \$storage{$capitalLetter}); + } + } + if (\$uploadData) { + \$savedName{$capitalLetter} = \$uploadData['saved_name']; + \$originalFileName = \$uploadData['original_name']; + \$fileSize = \$uploadData['size']; + \$fileExtension = \$uploadData['extension']; + } + } catch (\Throwable \$th) { + throw \$th; + } + if (\$savedName{$capitalLetter}) { + \$data['{$name}'] = \$savedName{$capitalLetter}; + \$data['{$name}_file_name'] = \$originalFileName; + \$data['{$name}_file_size'] = \$fileSize; + \$data['{$name}_file_extension'] = \$fileExtension; + + //SAVE DATA + DB::beginTransaction(); + try { + \$item->update(\$data); + if (\$oldSavedName{$capitalLetter}) { + UploadService::removeFile(\$oldSavedName{$capitalLetter}, \$storage{$capitalLetter}); + } + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + if (\$savedName{$capitalLetter}) { + UploadService::removeFile(\$savedName{$capitalLetter}, \$storage{$capitalLetter}); + } + throw \$th; + } + } + + if (request()->wantsJson()) { + return \$this->sendSuccess(); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + } + + /** + * Clear {$name}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function clear{$capitalLetter}(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + \$oldSavedName{$capitalLetter} = \$item->{$name}; + \$storage{$capitalLetter} = {$model}::{$nameUpper}_STORAGE; + \$savedName{$capitalLetter} = ''; + \$originalFileName = ''; + \$fileSize = 0; + \$fileExtension = ''; + \$data = []; + + \$data['{$name}'] = \$savedName{$capitalLetter}; + \$data['{$name}_file_name'] = \$originalFileName; + \$data['{$name}_file_size'] = \$fileSize; + \$data['{$name}_file_extension'] = \$fileExtension; + //SAVE DATA + DB::beginTransaction(); + try { + \$item->update(\$data); + if (\$oldSavedName{$capitalLetter}) { + UploadService::removeFile(\$oldSavedName{$capitalLetter}, \$storage{$capitalLetter}); + } + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + + if (request()->wantsJson()) { + return \$this->sendSuccess(); + } else { + return redirect()->back()->with( + 'toasts', + [ + 'id' => Str::uuid(), + 'type' => 'success', + 'message' => __('The action was executed successfully.'), + ] + ); + } + }"; + } + } + return $uploadLogic; + } + + + protected function generateBooleanActiveInactiveLogic($attributes, $model) + { + $modelSnaked = Str::snake($model); + $modelCamel = Str::camel($model); + + $uploadLogic = ""; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'boolean') { + $name = $attribute['name']; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + $uploadLogic .= "/** + * Mark as {$capitalLetter}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function change{$capitalLetter}ToTrue(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (\$item->{$name}) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$item->update([ + '{$name}' => 1, + ]); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Mark as NOT {$capitalLetter}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function change{$capitalLetter}ToFalse(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (!\$item->{$name}) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$item->update([ + '{$name}' => 0, + ]); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Toggle {$capitalLetter}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function toggle{$capitalLetter}(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + + DB::beginTransaction(); + try { + if (!\$item->{$name}) { + \$item->update([ + '{$name}' => 1, + ]); + } else { + \$item->update([ + '{$name}' => 0, + ]); + } + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + }"; + } + } + + return $uploadLogic; + } + + + protected function generateActiveInactiveLogic($model) + { + + $uploadLogic = ""; + + $name = 'is_active'; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + $modelSnaked = Str::snake($model); + $modelCamel = Str::camel($model); + + $uploadLogic .= "/** + * Active {$model}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function active(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (\$item->is_active) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$item->update([ + 'is_active' => 1, + ]); + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + + if (\$item->is_active) { + StatusService::active(\$item, \$motive, Auth::user()->id); + } else { + StatusService::deactive(\$item, \$motive, Auth::user()->id); + } + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Deactive {$model}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function deactive(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (!\$item->is_active) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$item->update([ + 'is_active' => 0, + ]); + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + + if (\$item->is_active) { + StatusService::active(\$item, \$motive, Auth::user()->id); + } else { + StatusService::deactive(\$item, \$motive, Auth::user()->id); + } + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Toggle IsActive. + * @urlParam gender_id int required No-example + */ + public function toggleIsActive(string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + + DB::beginTransaction(); + try { + if (!\$item->is_active) { + \$item->update([ + 'is_active' => 1, + ]); + } else { + \$item->update([ + 'is_active' => 0, + ]); + } + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + }"; + + return $uploadLogic; + } + + protected function generateApprovedStatusLogic($model) + { + $uploadLogic = ""; + $name = 'approved_status'; + $nameUpper = Str::upper($name); + $capitalLetter = ucwords(Str::camel($name)); + $modelSnaked = Str::snake($model); + $modelCamel = Str::camel($model); + + $uploadLogic .= "/** + * Turn Analisys {$model}. + * @urlParam {$modelSnaked}_id int required No-example + */ + public function analisys(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (\$item->approved_status == {$model}::APPROVED_STATUS_ANALISYS) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + StatusService::analisys(\$item, \$motive, request()->user()->id); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Approve {$model}. + * @urlParam {$modelSnaked}_id int required No-example + * + */ + public function approve(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + DB::beginTransaction(); + try { + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + StatusService::approve(\$item, \$motive, request()->user()->id); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Unapprove {$model}. + * @urlParam {$modelSnaked}_id int required No-example + * + */ + public function unapprove(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (\$item->approved_status == {$model}::APPROVED_STATUS_UNAPPROVED) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + StatusService::unapprove(\$item, \$motive, request()->user()->id); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Block {$model}. + * @urlParam {$modelSnaked}_id int required No-example + * + */ + public function block(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (\$item->approved_status == {$model}::APPROVED_STATUS_BLOCKED) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + StatusService::block(\$item, \$motive, request()->user()->id); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + } + + /** + * Cancel {$model}. + * @urlParam {$modelSnaked}_id int required No-example + * + */ + public function cancel(Change{$model}{$capitalLetter}Request \$request, string \${$modelCamel}Id) + { + \$item = QueryService::getOrFailById({$model}::class, \${$modelCamel}Id); + if (\$item->approved_status == {$model}::APPROVED_STATUS_CANCELED) { + return \$this->sendSuccess(); + } + DB::beginTransaction(); + try { + \$motive = 'Sem motivo indicado'; + if (\$request->motive) { + \$motive = \$request->motive; + } + StatusService::cancel(\$item, \$motive, request()->user()->id); + DB::commit(); + } catch (\Throwable \$th) { + DB::rollBack(); + throw \$th; + } + return \$this->sendSuccess(); + }"; + + return $uploadLogic; + } + + protected function generateConcretController($model, $version) + { + $filePath = app_path("Http/Controllers/Api/{$version}/{$model}/{$model}Controller.php"); + if (!File::isDirectory(dirname($filePath))) { + File::makeDirectory(dirname($filePath), 0755, true); + } + // Verifica se o modelo concreto já existe + if (!File::exists($filePath)) { + $modelContent = <<info("Concret controller {$model}Controller gerado com sucesso."); + } + } + + protected function generateApiDocumentation($modelName, $attributes, $relations, $timestamps, $softDeletes, $logsActivity, $useIsActive, $useApprovedStatus) + { + $attributeId = [ + "name" => "id", + "type" => "unsignedBigInteger", + "length" => null, + "max" => null, + "min" => null, + "required" => false, + "nullable" => true, + "default" => null, + "unique" => false, + "sortAble" => true, + "filterAble" => true, + "exactFilter" => true, + "searchAble" => true, + "translated" => false, + ]; + array_unshift($attributes, $attributeId); + if ($useIsActive) { + $attrib = [ + "name" => "is_active", + "sortAble" => true, + + ]; + array_push($attributes, $attrib); + } + if ($timestamps) { + $attrib = [ + "name" => "created_at", + "sortAble" => true, + + ]; + array_push($attributes, $attrib); + $attrib = [ + "name" => "updated_at", + "sortAble" => true, + + ]; + array_push($attributes, $attrib); + } + + if ($softDeletes) { + $attrib = [ + "name" => "deleted_at", + "sortAble" => true, + + ]; + array_push($attributes, $attrib); + } + + // Filtros: atributos com filterAble = true + $filters = array_filter($attributes, function ($attr) { + return isset($attr['filterAble']) && $attr['filterAble'] === true; + }); + + // Sort: atributos com sortAble = true + $sortableAttributes = array_filter($attributes, function ($attr) { + return isset($attr['sortAble']) && $attr['sortAble'] === true; + }); + // Include: lista de relacionamentos (se existirem) + $includeRelations = !empty($relations) ? array_map(function ($relation) { + return $relation['name']; + }, $relations) : []; + + if ($useIsActive) { + $includeRelations[] = 'activeMotives'; + } + if ($useApprovedStatus) { + $includeRelations[] = 'approvedMotives'; + } + + + if ($logsActivity) { + $includeRelations[] = 'activities'; + } + // Construindo a documentação dinâmica + $doc = "/**\n"; + $doc .= " * list {$modelName}.\n"; + $doc .= " * @queryParam page int Indique o número da página desejada No-example\n"; + $doc .= " * @queryParam per_page int Indique quantos registros deve conter cada página[default=50] No-example\n"; + + // Gerar a linha dos includes + if (!empty($includeRelations)) { + $doc .= " * @queryParam include Allowed: " . implode(",", $includeRelations) . " Relacionamentos que podem ser incluídos na resposta No-example\n"; + } + + // Gerar as linhas dos filtros + foreach ($filters as $filter) { + $name = $filter['name']; + + // Se o tipo for 'date', 'timestamp', ou 'datetime', cria filtros adicionais + if (in_array($filter['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $transformedName = Str::ucfirst(Str::camel($filter['name'])); // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $doc .= " * @queryParam filter[{$transformedName}After] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Before] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Between] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentDay] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentWeek] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentMonth] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}LastDays] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}NextDays] No-example\n"; + } else { + if (in_array($filter['type'], ['boolean'])) { + $transformedName = Str::ucfirst(Str::camel($filter['name'])); // Nome transformado + $doc .= " * @queryParam filter[{$name}] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $doc .= " * @queryParam filter[Not{$transformedName}] No-example\n"; + } else { + // Filtro normal + $doc .= " * @queryParam filter[{$name}] No-example\n"; + } + } + } + if ($timestamps) { + $transformedName = Str::ucfirst(Str::camel('created_at')); // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $doc .= " * @queryParam filter[{$transformedName}After] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Before] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Between] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentDay] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentWeek] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentMonth] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}LastDays] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}NextDays] No-example\n"; + + $transformedName = Str::ucfirst(Str::camel('updated_at')); // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $doc .= " * @queryParam filter[{$transformedName}After] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Before] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Between] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentDay] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentWeek] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentMonth] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}LastDays] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}NextDays] No-example\n"; + } + if ($softDeletes) { + $transformedName = Str::ucfirst(Str::camel('deleted_at')); // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $doc .= " * @queryParam filter[{$transformedName}After] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Before] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}Between] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentDay] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentWeek] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}CurrentMonth] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}LastDays] No-example\n"; + $doc .= " * @queryParam filter[{$transformedName}NextDays] No-example\n"; + } + if ($useIsActive) { + //WithTrashed,OnlyTrashed + $transformedName = 'IsActive'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + + $transformedName = 'IsNotActive'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + } + + if ($useApprovedStatus) { + //WithTrashed,OnlyTrashed + $transformedName = 'Analisys'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + + $transformedName = 'Approved'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $transformedName = 'Unapproved'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $transformedName = 'Blocked'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + $transformedName = 'Canceled'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + + } + + + if ($softDeletes) { + //WithTrashed,OnlyTrashed + $transformedName = 'WithTrashed'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + + $transformedName = 'OnlyTrashed'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + } + $transformedName = 'Search'; // Nome transformado + $doc .= " * @queryParam filter[{$transformedName}] No-example\n"; // Filtro original + + // Gerar a linha do sort + if (!empty($sortableAttributes)) { + $sortableNames = array_map(function ($attr) { + return $attr['name']; + }, $sortableAttributes); + $doc .= " * @queryParam sort Allowed: " . implode(",", $sortableNames) . " Classifica a lista. Para classificação descendente coloque o - na frente(-id) No-example\n"; + } + + $doc .= " */\n"; + + return $doc; + } + + protected function generateApiShowDocumentation($relations, $logsActivity, $useIsActive, $useApprovedStatus) + { + // Include: lista de relacionamentos (se existirem) + $includeRelations = !empty($relations) ? array_map(function ($relation) { + return $relation['name']; + }, $relations) : []; + if ($useIsActive) { + $includeRelations[] = 'activeMotives'; + } + if ($useApprovedStatus) { + $includeRelations[] = 'approvedMotives'; + } + + if ($logsActivity) { + $includeRelations[] = 'activities'; + } + + $doc = "*"; + if (!empty($includeRelations)) { + $doc = "* @queryParam include Allowed: " . implode(",", $includeRelations) . " Relacionamentos que podem ser incluídos na resposta No-example"; + } + return $doc; + } + + protected function generateStoreTranslatedCode($attributes) + { + + $translatedAttributes = array_filter($attributes, function ($attr) { + return isset($attr['translated']) && $attr['translated'] === true; + }); + + $translatedCode = "// TRANSLATEDS\n"; + + foreach ($translatedAttributes as $attribute) { + $name = $attribute['name']; + + // Gerar código dinamicamente para atributos traduzíveis + $translatedCode .= " if (!empty(\$request->{$name})) {\n"; + $translatedCode .= " \$translated = TranslatorGoogle::translate(\$request->{$name});\n"; + $translatedCode .= " \$data['{$name}'] = \$translated['original_text'];\n"; + $translatedCode .= " \$data['{$name}_translated'] = \$translated['translations'];\n"; + $translatedCode .= " \$data['original_locale'] = \$translated['source_language'];\n"; + $translatedCode .= " }\n"; + } + + return $translatedCode; + } + + protected function generateTranslatedWithComparisonCode($attributes) + { + + $translatedAttributes = array_filter($attributes, function ($attr) { + return isset($attr['translated']) && $attr['translated'] === true; + }); + + $translatedCode = ""; + + foreach ($translatedAttributes as $attribute) { + $name = $attribute['name']; + $nameTranslatedVar = "{$name}Translateds"; + + // Gerar código dinamicamente para atributos traduzíveis + $translatedCode .= "\${$nameTranslatedVar} = [];\n"; + $translatedCode .= " if (!empty(\$request->{$name}) && (\$request->{$name} != \$item->{$name})) {\n"; + $translatedCode .= " \$translated = TranslatorGoogle::translate(\$request->{$name});\n"; + $translatedCode .= " \$data['{$name}'] = \$translated['original_text'];\n"; + $translatedCode .= " \${$nameTranslatedVar} = \$translated['translations'];\n"; + $translatedCode .= " \$data['original_locale'] = \$translated['source_language'];\n"; + $translatedCode .= " }\n "; + } + + return $translatedCode; + } + + protected function generateCreateIsActiveApprovedCode($model, $useIsActive, $useApprovedStatus) + { + + $saveCode = "\$motive = 'Registro Inicial';\n"; + + if ($useIsActive) { + $saveCode .= " if (\$item->is_active) {\n"; + $saveCode .= " StatusService::active(\$item, \$motive, Auth::user()->id);\n"; + $saveCode .= " } else {\n"; + $saveCode .= " StatusService::deactive(\$item, \$motive, Auth::user()->id);\n"; + $saveCode .= " }\n"; + } + if ($useApprovedStatus) { + $saveCode .= " StatusService::analisys(\$item, \$motive, Auth::user()->id);\n"; + } + return $saveCode; + } + + protected function generateSaveTranslationsCode($attributes) + { + + $translatedAttributes = array_filter($attributes, function ($attr) { + return isset($attr['translated']) && $attr['translated'] === true; + }); + + $saveTranslationsCode = ""; + + foreach ($translatedAttributes as $attribute) { + $name = $attribute['name']; + $nameTranslatedVar = "{$name}Translateds"; + + // Gerar código dinamicamente para salvar as traduções + $saveTranslationsCode .= "if (\${$nameTranslatedVar}) {\n"; + $saveTranslationsCode .= " \$item->setTranslations('{$name}_translated', \${$nameTranslatedVar});\n"; + $saveTranslationsCode .= " \$item->save();\n"; + $saveTranslationsCode .= " }\n "; + } + + return $saveTranslationsCode; + } +} diff --git a/app/Console/Commands/GrgsDev/GenerateApiResource.php b/app/Console/Commands/GrgsDev/GenerateApiResource.php new file mode 100644 index 00000000..ba4ecdca --- /dev/null +++ b/app/Console/Commands/GrgsDev/GenerateApiResource.php @@ -0,0 +1,222 @@ +argument('model'); + $jsonPath = base_path("documentation/models/json/{$modelName}.json"); + + if (!File::exists($jsonPath)) { + $this->error("JSON file for model {$modelName} not found at path {$jsonPath}."); + return; + } + + $jsonContent = json_decode(File::get($jsonPath), true); + + if (!$jsonContent) { + $this->error('Invalid JSON content.'); + return; + } + + $attributes = $jsonContent['attributes'] ?? []; + $relations = $jsonContent['relations'] ?? []; + $softDeletes = $jsonContent['softDeletes'] ?? false; + $timestamps = $jsonContent['timestamps'] ?? true; + $version = $jsonContent['version'] ?? 'V1'; + $useIsActive = $jsonContent['useIsActive'] ?? false; + $useApprovedStatus = $jsonContent['useApprovedStatus'] ?? false; + $logsActivity = $jsonContent['logsActivity'] ?? false; + // Gerar API Resource + $this->generateApiResource($modelName, $attributes, $relations, $timestamps, $softDeletes, $version, $useIsActive, $useApprovedStatus, $logsActivity); + + $this->info("API Resource for {$modelName} generated successfully."); + } + + protected function generateApiResource($modelName, $attributes, $relations, bool $hasTimestamps = false, bool $hasSoftDeletes = false, $version, $useIsActive, $useApprovedStatus, $logsActivity) + { + $className = "{$modelName}Resource"; + $namespace = "App\\Http\\Resources\\Api\\{$version}\\{$modelName}"; + $filePath = app_path("Http/Resources/Api/{$version}/{$modelName}/{$className}.php"); + $hasDate = false; + $resourceAttributes = []; + $resourceAttributes[] = "'id' => \$this->id"; + $hasTranslated = false; + foreach ($attributes as $attribute) { + $type = $attribute['type']; + $name = $attribute['name']; + + if (in_array($type, ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $hasDate = true; + $resourceAttributes[] = << [ + 'default' => \$this->{$name}, + 'short' => \$this->{$name} ? Carbon::parse(\$this->{$name})->isoFormat('L') : null, + 'short_with_time' => \$this->{$name} ? Carbon::parse(\$this->{$name})->isoFormat('L LT') : null, + 'human' => \$this->{$name} ? Carbon::parse(\$this->{$name})->diffForHumans() : null, + ] +EOD; + } else { + if (in_array($type, ['time'])) { + $hasDate = true; + $resourceAttributes[] = << \$this->{$name} ? Carbon::parse(\$this->{$name})->toTimeString() : null + EOD; + } else { + if ($type === 'image' || $type === 'file' || $type === 'video' || $type === 'audio') { + $resourceAttributes[] = "'{$name}' => \$this->{$name}"; + $resourceAttributes[] = "'{$name}_url' => \$this->{$name}_url"; + $resourceAttributes[] = "'{$name}_file_name' => \$this->{$name}_file_name"; + $resourceAttributes[] = "'{$name}_file_extension' => \$this->{$name}_file_extension"; + $resourceAttributes[] = "'{$name}_file_size' => \$this->{$name}_file_size"; + } else { + if (in_array($type, ['morphs', 'nullableMorphs', 'numericMorphs', 'nullableNumericMorphs', 'uuidMorphs', 'nullableUuidMorphs', 'ulidMorphs', 'nullableUlidMorphs'])) { + $resourceAttributes[] = "'{$name}_id' => \$this->{$name}_id"; + $resourceAttributes[] = "'{$name}_type' => \$this->{$name}_type"; + } else { + $resourceAttributes[] = "'{$name}' => \$this->{$name}"; + if (isset($attribute['translated']) && $attribute['translated']) { + $hasTranslated = true; + $resourceAttributes[] = "'{$name}_translated' => \$this->{$name}_translated"; + } + } + } + } + } + } + if ($hasTranslated) { + $resourceAttributes[] = "'original_locale' => \$this->original_locale"; + } + + if ($useIsActive) { + $resourceAttributes[] = "'is_active' => \$this->is_active"; + $resourceAttributes[] = "'is_active_text' => \$this->is_active_text"; + } + if ($useApprovedStatus) { + $resourceAttributes[] = "'approved_status' => \$this->approved_status"; + $resourceAttributes[] = "'approved_status_text' => \$this->approved_status_text"; + } + + if ($hasTimestamps) { + $hasDate = true; + $nameTimestamp = 'created_at'; + $resourceAttributes[] = << [ + 'default' => \$this->{$nameTimestamp}, + 'short' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->isoFormat('L') : null, + 'short_with_time' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->isoFormat('L LT') : null, + 'human' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->diffForHumans() : null, + ] + EOD; + $nameTimestamp = 'updated_at'; + $resourceAttributes[] = << [ + 'default' => \$this->{$nameTimestamp}, + 'short' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->isoFormat('L') : null, + 'short_with_time' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->isoFormat('L LT') : null, + 'human' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->diffForHumans() : null, + ] + EOD; + } + if ($hasSoftDeletes) { + $hasDate = true; + $nameTimestamp = 'deleted_at'; + $resourceAttributes[] = << [ + 'default' => \$this->{$nameTimestamp}, + 'short' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->isoFormat('L') : null, + 'short_with_time' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->isoFormat('L LT') : null, + 'human' => \$this->{$nameTimestamp} ? Carbon::parse(\$this->{$nameTimestamp})->diffForHumans() : null, + ] + EOD; + } + // use App\Http\Resources\Api\V1\Example2\Example2Resource; + $resourceImport = ''; + foreach ($relations as $relation) { + if ($relation['type'] === 'belongsTo') { + $resourceAttributes[] = "'{$relation['name']}' => new {$relation['related']}Resource(\$this->whenLoaded('{$relation['name']}'))"; + $resourceImport .= 'use App\\Http\\Resources\\Api\\' . $version . '\\' . $relation['related'] . '\\' . $relation['related'] . 'Resource; '; + $resourceImport .= "\n"; + } elseif ($relation['type'] === 'belongsToMany') { + $resourceAttributes[] = "'{$relation['name']}' => {$relation['related']}Resource::collection(\$this->whenLoaded('{$relation['name']}'))"; + $resourceImport .= 'use App\\Http\\Resources\\Api\\' . $version . '\\' . $relation['related'] . '\\' . $relation['related'] . 'Resource; '; + $resourceImport .= "\n"; + } elseif ($relation['type'] === 'hasMany') { + $resourceAttributes[] = "'{$relation['name']}' => {$relation['related']}Resource::collection(\$this->whenLoaded('{$relation['name']}'))"; + $resourceImport .= 'use App\\Http\\Resources\\Api\\' . $version . '\\' . $relation['related'] . '\\' . $relation['related'] . 'Resource; '; + $resourceImport .= "\n"; + } + + // $resourceAttributes[] = "'{$relation['name']}' => \$this->{$relation['name']}"; + } + if ($useIsActive) { + $relationName = 'active_motives'; + $relationWhen = 'activeMotives'; + $relationRelated = 'ActiveMotive'; + + $resourceAttributes[] = "'{$relationName}' => {$relationRelated}Resource::collection(\$this->whenLoaded('{$relationWhen}'))"; + $resourceImport .= 'use App\\Http\\Resources\\Api\\' . $version . '\\' . $relationRelated . '\\' . $relationRelated . 'Resource; '; + $resourceImport .= "\n"; + } + if ($useApprovedStatus) { + $relationName = 'approved_status_motives'; + $relationWhen = 'approvedMotives'; + + $relationRelated = 'ApprovedStatusMotive'; + + $resourceAttributes[] = "'{$relationName}' => {$relationRelated}Resource::collection(\$this->whenLoaded('{$relationWhen}'))"; + $resourceImport .= 'use App\\Http\\Resources\\Api\\' . $version . '\\' . $relationRelated . '\\' . $relationRelated . 'Resource; '; + $resourceImport .= "\n"; + } + + if ($logsActivity) { + $relationName = 'activities'; + $relationRelated = 'ActivityLog'; + + $resourceAttributes[] = "'{$relationName}' => {$relationRelated}Resource::collection(\$this->whenLoaded('{$relationName}'))"; + $resourceImport .= 'use App\\Http\\Resources\\Api\\' . $version . '\\' . $relationRelated . '\\' . $relationRelated . 'Resource; '; + $resourceImport .= "\n"; + } + $carbonImport = $hasDate ? "use Carbon\Carbon;" : ''; + + $resourceContent = implode(",\n ", $resourceAttributes); + + $classTemplate = <<info("Resource {$className} gerado com sucesso."); + } +} diff --git a/app/Console/Commands/GrgsDev/GenerateFormRequest.php b/app/Console/Commands/GrgsDev/GenerateFormRequest.php new file mode 100644 index 00000000..58f0361b --- /dev/null +++ b/app/Console/Commands/GrgsDev/GenerateFormRequest.php @@ -0,0 +1,656 @@ +argument('model'); + $jsonPath = base_path("documentation/models/json/{$modelName}.json"); + + if (!File::exists($jsonPath)) { + $this->error("JSON file for model {$modelName} not found at path {$jsonPath}."); + return; + } + + $jsonContent = json_decode(File::get($jsonPath), true); + + if (!$jsonContent) { + $this->error('Invalid JSON content.'); + return; + } + + $attributes = $jsonContent['attributes'] ?? []; + $relations = $jsonContent['relations'] ?? []; + $version = $jsonContent['version'] ?? 'V1'; + $softDeletes = $jsonContent['softDeletes'] ?? false; // Verifica se softDeletes está no JSON + $useIsActive = $jsonContent['useIsActive'] ?? false; + $useApprovedStatus = $jsonContent['useApprovedStatus'] ?? false; + + // Gerar Form Requests + $this->generateFormRequests($modelName, $attributes, $relations, $version, $softDeletes, $useIsActive, $useApprovedStatus); + + + $this->info("Form Requests for {$modelName} generated successfully."); + } + + + protected function generateFormRequests($modelName, $attributes, $relations, $version, $softDeletes, $useIsActive, $useApprovedStatus) + { + $hasFile = false; + $hasImage = false; + $hasVideo = false; + if ($useIsActive) { + $this->generateChangeIsActiveRequest($modelName, $version); + } + + if ($useApprovedStatus) { + $this->generateChangeApprovedStatusRequest($modelName, $version); + } + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'file') { + $hasFile = true; + $this->generateChangeRequest($modelName, $attribute, $version); + } + if ($attribute['type'] === 'image' || $attribute['type'] === 'video') { + $hasImage = true; + $this->generateChangeRequest($modelName, $attribute, $version); + } + if ($attribute['type'] === 'video') { + $hasVideo = true; + $this->generateChangeRequest($modelName, $attribute, $version); + } + } + $imageGet = ''; + $videoGet = ''; + $fileGet = ''; + if ($hasImage) { + $imageGet = "\$supportedImageMimes = implode(',', config('image-file.supported_images'));"; + } + if ($hasVideo) { + $videoGet = "\$supportedVideoMimes = implode(',', config('image-file.supported_videos'));"; + } + if ($hasFile) { + $fileGet = "\$supportedFileMimes = implode(',', config('image-file.supported_files'));"; + } + // Gerar Store Request + $this->generateRequest('Store', $modelName, $attributes, $relations, $version, $softDeletes, $imageGet, $videoGet, $fileGet, $useIsActive, $useApprovedStatus); + // Gerar Update Request + $this->generateRequest('Update', $modelName, $attributes, $relations, $version, $softDeletes, $imageGet, $videoGet, $fileGet, $useIsActive, $useApprovedStatus); + } + + protected function generateRequest($type, $modelName, $attributes, $relations, $version, $softDeletes, $imageGet, $videoGet, $fileGet, $useIsActive, $useApprovedStatus) + { + $className = "{$type}{$modelName}Request"; + $namespace = "App\\Http\\Requests\\Api\\{$version}\\{$modelName}"; + + // Caminho do arquivo + $filePath = app_path("Http/Requests/Api/{$version}/{$modelName}/{$className}.php"); + + // Definir as regras baseadas nos atributos e relações + $rules = $this->generateRules($modelName, $attributes, $relations, $type, $softDeletes); + $bodyParameters = $this->generateBodyParameters($attributes, $relations); + $prepareForValidationBoolean = $this->generatePrepareForValidationBoolean($type, $attributes, $relations, $useIsActive, $useApprovedStatus); + $prepareForValidationDate = $this->generatePrepareForValidationDate($attributes, $relations); + // Template da classe do Form Request + $classTemplate = <<merge([ + {$prepareForValidationBoolean} + ]); + + {$prepareForValidationDate} + } + + public function bodyParameters() + { + return [ + {$bodyParameters} + ]; + } +} +EOD; + + // Criar diretório, se não existir + if (!File::isDirectory(dirname($filePath))) { + File::makeDirectory(dirname($filePath), 0755, true); + } + + // Escrever o arquivo + File::put($filePath, $classTemplate); + $this->info("Form Request {$className} gerado com sucesso."); + } + + + protected function generateChangeRequest($modelName, $attribute, $version) + { + if ($attribute['type'] === 'image') { + $supported = "\$supportedImageMimes = implode(',', config('image-file.supported_images'));"; + $rule = "'required|image|mimes:' . \$supportedImageMimes . '|max:2048',"; + } + if ($attribute['type'] === 'video') { + $supported = "\$supportedVideoMimes = implode(',', config('image-file.supported_videos'));"; + $rule = "'required|file|mimes:' . \$supportedVideoMimes . '|max:2048',"; + } + + if ($attribute['type'] === 'file') { + $supported = "\$supportedFileMimes = implode(',', config('image-file.supported_files'));"; + $rule = "'required|file|mimes:' . \$supportedFileMimes . '|max:25600',"; + } + $description = $attribute['description'] ?? 'No description provided.'; + + $attributeCamel = Str::ucfirst(Str::camel($attribute['name'])); + $className = "Change{$modelName}{$attributeCamel}Request"; + $namespace = "App\\Http\\Requests\\Api\\{$version}\\{$modelName}"; + + // Caminho do arquivo + $filePath = app_path("Http/Requests/Api/{$version}/{$modelName}/{$className}.php"); + // Template da classe do Form Request + $classTemplate = << {$rule} + ]; + } + + public function bodyParameters() + { + return [ + '{$attribute['name']}' => [ + 'description' => '{$description}', + ], + ]; + } +} +EOD; + + // Criar diretório, se não existir + if (!File::isDirectory(dirname($filePath))) { + File::makeDirectory(dirname($filePath), 0755, true); + } + + // Escrever o arquivo + File::put($filePath, $classTemplate); + $this->info("Form Request {$className} gerado com sucesso."); + } + + protected function generateChangeIsActiveRequest($modelName, $version) + { + $attributeCamel = Str::ucfirst(Str::camel('is_active')); + $className = "Change{$modelName}{$attributeCamel}Request"; + $namespace = "App\\Http\\Requests\\Api\\{$version}\\{$modelName}"; + + // Caminho do arquivo + $filePath = app_path("Http/Requests/Api/{$version}/{$modelName}/{$className}.php"); + // Template da classe do Form Request + $classTemplate = << + */ + public function rules(): array + { + return [ + 'motive' => 'nullable|string', + ]; + } + + public function bodyParameters() + { + return [ + 'motive' => [ + 'description' => 'Descrição do motivo.', + 'example' => 'Não apresentou a documentação', + ], + ]; + } +} +EOD; + + // Criar diretório, se não existir + if (!File::isDirectory(dirname($filePath))) { + File::makeDirectory(dirname($filePath), 0755, true); + } + + // Escrever o arquivo + File::put($filePath, $classTemplate); + $this->info("Form Request {$className} gerado com sucesso."); + } + + protected function generateChangeApprovedStatusRequest($modelName, $version) + { + $attributeCamel = Str::ucfirst(Str::camel('approved_status')); + $className = "Change{$modelName}{$attributeCamel}Request"; + $namespace = "App\\Http\\Requests\\Api\\{$version}\\{$modelName}"; + + // Caminho do arquivo + $filePath = app_path("Http/Requests/Api/{$version}/{$modelName}/{$className}.php"); + // Template da classe do Form Request + $classTemplate = << + */ + public function rules(): array + { + return [ + 'motive' => 'nullable|string', + ]; + } + + public function bodyParameters() + { + return [ + 'motive' => [ + 'description' => 'Descrição do motivo.', + 'example' => 'Não apresentou a documentação', + ], + ]; + } +} +EOD; + + // Criar diretório, se não existir + if (!File::isDirectory(dirname($filePath))) { + File::makeDirectory(dirname($filePath), 0755, true); + } + + // Escrever o arquivo + File::put($filePath, $classTemplate); + $this->info("Form Request {$className} gerado com sucesso."); + } + + protected function generateBodyParameters($attributes, $relations) + { + $bodyParams = []; + $body = ''; + foreach ($attributes as $attribute) { + if (isset($attribute['validate']) && !$attribute['validate']) { + continue; + } + + $description = $attribute['description'] ?? 'No description provided.'; + $example = $attribute['example'] ?? 'No example provided.'; + $name = $attribute['name']; + $texts = []; + if (!in_array($attribute['type'], ['morphs', 'nullableMorphs', 'numericMorphs', 'nullableNumericMorphs', 'uuidMorphs', 'nullableUuidMorphs', 'ulidMorphs', 'nullableUlidMorphs'])) { + if ($attribute['type'] === 'image' || $attribute['type'] === 'video' || $attribute['type'] === 'file') { + $body .= "'{$name}' => [ + 'description' => '{$description}', + ],\n "; + } else { + $body .= "'{$name}' => [ + 'description' => '{$description}', + 'example' => '{$example}' + ],\n "; + } + } + } + + // Adicionar as regras das relações + foreach ($relations as $relation) { + if ($relation['type'] === 'belongsTo') { + $description = $relation['description'] ?? 'No description provided.'; + $example = $relation['example'] ?? 'No example provided.'; + $nameRelation = $relation['name'] . '_id'; + $body .= "'{$nameRelation}' => [ + 'description' => '{$description}', + 'example' => '{$example}' + ],\n "; + } elseif ($relation['type'] === 'belongsToMany') { + $description = $relation['description'] ?? 'No description provided.'; + $example = $relation['example'] ?? 'No example provided.'; + $nameRelation = $relation['name'] . '.*'; + $body .= "'{$nameRelation}' => [ + 'description' => '{$description}', + 'example' => '{$example}' + ],\n "; + } + } + + return $body; + } + + protected function generatePrepareForValidationBoolean($type, $attributes, $relations, $useIsActive, $useApprovedStatus) + { + $forValidation = ''; + foreach ($attributes as $attribute) { + if (isset($attribute['validate']) && !$attribute['validate']) { + continue; + } + + if ($attribute['type'] === 'boolean') { + $name = $attribute['name']; + $forValidation .= "'$name' => \$this->boolean('$name'),\n "; + } + } + if ($type === 'Store') { + if ($useIsActive) { + $name = 'is_active'; + $forValidation .= "'$name' => 0,\n "; + } + if ($useApprovedStatus) { + $name = 'approved_status'; + $forValidation .= "'$name' => '1',\n "; + } + } + + return $forValidation; + } + + protected function generatePrepareForValidationDate($attributes, $relations) + { + $forValidation = ''; + foreach ($attributes as $attribute) { + if (isset($attribute['validate']) && !$attribute['validate']) { + continue; + } + + $name = $attribute['name']; + + // Controle para atributos do tipo date, datetime, timestamp ou time + if (in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $parsedFunction = $attribute['type'] === 'time' ? 'parseTime' : 'parseDate'; // Determina qual função usar + $camelName = Str::ucfirst(Str::camel($name)); + // Geração do código para o atributo + $forValidation .= "if (\$this->input('$name')) {\n"; + $forValidation .= " \$parsed{$camelName} = DateService::{$parsedFunction}(\$this->input('$name'));\n"; + $forValidation .= " if (\$parsed{$camelName}) {\n"; + $forValidation .= " \$this->merge([\n"; + $forValidation .= " '$name' => \$parsed{$camelName}->setTimezone('UTC')->toISOString(),\n"; + $forValidation .= " ]);\n"; + $forValidation .= " } else {\n"; + $forValidation .= " \$this->merge([\n"; + $forValidation .= " '$name' => 'error date', // handle error case appropriately\n"; + $forValidation .= " ]);\n"; + $forValidation .= " }\n"; + $forValidation .= " }\n\n "; + } + } + + return $forValidation; + } + + protected function generateRules($modelName, $attributes, $relations, $type, $softDeletes) + { + $rules = []; + + foreach ($attributes as $attribute) { + if (isset($attribute['validate']) && !$attribute['validate']) { + continue; + } + $name = $attribute['name']; + $attributeType = $attribute['type']; + if (!in_array($attributeType, ['morphs', 'nullableMorphs', 'numericMorphs', 'nullableNumericMorphs', 'uuidMorphs', 'nullableUuidMorphs', 'ulidMorphs', 'nullableUlidMorphs'])) { + if ($type === 'Update') { + $required = 'sometimes|nullable'; + } else { + $required = $attribute['required'] ? 'required' : 'nullable'; + } + + $unique = $attribute['unique'] ?? false; + $nullable = $attribute['nullable'] ? 'nullable' : 'required'; + $rule = $required . '|'; + switch ($attributeType) { + case 'integer': + case 'bigInteger': + case 'tinyInteger': + case 'smallInteger': + case 'mediumInteger': + case 'unsignedInteger': + case 'unsignedBigInteger': + case 'unsignedTinyInteger': + case 'unsignedSmallInteger': + case 'unsignedMediumInteger': + $rule .= 'integer'; + if (!empty($attribute['min'])) { + $rule .= "|min:{$attribute['min']}"; + } + if (!empty($attribute['max'])) { + $rule .= "|max:{$attribute['max']}"; + } + break; + + case 'boolean': + $rule .= 'boolean'; + break; + + case 'decimal': + case 'float': + case 'double': + $precision = $attribute['precision'] ?? 8; + $scale = $attribute['scale'] ?? 2; + $rule .= "numeric"; + $rule .= "|digits_between:0,{$precision}"; + if (!empty($scale)) { + $rule .= "regex:/^\d+(\.\d{1,{$scale}})?$/"; + } + break; + + case 'string': + case 'char': + $length = $attribute['length'] ?? 255; + $values = $attribute['values'] ?? ''; + $rule .= "string"; + $rule .= "|max:$length"; + if ($values) { + $rule .= '|in:' . implode(',', $values); + } + + + break; + + case 'email': + $length = $attribute['length'] ?? 255; + $rule .= "email"; + $rule .= "|max:$length"; + break; + + case 'text': + case 'mediumText': + case 'longText': + $rule .= 'string'; + break; + + case 'enum': + $rule .= 'in:' . implode(',', $attribute['values']); + break; + + case 'date': + case 'datetime': + case 'timestamp': + case 'dateTime': + case 'timeStamp': + + $rule .= 'date'; + break; + + case 'time': + $rule .= 'date'; + break; + + case 'json': + case 'jsonb': + $rule .= 'json'; + break; + + case 'uuid': + $rule .= 'uuid'; + break; + + case 'binary': + $rule .= 'string'; // Laravel não tem regra explícita para binary, trata como string. + break; + + case 'file': + $length = $attribute['length'] ?? 25600; + $rule .= 'file'; + $rule .= "|mimes:' . \$supportedFileMimes . "; + $rule .= "'|max:$length"; + break; + + case 'image': + $length = $attribute['length'] ?? 2048; + $rule .= 'image'; + $rule .= "|mimes:' . \$supportedImageMimes . "; + + // $rule .= '|mimes:jpg,jpeg,png,svg,ifc,dwg,dxf'; + $rule .= "'|max:$length"; + break; + case 'video': + $length = $attribute['length'] ?? 2048; + $rule .= 'file'; + $rule .= "|mimes:' . \$supportedVideoMimes . "; + + // $rule .= '|mimes:jpg,jpeg,png,svg,ifc,dwg,dxf'; + $rule .= "'|max:$length"; + break; + + case 'ipAddress': + $rule .= 'ip'; + break; + + case 'macAddress': + $rule .= 'mac_address'; + break; + + case 'geometry': + case 'point': + case 'linestring': + case 'polygon': + case 'geometryCollection': + case 'multipoint': + case 'multilinestring': + case 'multipolygon': + // Não há regras de validação específicas para tipos geométricos no Laravel. + break; + + + default: + $rule = "{$nullable}"; + break; + } + //|' . Rule::unique(Company::class)->whereNull('deleted_at')->ignore($this->company_id) + if ($unique) { + if ($type === 'Update') { + $modelSnakedId = Str::snake($modelName) . '_id'; + if ($softDeletes) { + $rule .= "|' . Rule::unique({$modelName}::class)->whereNull('deleted_at')->ignore(\$this->{$modelSnakedId})"; + } else { + $rule .= "|' . Rule::unique({$modelName}::class)->ignore(\$this->{$modelSnakedId})"; + } + } else { + $rule .= "|' . Rule::unique({$modelName}::class,'{$name}')"; + } + + // $rule .= "|unique:{$modelName}::class,{$name}"; + } else { + $rule .= "'"; + } + + $rules[] = "'{$name}' => '{$rule}"; + } + } + + // Adicionar as regras das relações + foreach ($relations as $relation) { + $tableName = Str::snake(Str::pluralStudly($relation['related'])); + if ($relation['type'] === 'belongsTo') { + $rules[] = "'{$relation['name']}_id' => 'required|exists:{$tableName},id'"; + } elseif ($relation['type'] === 'belongsToMany') { + $rules[] = "'{$relation['name']}' => 'nullable|array'"; + $rules[] = "'{$relation['name']}.*' => 'exists:{$tableName},id'"; + } + } + + return "[\n " . implode(",\n ", $rules) . "\n ]"; + } +} diff --git a/app/Console/Commands/GrgsDev/GenerateMigration.php b/app/Console/Commands/GrgsDev/GenerateMigration.php new file mode 100644 index 00000000..c63f7d8e --- /dev/null +++ b/app/Console/Commands/GrgsDev/GenerateMigration.php @@ -0,0 +1,406 @@ +argument('model'); + $jsonPath = base_path("documentation/models/json/{$modelName}.json"); + + if (!File::exists($jsonPath)) { + $this->error("JSON file for model {$modelName} not found at path {$jsonPath}."); + return; + } + + $jsonContent = json_decode(File::get($jsonPath), true); + + if (!$jsonContent) { + $this->error('Invalid JSON content.'); + return; + } + + $version = $jsonContent['version'] ?? 'V1'; + // Gerar a Migration + $this->generateMigration($jsonContent, $modelName, $version); + } + + + protected function generateMigration(array $modelData, string $modelName, $version) + { + $tableName = Str::snake(Str::pluralStudly($modelName)); + + $attributes = $modelData['attributes']; + $relations = $modelData['relations'] ?? []; + $softDeletes = $modelData['softDeletes'] ?? false; + $timestamps = $modelData['timestamps'] ?? false; + $useIsActive = $modelData['useIsActive'] ?? false; + $useApprovedStatus = $modelData['useApprovedStatus'] ?? false; + + $migrationContent = $this->generateMigrationContent($attributes, $relations, $modelName, $tableName, $softDeletes, $timestamps, $version, $useIsActive, $useApprovedStatus); + + $timestamp = now()->format('Y_m_d_His'); + $migrationFileName = "{$timestamp}_create_{$tableName}_table.php"; + + File::put(database_path("migrations/{$migrationFileName}"), $migrationContent); + $this->info("Migration {$migrationFileName} gerado com sucesso."); + } + + protected function generateMigrationContent(array $attributes, array $relations, string $ModelName, string $tableName, bool $softDeletes, bool $timestamps, $version, bool $useIsActive, bool $useApprovedStatus) + { + $fields = $this->generateFields($attributes); + $isActiveStr = $useIsActive ? "\$table->boolean('is_active')->nullable()->default(0);" : ''; + $approvedStatusStr = $useApprovedStatus ? "\$table->string('approved_status')->nullable()->default('1');" : ''; + $relationsFields = $this->generateRelationFields($relations); + $softDeletesStr = $softDeletes ? "\$table->softDeletes();" : ''; + $softDeletesParent = $softDeletes ? "\$table->boolean('deleted_by_parent')->default(0);" : "\$table->boolean('deleted_by_parent')->default(0);"; + $timestampsStr = $timestamps ? "\$table->timestamps();" : ''; + $translatedSchema = $this->generateTranslationsSchema($ModelName, $attributes); + $dropTranslatedSchema = ''; + $useModel = ''; + if ($translatedSchema) { + $table = Str::snake($ModelName) . '_translations'; + $dropTranslatedSchema = "Schema::dropIfExists('{$table}');"; + $useModel = "use App\Models\\{$ModelName};"; + } + $migrationTemplate = <<id(); + + {$fields} + {$isActiveStr} + {$approvedStatusStr} + {$relationsFields} + {$softDeletesParent} + {$softDeletesStr} + {$timestampsStr} + }); + + {$translatedSchema} + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + {$dropTranslatedSchema} + Schema::dropIfExists('{$tableName}'); + } +}; +EOT; + + return $migrationTemplate; + } + + protected function generateFields(array $attributes) + { + $fields = ''; + $hasTranslated = false; + foreach ($attributes as $attribute) { + $type = $this->getMigrationType($attribute['type'], $attribute); + $nullable = $attribute['nullable'] ? '->nullable()' : ''; + $unique = $attribute['unique'] ?? false ? '->unique()' : ''; + $default = isset($attribute['default']) ? '->default(' . $this->formatDefaultValue($attribute['default']) . ')' : ''; + $field = "\$table->{$type}{$nullable}{$unique}{$default};"; + $fields .= "{$field}\n "; + if (isset($attribute['translated']) && $attribute['translated']) { + $hasTranslated = true; + $attribute['name'] = $attribute['name'] . '_translated'; + $type = $this->getMigrationType($attribute['type'], $attribute); + $nullable = '->nullable()'; + $field = "\$table->{$type}{$nullable};"; + $fields .= "{$field}\n "; + } + if ($attribute['type'] === 'image' || $attribute['type'] === 'video' || $attribute['type'] === 'file') { + $text = $attribute['name'] . '_file_name'; + $type = "string('{$text}')"; + $nullable = '->nullable()'; + $field = "\$table->{$type}{$nullable};"; + $fields .= "{$field}\n "; + + $text = $attribute['name'] . '_file_extension'; + $type = "string('{$text}')"; + $nullable = '->nullable()'; + $field = "\$table->{$type}{$nullable};"; + $fields .= "{$field}\n "; + + $text = $attribute['name'] . '_file_size'; + $type = "integer('{$text}')"; + $nullable = '->nullable()'; + $field = "\$table->{$type}{$nullable};"; + $fields .= "{$field}\n "; + } + } + if ($hasTranslated) { + $field = "\$table->string('original_locale')->nullable();"; + $fields .= "{$field}\n "; + } + return $fields; + } + + protected function getMigrationType($type, $attribute) + { + switch ($type) { + case 'bigInteger': + case 'integer': + case 'tinyInteger': + case 'smallInteger': + case 'mediumInteger': + case 'unsignedBigInteger': + case 'unsignedInteger': + case 'unsignedMediumInteger': + case 'unsignedSmallInteger': + case 'unsignedTinyInteger': + return "{$type}('{$attribute['name']}')"; + + case 'morphs': + return "morphs('{$attribute['name']}')"; + case 'nullableMorphs': + return "nullableMorphs('{$attribute['name']}')"; + case 'numericMorphs': + return "numericMorphs('{$attribute['name']}')"; + case 'nullableNumericMorphs': + return "nullableNumericMorphs('{$attribute['name']}')"; + case 'uuidMorphs': + return "uuidMorphs('{$attribute['name']}')"; + case 'nullableUuidMorphs': + return "nullableUuidMorphs('{$attribute['name']}')"; + case 'ulidMorphs': + return "ulidMorphs('{$attribute['name']}')"; + case 'nullableUlidMorphs': + return "nullableUlidMorphs('{$attribute['name']}')"; + + case 'boolean': + return "boolean('{$attribute['name']}')"; + + case 'decimal': + $precision = $attribute['precision'] ?? 8; + $scale = $attribute['scale'] ?? 2; + return "decimal('{$attribute['name']}', $precision, $scale)"; + + case 'float': + return "float('{$attribute['name']}')"; + + case 'double': + return "double('{$attribute['name']}')"; + + case 'string': + $length = $attribute['length'] ?? 255; + return "string('{$attribute['name']}', $length)"; + case 'email': + $length = $attribute['length'] ?? 255; + return "string('{$attribute['name']}', $length)"; + + case 'text': + return "text('{$attribute['name']}')"; + + case 'mediumText': + return "mediumText('{$attribute['name']}')"; + + case 'longText': + return "longText('{$attribute['name']}')"; + + case 'binary': + return "binary('{$attribute['name']}')"; + + case 'date': + return "date('{$attribute['name']}')"; + + case 'datetime': + return "dateTime('{$attribute['name']}')"; + case 'dateTime': + return "dateTime('{$attribute['name']}')"; + + case 'timestamp': + return "timestamp('{$attribute['name']}')"; + case 'timeStamp': + return "timestamp('{$attribute['name']}')"; + + case 'time': + return "time('{$attribute['name']}')"; + + case 'year': + return "year('{$attribute['name']}')"; + + case 'json': + return "json('{$attribute['name']}')"; + + case 'jsonb': + return "jsonb('{$attribute['name']}')"; + + case 'uuid': + return "uuid('{$attribute['name']}')"; + + case 'char': + $length = $attribute['length'] ?? 255; + return "char('{$attribute['name']}', $length)"; + + case 'enum': + $enumValues = implode(", ", array_map(fn($v) => "'$v'", $attribute['values'])); + return "enum('{$attribute['name']}', [$enumValues])"; + + case 'set': + $setValues = implode(", ", array_map(fn($v) => "'$v'", $attribute['values'])); + return "set('{$attribute['name']}', [$setValues])"; + + case 'geometry': + return "geometry('{$attribute['name']}')"; + + case 'point': + return "point('{$attribute['name']}')"; + + case 'linestring': + return "lineString('{$attribute['name']}')"; + + case 'polygon': + return "polygon('{$attribute['name']}')"; + + case 'geometryCollection': + return "geometryCollection('{$attribute['name']}')"; + + case 'multipoint': + return "multiPoint('{$attribute['name']}')"; + + case 'multilinestring': + return "multiLineString('{$attribute['name']}')"; + + case 'multipolygon': + return "multiPolygon('{$attribute['name']}')"; + + case 'ipAddress': + return "ipAddress('{$attribute['name']}')"; + + case 'macAddress': + return "macAddress('{$attribute['name']}')"; + + case 'foreignId': + return "foreignId('{$attribute['name']}')"; + + case 'foreignUuid': + return "foreignUuid('{$attribute['name']}')"; + + // Tratamento de tipos 'file' e 'image' como string + case 'file': + case 'image': + case 'video': + return "string('{$attribute['name']}')"; + + default: + throw new \Exception("Tipo de dado desconhecido: {$type}"); + } + } + + protected function formatDefaultValue($default) + { + // Format the default value for the migration + if (is_string($default)) { + return "'{$default}'"; + } + if (is_null($default)) { + return 'null'; + } + return $default; + } + + protected function generateRelationFields(array $relations) + { + $relationsFields = ''; + foreach ($relations as $relation) { + $relationType = $relation['type']; + $relatedModel = $relation['related']; + $relatedTable = Str::snake(Str::pluralStudly($relatedModel)); + $foreignKey = Str::snake($relation['name']) . '_id'; + + switch ($relationType) { + case 'belongsTo': + $relationsFields .= "\$table->foreignId('{$foreignKey}')->constrained('{$relatedTable}');\n "; + break; + case 'belongsToMany': + $pivotTable = $this->getPivotTableName($relatedTable, Str::snake(Str::pluralStudly($relation['name']))); + $relationsFields .= "\n Schema::create('{$pivotTable}', function (Blueprint \$table) use (\$table) { + \$table->id(); + \$table->foreignId('{$foreignKey}')->constrained('{$relatedTable}'); + \$table->foreignId('{$relatedModel}_id')->constrained('{$relatedTable}'); + \$table->timestamps(); + });\n"; + break; + } + } + + return $relationsFields; + } + + protected function getPivotTableName(string $relatedTable, string $currentTable) + { + $tables = [$relatedTable, $currentTable]; + sort($tables); + return implode('_', $tables); + } + + protected function generateTranslationsSchema($model, $attributes) + { + $relatedTable = Str::snake(Str::pluralStudly($model)); + $table = Str::snake($model); + + $fields = $this->generateFieldsTranslate($attributes); + $translatedSchema = ''; + if (!$fields) { + return $translatedSchema; + } + $translatedSchema = "Schema::create('{$table}_translations', function (Blueprint \$table) { + \$table->id(); + + \$table->foreignIdFor({$model}::class, 'item_id') + ->constrained('{$relatedTable}') + ->cascadeOnDelete(); + + \$table->string('locale'); + + {$fields} + \$table->unique(['item_id', 'locale']); + });"; + return $translatedSchema; + } + + protected function generateFieldsTranslate(array $attributes) + { + $fields = ''; + foreach ($attributes as $attribute) { + if (isset($attribute['translated']) && $attribute['translated']) { + $attribute['name'] = $attribute['name'] . '_translated'; + $type = $this->getMigrationType($attribute['type'], $attribute); + $nullable = '->nullable()'; + $field = "\$table->{$type}{$nullable};"; + $fields .= "{$field}\n "; + } + } + return $fields; + } +} diff --git a/app/Console/Commands/GrgsDev/GenerateModelContract.php b/app/Console/Commands/GrgsDev/GenerateModelContract.php new file mode 100644 index 00000000..f6a7bc3d --- /dev/null +++ b/app/Console/Commands/GrgsDev/GenerateModelContract.php @@ -0,0 +1,1432 @@ +argument('model'); + $jsonPath = base_path("documentation/models/json/{$modelName}.json"); + + if (!File::exists($jsonPath)) { + $this->error("JSON file for model {$modelName} not found at path {$jsonPath}."); + return; + } + + $jsonContent = json_decode(File::get($jsonPath), true); + + if (!$jsonContent) { + $this->error('Invalid JSON content.'); + return; + } + + $version = $jsonContent['version'] ?? 'V1'; + $logsActivity = $jsonContent['logsActivity'] ?? false; + $clearsResponseCache = $jsonContent['clearsResponseCache'] ?? false; + // Gerar o Model Contract abstract class + $this->generateModelContract($jsonContent, $modelName, $version, $logsActivity, $clearsResponseCache); + } + + ///////////////////// + + protected function generateModelContract($data, $modelName, $version, $logsActivity, $clearsResponseCache) + { + $attributes = $data['attributes']; + $relations = $data['relations'] ?? []; + $softDeletes = $data['softDeletes'] ?? false; // Verifica se softDeletes está no JSON + $timestamps = $data['timestamps'] ?? false; + $useIsActive = $data['useIsActive'] ?? false; + $useApprovedStatus = $data['useApprovedStatus'] ?? false; + + $hasImages = false; + $imageConsts = ''; + $fileConsts = ''; + + $fillable = []; + $casts = []; + $appends = []; + $relationMethods = []; + $hasSearchAble = false; + $hasTranslated = false; + $hasBoolean = false; + // Prepara os atributos + foreach ($attributes as $attribute) { + $name = $attribute['name']; + $type = $attribute['type']; + if ($type === 'boolean') { + $hasBoolean = true; + } + if (isset($attribute['translated']) && $attribute['translated']) { + $hasTranslated = true; + } + if (isset($attribute['searchAble']) && $attribute['searchAble']) { + $hasSearchAble = true; + } + if (!in_array($type, ['morphs', 'nullableMorphs', 'numericMorphs', 'nullableNumericMorphs', 'uuidMorphs', 'nullableUuidMorphs', 'ulidMorphs', 'nullableUlidMorphs'])) { + $casts[$name] = $this->getCastType($type, $attribute); + } + + if ($type === 'image' || $type === 'video' || $type === 'file') { + $fillable[] = "'$name',"; + + $nameImageAux = $name . '_file_name'; + $fillable[] = "'$nameImageAux',"; + $nameImageAux = $name . '_file_size'; + $fillable[] = "'$nameImageAux',"; + $nameImageAux = $name . '_file_extension'; + $fillable[] = "'$nameImageAux',"; + + $hasImages = true; + $snakeModel = Str::of($modelName)->snake(); //snake(strtolower($modelName)); + $upperName = strtoupper($name); + $appends[] = "'{$name}_url'"; + $imageConsts .= "const {$upperName}_STORAGE = '{$type}/{$snakeModel}_{$name}';\n "; + } else { + if (in_array($type, ['morphs', 'nullableMorphs', 'numericMorphs', 'nullableNumericMorphs', 'uuidMorphs', 'nullableUuidMorphs', 'ulidMorphs', 'nullableUlidMorphs'])) { + $nameAux = $name . '_id'; + $fillable[] = "'$nameAux',"; + $nameAux = $name . '_type'; + $fillable[] = "'$nameAux',"; + } else { + $fillable[] = "'$name',"; + } + } + } + $useTranslated = ''; + $useHasTranslations = ''; + if ($hasTranslated) { + $fillable[] = "'original_locale',"; + $casts['original_locale'] = 'string'; + $useTranslated = "use LaravelLang\Models\HasTranslations;"; + $useHasTranslations = "use HasTranslations;"; + } + if ($useIsActive) { + $imageConsts .= "const IS_ACTIVE_TRUE = '1';\n "; + $imageConsts .= "const IS_ACTIVE_FALSE = '0';\n "; + $imageConsts .= "const IS_ACTIVE_TEXT = ['0' => 'INACTIVE', '1' => 'ACTIVE'];\n "; + + $fillable[] = "'is_active',"; + $casts['is_active'] = 'boolean'; + $appends[] = "'is_active_text'"; + } + if ($useApprovedStatus) { + $imageConsts .= "const APPROVED_STATUS_ANALISYS = '1';\n "; + $imageConsts .= "const APPROVED_STATUS_APPROVED = '2';\n "; + $imageConsts .= "const APPROVED_STATUS_UNAPPROVED = '3';\n "; + $imageConsts .= "const APPROVED_STATUS_BLOCKED = '4';\n "; + $imageConsts .= "const APPROVED_STATUS_CANCELED = '5';\n "; + $imageConsts .= "const APPROVED_STATUS_TEXT = ['1' => 'ANALISYS', '2' => 'APPROVED', '3' => 'UNAPPROVED', '4' => 'BLOCKED', '5' => 'CANCELED'];\n "; + + $fillable[] = "'approved_status',"; + $casts['approved_status'] = 'string'; + $appends[] = "'approved_status_text'"; + } + if ($softDeletes) { + $fillable[] = "'deleted_by_parent',"; + $casts['deleted_by_parent'] = 'boolean'; + } else { + $fillable[] = "'deleted_by_parent',"; + $casts['deleted_by_parent'] = 'boolean'; + } + //prepara scopes + $scopeSearch = ''; + if ($hasSearchAble) { + $scopeSearch = $this->generateSearchScope($attributes, $timestamps, $softDeletes, $useIsActive, $useApprovedStatus); + } + $scopeBoolean = ''; + if ($hasBoolean) { + $scopeBoolean = $this->generateBooleanScopes($attributes); + } + + + $scopeActiveApproved = $this->generateActiveApprovedScopes($useIsActive, $useApprovedStatus); + $scopeDate = $this->generateDateScopes($attributes, $timestamps, $softDeletes, $useIsActive, $useApprovedStatus); + + $allowedFilters = $this->generateAllowedFilters($attributes, $timestamps, $softDeletes, $hasSearchAble, $useIsActive, $useApprovedStatus); + $allowedIncludes = $this->generateAllowedIncludes($relations, $logsActivity, $useIsActive, $useApprovedStatus); + $defaultIncludes = $this->generateDefaultIncludes($relations, $logsActivity, $useIsActive, $useApprovedStatus); + $allowedSorts = $this->generateAllowedSorts($attributes, $timestamps, $softDeletes, $useIsActive); + $defaultSorts = $this->generateDefaultSorts($attributes); + + $useRelations = ''; + // Prepara os relacionamentos + foreach ($relations as $relation) { + $relationName = $relation['name']; + $relationType = $relation['type']; + $relatedModel = $relation['related']; + $relationMethods[] = $this->generateRelationMethod($relationName, $relationType, $relatedModel); + if ($relatedModel) { + $useRelations .= "use App\Models\\$relatedModel;\n"; + } + } + + $useRelationsIsActiveApprovedStatus = ''; + $useRelationsIsActive = ""; + $useRelationsApprovedStatus = ""; + if ($useIsActive) { + $useRelationsIsActive = "use App\Models\ActiveHistoric;\n"; + } + if ($useApprovedStatus) { + $useRelationsApprovedStatus = "use App\Models\ApproveHistoric;\n"; + } + + $useRelationsIsActiveApprovedStatus = $this->generateRelationIsActiveApprovedStatus($useIsActive, $useApprovedStatus); + + // Define o uso do SoftDeletes + $softDeletesTrait = $softDeletes ? 'use SoftDeletes;' : ''; + $softDeletesImport = $softDeletes ? "use Illuminate\\Database\\Eloquent\\SoftDeletes;" : ''; + $cascadeSoftDeletesTrait = $softDeletes ? 'use CascadeSoftDeletes;' : ''; + $cascadeSoftDeletesImport = $softDeletes ? "use App\\Traits\\CascadeSoftDeletes;" : ''; + + //Define o uso do logs activity + $logsActivityOptionsImport = $logsActivity ? "use Spatie\\Activitylog\\LogOptions;" : ''; + $logsActivityImport = $logsActivity ? "use Spatie\\Activitylog\\Traits\LogsActivity;" : ''; + $logsActivityTrait = $logsActivity ? 'use LogsActivity;' : ''; + + //Define o uso de clears cache + $clearsResponseCacheTraitImport = $clearsResponseCache ? "use App\\Traits\\ClearsResponseCache;" : ''; + $clearsResponseCacheTrait = $clearsResponseCache ? 'use ClearsResponseCache;' : ''; + + $storageImport = $hasImages ? "use Illuminate\\Support\\Facades\\Storage;" : ''; + + // Construa o conteúdo do modelo + $modelContent = << $value) { + $modelContent .= "\n '$key' => '$value',"; + } + + $modelContent .= "\n ];\n\n // APPENDS\n"; + + $modelContent .= " protected \$appends = [\n "; + + // Adicionar os appends manualmente + $modelContent .= implode(",\n ", $appends); + + $modelContent .= "\n ];\n\n"; + if ($useIsActive) { + $modelContent .= $this->generateAppendActiveMethod(); + $modelContent .= "\n\n"; + } + if ($useApprovedStatus) { + $modelContent .= $this->generateAppendApprovedMethod(); + $modelContent .= "\n\n"; + } + // Adicionando a função para image URL + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'image' || $attribute['type'] === 'video' || $attribute['type'] === 'file') { + $name = $attribute['name']; + $modelContent .= $this->generateImageUrlMethod($name); + $modelContent .= "\n\n"; + } + } + + // Adicionando os métodos de relacionamento + if ($relationMethods || $useIsActive || $useApprovedStatus) { + $modelContent .= "\n // INCLUDES\n "; + } + $modelContent .= implode("\n\n ", $relationMethods); + $modelContent .= $useRelationsIsActiveApprovedStatus; + // Adiciona scopes para SoftDeletes se for habilitado + if ($softDeletes) { + $modelContent .= "\n "; + $modelContent .= <<withTrashed(); + } + + public function scopeOnlyTrashed(\$query) + { + return \$query->onlyTrashed(); + } + + // QUERY BUILDER + {$allowedFilters} + {$allowedIncludes} + {$allowedSorts} + {$defaultSorts} + {$defaultIncludes} + + EOT; + } else { + $modelContent .= "\n "; + $modelContent .= <<logFillable()->dontSubmitEmptyLogs(); + } + + EOT; + } + $modelContent .= "\n}\n"; + // Garante que o diretório 'Contracts' existe + $contractsPath = app_path('Models/AbstractContracts'); + File::ensureDirectoryExists($contractsPath); + $abstractModelPath = "{$contractsPath}/{$modelName}.php"; + File::put($abstractModelPath, $modelContent); + + if ($hasTranslated) { + $this->generateModelTranslation($attributes, $modelName, $version); + } + // Gerar o Model concret class + $this->generateModel($modelName, $version); + } + + protected function getCastType($type, $attribute) + { + switch ($type) { + case 'bigIncrements': + case 'bigInteger': + case 'increments': + case 'integer': + case 'mediumIncrements': + case 'mediumInteger': + case 'smallIncrements': + case 'smallInteger': + case 'tinyIncrements': + case 'tinyInteger': + case 'unsignedBigInteger': + case 'unsignedInteger': + case 'unsignedMediumInteger': + case 'unsignedSmallInteger': + case 'unsignedTinyInteger': + case 'year': + return 'integer'; + + case 'decimal': + case 'unsignedDecimal': + $precision = $attribute['precision'] ?? 8; + $scale = $attribute['scale'] ?? 2; + + return "decimal:{$precision},{$scale}"; + + case 'float': + case 'double': + return 'float'; // 'double' também pode ser usado aqui dependendo do uso + + case 'boolean': + return 'boolean'; + + case 'string': + case 'char': + case 'text': + case 'mediumText': + case 'longText': + case 'enum': + case 'uuid': + return 'string'; + + case 'json': + case 'jsonb': + return 'json'; // ou 'array' ou 'object' dependendo do uso + + case 'date': + return 'date'; + + case 'datetime': + case 'dateTime': + case 'dateTimeTz': + return 'datetime'; + + case 'timestamp': + case 'timeStamp': + case 'timestampTz': + return 'datetime'; + + case 'time': + case 'timeTz': + return 'string'; + + case 'ipAddress': + return 'ipAddress'; + + case 'macAddress': + return 'macAddress'; + + case 'binary': + case 'geometry': + case 'geometryCollection': + case 'lineString': + case 'multiLineString': + case 'multiPoint': + case 'multiPolygon': + case 'point': + case 'polygon': + return null; // Não há cast nativo para tipos geométricos + + default: + return 'string'; // Um fallback padrão para tipos não especificados + } + } + + protected function generateImageUrlMethod($attribute) + { + $capitalLetter = ucwords($attribute); + $upperName = strtoupper($attribute); + + return <<{$attribute}) { + return null; // asset('noimage.png'); + } + return Storage::url(\$storage . \$this->{$attribute}); + } +EOT; + } + + protected function generateAppendActiveMethod() + { + return <<is_active]); + } +EOT; + } + + protected function generateAppendApprovedMethod() + { + return <<approved_status]); + } +EOT; + } + + protected function generateSearchScope($attributes, $timestamps, $softDeletes) + { + $scopeSearch = " + public function scopeSearch(Builder \$builder, string \$search) + { + \$parsedDate = DateService::parseDate(\$search); + + if (\$parsedDate) { + \$builder->where(function (\$query) use (\$parsedDate) {"; + + // Adiciona as condições para os atributos do tipo date, timestamp ou datetime + foreach ($attributes as $attribute) { + if (isset($attribute['searchAble']) && $attribute['searchAble'] && in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $name = $attribute['name']; + $scopeSearch .= " + \$query->whereDate('$name', \$parsedDate->format('Y-m-d'));"; + } + } + if ($timestamps) { + $name = 'created_at'; + $scopeSearch .= " + \$query->whereDate('$name', \$parsedDate->format('Y-m-d'));"; + $name = 'updated_at'; + $scopeSearch .= " + \$query->whereDate('$name', \$parsedDate->format('Y-m-d'));"; + } + if ($softDeletes) { + $name = 'deleted_at'; + $scopeSearch .= " + \$query->whereDate('$name', \$parsedDate->format('Y-m-d'));"; + } + // Finaliza a parte da busca por datas completas + $scopeSearch .= " + }); + } else { + \$builder->where(function (\$query) use (\$search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\\d{1,2}\\/\\d{1,2}\$/', \$search)) { + // Exemplo: 29/03 (dia/mês) + list(\$day, \$month) = explode('/', \$search);"; + + // Adiciona as condições para os atributos do tipo date, timestamp ou datetime para busca parcial de dia/mês + foreach ($attributes as $attribute) { + if (isset($attribute['searchAble']) && $attribute['searchAble'] && in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $name = $attribute['name']; + $scopeSearch .= " + \$query->whereMonth('$name', \$month) + ->whereDay('$name', \$day);"; + } + } + if ($timestamps) { + $name = 'created_at'; + $scopeSearch .= " + \$query->whereMonth('$name', \$month) + ->whereDay('$name', \$day);"; + $name = 'updated_at'; + $scopeSearch .= " + \$query->whereMonth('$name', \$month) + ->whereDay('$name', \$day);"; + } + if ($softDeletes) { + $name = 'deleted_at'; + $scopeSearch .= " + \$query->whereMonth('$name', \$month) + ->whereDay('$name', \$day);"; + } + + // Busca parcial por dia + $scopeSearch .= " + } elseif (preg_match('/^\\d{1,2}\\/\\$/', \$search)) { + // Exemplo: 29/ (somente dia) + \$day = str_replace('/', '', \$search);"; + + foreach ($attributes as $attribute) { + if (isset($attribute['searchAble']) && $attribute['searchAble'] && in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $name = $attribute['name']; + $scopeSearch .= " + \$query->whereDay('$name', \$day);"; + } + } + if ($timestamps) { + $name = 'created_at'; + $scopeSearch .= " + \$query->whereDay('$name', \$day);"; + + $name = 'updated_at'; + $scopeSearch .= " + \$query->whereDay('$name', \$day);"; + } + if ($softDeletes) { + $name = 'deleted_at'; + $scopeSearch .= " + \$query->whereDay('$name', \$day);"; + } + // Busca parcial por mês + $scopeSearch .= " + } elseif (preg_match('/^\\/\\d{1,2}\$/', \$search)) { + // Exemplo: /05 (somente mês) + \$month = str_replace('/', '', \$search);"; + + foreach ($attributes as $attribute) { + if (isset($attribute['searchAble']) && $attribute['searchAble'] && in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $name = $attribute['name']; + $scopeSearch .= " + \$query->whereMonth('$name', \$month);"; + } + } + if ($timestamps) { + $name = 'created_at'; + $scopeSearch .= " + \$query->whereMonth('$name', \$month);"; + + $name = 'updated_at'; + $scopeSearch .= " + \$query->whereMonth('$name', \$month);"; + } + if ($softDeletes) { + $name = 'deleted_at'; + $scopeSearch .= " + \$query->whereMonth('$name', \$month);"; + } + // Busca padrão por strings (como nome, email, etc.) + $scopeSearch .= " + } else {"; + + foreach ($attributes as $attribute) { + if (isset($attribute['searchAble']) && $attribute['searchAble'] && !in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + $name = $attribute['name']; + $scopeSearch .= " + \$query->orWhere('$name', 'LIKE', \"%\$search%\");"; + if (isset($attribute['translated']) && $attribute['translated']) { + $nameTranslated = $name . '_translated'; + $scopeSearch .= " + \$query->orWhereHas('translations', fn(\$q) => \$q->where('$nameTranslated', 'LIKE', \"%\$search%\"));"; + } + } + } + + // Finaliza o método scopeSearch + $scopeSearch .= " + } + }); + } + }"; + + return $scopeSearch; + } + + protected function generateDateScopes($attributes, $timestamps, $softDeletes) + { + $scopes = ''; + if ($timestamps) { + $attributeUpdatedAt = [ + "name" => "updated_at", + "type" => "timestamp", + "length" => null, + "max" => null, + "min" => null, + "required" => false, + "nullable" => true, + "default" => null, + "unique" => false, + "sortAble" => true, + "filterAble" => true, + "exactFilter" => true, + "searchAble" => true, + "translated" => false, + ]; + array_unshift($attributes, $attributeUpdatedAt); + $attributeCreatedAt = [ + "name" => "created_at", + "type" => "timestamp", + "length" => null, + "max" => null, + "min" => null, + "required" => false, + "nullable" => true, + "default" => null, + "unique" => false, + "sortAble" => true, + "filterAble" => true, + "exactFilter" => true, + "searchAble" => true, + "translated" => false, + ]; + array_unshift($attributes, $attributeCreatedAt); + } + if ($softDeletes) { + $attributeDeleteddAt = [ + "name" => "deleted_at", + "type" => "timestamp", + "length" => null, + "max" => null, + "min" => null, + "required" => false, + "nullable" => true, + "default" => null, + "unique" => false, + "sortAble" => true, + "filterAble" => true, + "exactFilter" => true, + "searchAble" => true, + "translated" => false, + ]; + array_unshift($attributes, $attributeDeleteddAt); + } + + foreach ($attributes as $attribute) { + if (in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) { + // $name = ucfirst($attribute['name']); + $name = Str::ucfirst(Str::camel($attribute['name'])); + + // Scope for the exact date + $scopes .= " + public function scope{$name}(Builder \$builder, \$date) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'At', \$date); + } + + public function scope{$name}Before(Builder \$builder, \$date) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtBefore', \$date); + } + + public function scope{$name}After(Builder \$builder, \$date) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtAfter', \$date); + } + + public function scope{$name}Between(Builder \$builder, \$startDate, \$endDate) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtBetween', \$startDate, \$endDate); + } + + public function scope{$name}CurrentDay(Builder \$builder) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtCurrentDay'); + } + + public function scope{$name}CurrentWeek(Builder \$builder) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtCurrentWeek'); + } + + public function scope{$name}CurrentMonth(Builder \$builder) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtCurrentMonth'); + } + + public function scope{$name}LastDays(Builder \$builder, int \$days) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtLastDays', \$days); + } + + public function scope{$name}NextDays(Builder \$builder, int \$days) + { + return \$this->applyDateScope(\$builder, '{$attribute['name']}', 'AtNextDays', \$days); + } + "; + } + } + + return $scopes; + } + + protected function generateBooleanScopes($attributes) + { + $scopes = ''; + foreach ($attributes as $attribute) { + if ($attribute['type'] === 'boolean') { + $attr = $attribute['name']; + $name = Str::ucfirst(Str::camel($attr)); + $scopes .= " + public function scope{$name}(Builder \$query): void + { + \$query->where('{$attribute['name']}', 1); + } + + "; + + $attr = 'not_' . $attribute['name']; + $name = Str::ucfirst(Str::camel($attr)); + + // Scope for is NOT active + $scopes .= " + public function scope{$name}(Builder \$query): void + { + \$query->where('{$attribute['name']}', 0); + } + "; + } + } + + return $scopes; + } + + + protected function generateActiveApprovedScopes($useIsActive, $useApprovedStatus) + { + $scopes = ''; + if ($useIsActive) { + $attr = 'is_active'; + $name = Str::ucfirst(Str::camel($attr)); + + // Scope for is active + $scopes .= " + public function scopeIsActive(Builder \$query): void + { + \$query->where('is_active', 1); + } + + "; + + $attr = 'is_not_active'; + $name = Str::ucfirst(Str::camel($attr)); + + // Scope for is NOT active + $scopes .= " + public function scopeIsNotActive(Builder \$query): void + { + \$query->where('is_active', 0); + } + "; + } + + if ($useApprovedStatus) { + $attr = 'analisys'; + $name = Str::ucfirst(Str::camel($attr)); + $scopes .= " + public function scopeAnalisys(Builder \$query): void + { + \$query->where('approved_status', \$this::APPROVED_STATUS_ANALISYS); + } + "; + $attr = 'approved'; + $name = Str::ucfirst(Str::camel($attr)); + $scopes .= " + public function scopeApproved(Builder \$query): void + { + \$query->where('approved_status', \$this::APPROVED_STATUS_APPROVED); + } + "; + $attr = 'unapproved'; + $name = Str::ucfirst(Str::camel($attr)); + $scopes .= " + public function scopeUnapproved(Builder \$query): void + { + \$query->where('approved_status', \$this::APPROVED_STATUS_UNAPPROVED); + } + "; + $attr = 'blocked'; + $name = Str::ucfirst(Str::camel($attr)); + $scopes .= " + public function scopeBlocked(Builder \$query): void + { + \$query->where('approved_status', \$this::APPROVED_STATUS_BLOCKED); + } + "; + $attr = 'canceled'; + $name = Str::ucfirst(Str::camel($attr)); + $scopes .= " + public function scopeCanceled(Builder \$query): void + { + \$query->where('approved_status', \$this::APPROVED_STATUS_CANCELED); + } + "; + } + + return $scopes; + } + + protected function generateAllowedFilters($attributes, $timestamps, $softDelete, $hasSearchAble, $useIsActive, $useApprovedStatus) + { + $allowedFilters = " + /** + * The allowed filters attributes. + * "; + + // Lista os atributos filtráveis + $filterAttributes = []; + $filterAttributes[] = 'id'; + foreach ($attributes as $attribute) { + if (isset($attribute['filterAble']) && $attribute['filterAble']) { + if (isset($attribute['exactFilter']) && $attribute['exactFilter']) { + $filterAttributes[] = $attribute['name']; + if (isset($attribute['type']) && in_array($attribute['type'], ['boolean'])) { + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])); + $filterAttributes[] = 'Not' . Str::ucfirst(Str::camel($attribute['name'])); + } + } elseif ( + isset($attribute['searchAble']) && $attribute['searchAble'] && + (isset($attribute['type']) && in_array($attribute['type'], ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime'])) + ) { + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])); + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'Before'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'After'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'Between'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'CurrentDay'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'CurrentWeek'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'CurrentMonth'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'LastDays'; + $filterAttributes[] = Str::ucfirst(Str::camel($attribute['name'])) . 'NextDays'; + } else { + $filterAttributes[] = $attribute['name']; + } + } + } + + if ($useIsActive) { + $attr = 'is_active'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $attr = 'is_not_active'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + } + + if ($useApprovedStatus) { + $attr = 'analisys'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $attr = 'approved'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $attr = 'unapproved'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $attr = 'blocked'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $attr = 'canceled'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + } + + + if ($timestamps) { + $attr = 'created_at'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'Before'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'After'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'Between'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentDay'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentWeek'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentMonth'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'LastDays'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'NextDays'; + $attr = 'updated_at'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'Before'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'After'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'Between'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentDay'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentWeek'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentMonth'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'LastDays'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'NextDays'; + } + if ($softDelete) { + $attr = 'deleted_at'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)); + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'Before'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'After'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'Between'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentDay'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentWeek'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'CurrentMonth'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'LastDays'; + $filterAttributes[] = Str::ucfirst(Str::camel($attr)) . 'NextDays'; + $filterAttributes[] = 'WithTrashed'; + $filterAttributes[] = 'OnlyTrashed'; + } + if ($hasSearchAble) { + $filterAttributes[] = 'Search'; + } + // Adiciona os atributos filtráveis no comentário da função + if (!empty($filterAttributes)) { + $allowedFilters .= implode(',', $filterAttributes); + } else { + $allowedFilters .= "No filterable attributes found."; + } + + // Fecha o comentário e define o retorno da função + $allowedFilters .= " + */ + public static function ALLOWEDFILTERS() + { + return ["; + $nameId = 'id'; + $allowedFilters .= " + AllowedFilter::exact('{$nameId}'),"; + foreach ($attributes as $attribute) { + if (isset($attribute['filterAble']) && $attribute['filterAble']) { + $name = $attribute['name']; + $type = $attribute['type']; + $scopeName = Str::ucfirst(Str::camel($attribute['name'])); + // Verifica se o tipo é date, timestamp ou datetime e se tem searchAble + if (in_array($type, ['date', 'timestamp', 'timeStamp', 'datetime', 'dateTime']) && isset($attribute['searchAble']) && $attribute['searchAble']) { + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'), + AllowedFilter::scope('{$scopeName}Before'), + AllowedFilter::scope('{$scopeName}After'), + AllowedFilter::scope('{$scopeName}Between'), + AllowedFilter::scope('{$scopeName}CurrentDay'), + AllowedFilter::scope('{$scopeName}CurrentWeek'), + AllowedFilter::scope('{$scopeName}CurrentMonth'), + AllowedFilter::scope('{$scopeName}LastDays'), + AllowedFilter::scope('{$scopeName}NextDays'),"; + } elseif (isset($attribute['exactFilter']) && $attribute['exactFilter']) { + // Se tem exactFilter true, usa o filtro exato + $allowedFilters .= " + AllowedFilter::exact('{$name}'),"; + if (in_array($type, ['boolean'])) { + $scopeName = Str::ucfirst(Str::camel($attribute['name'])); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'), + AllowedFilter::scope('Not{$scopeName}'),"; + } + } else { + // Caso não tenha exactFilter ou seja false, usa partial + $allowedFilters .= " + AllowedFilter::partial('{$name}'),"; + } + } + } + + if ($useIsActive) { + $attr = 'is_active'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + $attr = 'is_not_active'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + } + + if ($useApprovedStatus) { + $attr = 'analisys'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + $attr = 'approved'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + $attr = 'unapproved'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + $attr = 'blocked'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + $attr = 'canceled'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'),"; + } + + + if ($timestamps) { + $attr = 'created_at'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'), + AllowedFilter::scope('{$scopeName}Before'), + AllowedFilter::scope('{$scopeName}After'), + AllowedFilter::scope('{$scopeName}Between'), + AllowedFilter::scope('{$scopeName}CurrentDay'), + AllowedFilter::scope('{$scopeName}CurrentWeek'), + AllowedFilter::scope('{$scopeName}CurrentMonth'), + AllowedFilter::scope('{$scopeName}LastDays'), + AllowedFilter::scope('{$scopeName}NextDays'),"; + $attr = 'updated_at'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'), + AllowedFilter::scope('{$scopeName}Before'), + AllowedFilter::scope('{$scopeName}After'), + AllowedFilter::scope('{$scopeName}Between'), + AllowedFilter::scope('{$scopeName}CurrentDay'), + AllowedFilter::scope('{$scopeName}CurrentWeek'), + AllowedFilter::scope('{$scopeName}CurrentMonth'), + AllowedFilter::scope('{$scopeName}LastDays'), + AllowedFilter::scope('{$scopeName}NextDays'),"; + } + // Adiciona filtros padrão como Search e OnlyTrashed + if ($softDelete) { + $attr = 'deleted_at'; + $scopeName = Str::ucfirst(Str::camel($attr)); + $allowedFilters .= " + AllowedFilter::scope('{$scopeName}'), + AllowedFilter::scope('{$scopeName}Before'), + AllowedFilter::scope('{$scopeName}After'), + AllowedFilter::scope('{$scopeName}Between'), + AllowedFilter::scope('{$scopeName}CurrentDay'), + AllowedFilter::scope('{$scopeName}CurrentWeek'), + AllowedFilter::scope('{$scopeName}CurrentMonth'), + AllowedFilter::scope('{$scopeName}LastDays'), + AllowedFilter::scope('{$scopeName}NextDays'),"; + $allowedFilters .= " + AllowedFilter::scope('WithTrashed'), + AllowedFilter::scope('OnlyTrashed'), + "; + } + if ($hasSearchAble) { + $allowedFilters .= " + AllowedFilter::scope('Search'), + "; + } + + $allowedFilters .= " + ]; + }"; + + + return $allowedFilters; + } + + protected function generateAllowedSorts($attributes, $timestamps, $softDeletes, $useIsActive) + { + // Inicializa o comentário com uma explicação e uma lista de atributos + $allowedSorts = " + /** + * The allowed sorts attributes. + * "; + + // Lista os atributos sortáveis no comentário + $sortAttributes = []; + $sortAttributes[] = 'id'; + + + foreach ($attributes as $attribute) { + if (isset($attribute['sortAble']) && $attribute['sortAble']) { + $sortAttributes[] = $attribute['name']; + } + } + if ($useIsActive) { + $sortAttributes[] = 'is_active'; + } + if ($timestamps) { + $sortAttributes[] = 'created_at'; + $sortAttributes[] = 'updated_at'; + } + if ($softDeletes) { + $sortAttributes[] = 'deleted_at'; + } + + // Adiciona os atributos sortáveis no comentário da função + if (!empty($sortAttributes)) { + $allowedSorts .= implode(',', $sortAttributes); + } else { + $allowedSorts .= "No sortable attributes found."; + } + + // Fecha o comentário e define o retorno da função + $allowedSorts .= " + */ + public static function ALLOWEDSORTS() + { + return ["; + + // Adiciona os atributos sortáveis no retorno da função + foreach ($sortAttributes as $name) { + $allowedSorts .= "'{$name}', "; + } + + // Remove a última vírgula e espaço, e fecha o array da função + $allowedSorts = rtrim($allowedSorts, ', ') . "]; + }"; + + return $allowedSorts; + } + + protected function generateDefaultSorts($attributes) + { + // Inicializa o comentário com uma explicação e uma lista de atributos + $allowedSorts = " + /** + * The Default sorts attributes. + * "; + + // Lista os atributos sortáveis no comentário + $sortAttributes = []; + foreach ($attributes as $attribute) { + if (isset($attribute['sortAble']) && $attribute['sortAble']) { + $sortAttributes[] = $attribute['name']; + } + } + + // Adiciona os atributos sortáveis no comentário da função + if (!empty($sortAttributes)) { + $allowedSorts .= implode(',', $sortAttributes); + } else { + $allowedSorts .= "No default sortable attributes found."; + } + + // Fecha o comentário e define o retorno da função + $allowedSorts .= " + */ + public static function DEFAULTSORT() + { + return ["; + + // Adiciona os atributos sortáveis no retorno da função + foreach ($sortAttributes as $name) { + $allowedSorts .= "'{$name}', "; + } + + // Remove a última vírgula e espaço, e fecha o array da função + $allowedSorts = rtrim($allowedSorts, ', ') . "]; + }"; + + return $allowedSorts; + } + + protected function generateAllowedIncludes($relations, $logsActivity, $useIsActive, $useApprovedStatus) + { + // Inicializa o comentário com uma explicação e uma lista de atributos + $allowedIncludes = " + /** + * The allowed includes relationships. + * "; + + // Lista os atributos no comentário + $sortAttributes = []; + foreach ($relations as $relation) { + $sortAttributes[] = $relation['name']; + } + if ($useIsActive) { + $sortAttributes[] = 'activeMotives'; + } + if ($useApprovedStatus) { + $sortAttributes[] = 'approvedMotives'; + } + + if ($logsActivity) { + $sortAttributes[] = 'activities'; + } + // Adiciona os atributos no comentário da função + if (!empty($sortAttributes)) { + $allowedIncludes .= implode(',', $sortAttributes); + } else { + $allowedIncludes .= "No includes relationships found."; + } + + // Fecha o comentário e define o retorno da função + $allowedIncludes .= " + */ + public static function ALLOWEDINCLUDES() + { + return ["; + + // Adiciona os atributos sortáveis no retorno da função + foreach ($sortAttributes as $name) { + $allowedIncludes .= "'{$name}', "; + } + + // Remove a última vírgula e espaço, e fecha o array da função + $allowedIncludes = rtrim($allowedIncludes, ', ') . "]; + }"; + + return $allowedIncludes; + } + + protected function generateDefaultIncludes($relations, $logsActivity, $useIsActive, $useApprovedStatus) + { + // Inicializa o comentário com uma explicação e uma lista de atributos + $allowedIncludes = " + /** + * The default includes relationships. + * "; + + // Lista os atributos no comentário + $sortAttributes = []; + foreach ($relations as $relation) { + if (isset($relation['default']) && $relation['default']) { + $sortAttributes[] = $relation['name']; + } + } + + // Adiciona os atributos no comentário da função + if (!empty($sortAttributes)) { + $allowedIncludes .= implode(',', $sortAttributes); + } else { + $allowedIncludes .= "No default includes relationships found."; + } + + // Fecha o comentário e define o retorno da função + $allowedIncludes .= " + */ + public static function DEFAULTINCLUDES() + { + return ["; + + // Adiciona os atributos sortáveis no retorno da função + foreach ($sortAttributes as $name) { + $allowedIncludes .= "'{$name}', "; + } + + // Remove a última vírgula e espaço, e fecha o array da função + $allowedIncludes = rtrim($allowedIncludes, ', ') . "]; + }"; + + return $allowedIncludes; + } + + + protected function generateRelationMethod($name, $type, $related) + { + switch ($type) { + case 'belongsTo': + return "public function {$name}() { return \$this->belongsTo({$related}::class); }"; + + case 'hasOne': + return "public function {$name}() { return \$this->hasOne({$related}::class); }"; + + case 'hasMany': + return "public function {$name}() { return \$this->hasMany({$related}::class); }"; + + case 'belongsToMany': + return "public function {$name}() { return \$this->belongsToMany({$related}::class); }"; + + case 'morphTo': + return "public function {$name}() { return \$this->morphTo(); }"; + + case 'morphMany': + return "public function {$name}() { return \$this->morphMany({$related}::class); }"; + + case 'morphOne': + return "public function {$name}() { return \$this->morphOne({$related}::class); }"; + + case 'morphToMany': + return "public function {$name}() { return \$this->morphToMany({$related}::class); }"; + + default: + return "// Relação não suportada: $type"; + } + } + + protected function generateRelationIsActiveApprovedStatus($useIsActive, $useApprovedStatus) + { + $include = ''; + if ($useIsActive) { + $include .= " + public function activeMotives() + { + return \$this->morphMany(ActiveHistoric::class, 'subject'); + } + + "; + } + + if ($useApprovedStatus) { + $include .= " + public function approvedMotives() + { + return \$this->morphMany(ApproveHistoric::class, 'subject'); + } + "; + } + return $include; + } + + + //////////////////// + + protected function generateModel($model, $version) + { + $modelPath = app_path("Models/{$model}.php"); + + // Verifica se o modelo concreto já existe + if (!File::exists($modelPath)) { + $modelContent = <<info("Model {$model} gerado com sucesso."); + } + } + + protected function generateModelTranslation($attributes, $model, $version) + { + $modelPath = app_path("Models/{$model}Translation.php"); + $fillable[] = "'locale',"; + foreach ($attributes as $attribute) { + $name = $attribute['name'] . '_translated'; + + if (isset($attribute['translated']) && $attribute['translated']) { + $fillable[] = "'{$name}',"; + $casts[$name] = "TrimCast::class"; + } + } + // Verifica se o modelo já existe + if (!File::exists($modelPath)) { + // Construa o conteúdo do modelo + $modelContent = << $value) { + $modelContent .= "\n '$key' => $value,"; + } + + $modelContent .= "\n ];"; + + $modelContent .= "\n}\n"; + + File::put($modelPath, $modelContent); + $this->info("Model {$model}Translation gerado com sucesso."); + } + } +} diff --git a/app/Console/Commands/GrgsDev/RunGenerateCommands.php b/app/Console/Commands/GrgsDev/RunGenerateCommands.php new file mode 100644 index 00000000..6d04db46 --- /dev/null +++ b/app/Console/Commands/GrgsDev/RunGenerateCommands.php @@ -0,0 +1,69 @@ +argument('model'); // Obtém o nome do arquivo JSON (sem a extensão) + $jsonPath = base_path("documentation/models/json/{$model}.json"); + + if (!File::exists($jsonPath)) { + $this->error("JSON file for model {$model} not found at path {$jsonPath}."); + return; + } + + $jsonContent = json_decode(File::get($jsonPath), true); + + if (!$jsonContent) { + $this->error('Invalid JSON content.'); + return; + } + // Array de comandos que você deseja executar + $commands = [ + 'grgsdev:migration' => "Run migration", + 'grgsdev:model' => "Generate model", + 'grgsdev:formrequest' => "Generate form request", + 'grgsdev:resource' => "Generate resource", + 'grgsdev:controller' => "Generate controller", + ]; + + // Definimos aqui os comandos que estarão selecionados por padrão + $defaultSelected = [ + 'grgsdev:model', + 'grgsdev:formrequest', + 'grgsdev:resource', + 'grgsdev:controller' + ]; + + $selectedCommands = multiselect( + label: 'What command should be assigned?', + options: $commands, + default: $defaultSelected + ); + + + // Executa apenas os comandos selecionados + foreach ($selectedCommands as $commandKey) { + $this->call($commandKey, ['model' => $model]); + $this->info("Command {$commandKey} executed successfully."); + } + + $this->info("All selected commands have been processed."); + } +} diff --git a/app/Console/Commands/GrgsDev/TranslateAttributes.php b/app/Console/Commands/GrgsDev/TranslateAttributes.php new file mode 100644 index 00000000..00016fed --- /dev/null +++ b/app/Console/Commands/GrgsDev/TranslateAttributes.php @@ -0,0 +1,114 @@ +error("Arquivo appAttributes.php não encontrado!"); + return Command::FAILURE; + } + + // Carregar o array de atributos + $attributes = include $inputFilePath; + + // Linguagens para tradução + $locales = ['en', 'it', 'es', 'fr', 'de', 'pt_BR']; + + // Inicializar tradutor (Stichoza/GoogleTranslate) + $translator = new GoogleTranslate(); + + // Caminho para o arquivo de saída + $outputFilePath = base_path('documentation/translations/appTranslatedAttributes.php'); + + // Verificar se o arquivo de saída já existe e carregar as traduções existentes + if (File::exists($outputFilePath)) { + $translatedAttributes = include $outputFilePath; + } else { + $translatedAttributes = []; + } + // Conjuntos de chaves de atributos para verificar se uma tradução é obsoleta + $attributeKeys = array_flip($attributes); + // Loop por cada idioma e traduzir novos atributos + + foreach ($locales as $locale) { + if (!isset($translatedAttributes[$locale])) { + $translatedAttributes[$locale] = []; + } + + // Ajustar o tradutor para o idioma alvo + $translator->setTarget($locale); + + foreach ($attributes as $attribute) { + // Manter a chave original se já estiver traduzida + if (array_key_exists($attribute, $translatedAttributes[$locale])) { + continue; // Ignora se já existe + } + + // Substituir underscores por espaços antes de traduzir + $attributeToTranslate = str_replace('_', ' ', $attribute); + + // Manter as chaves com '.' ou '.*' intactas + if (strpos($attribute, '.') !== false) { + $parts = explode('.', $attribute); + $attributeToTranslate = str_replace('_', ' ', $parts[0]); + $suffix = '.' . $parts[1]; + } else { + $suffix = ''; + } + + // Traduzir o atributo + try { + $translation = $translator->translate($attributeToTranslate); + } catch (\Exception $e) { + $this->error("Erro ao traduzir atributo '$attribute' para '$locale'. Erro: " . $e->getMessage()); + $translation = $attributeToTranslate; + } + + // Adicionar a tradução ao array, mantendo a chave original + $translatedAttributes[$locale][$attribute] = $translation . $suffix; + } + // Remover chaves obsoletas + $translatedAttributes[$locale] = array_intersect_key($translatedAttributes[$locale], $attributeKeys); + + // Ordenar as traduções em ordem alfabética pela chave + ksort($translatedAttributes[$locale]); + } + + // Gerar o array formatado para o arquivo de saída com aspas duplas para strings + $output = " $translations) { + $output .= " \"$locale\" => [\n"; + foreach ($translations as $key => $translation) { + $output .= " \"$key\" => \"$translation\",\n"; + } + $output .= " ],\n"; + } + $output .= "];\n"; + + // Criar o diretório se não existir + if (!File::isDirectory(base_path('documentation/translations'))) { + File::makeDirectory(base_path('documentation/translations'), 0755, true); + } + + // Escrever o arquivo com as traduções + File::put($outputFilePath, $output); + + $this->info("Traduções geradas com sucesso em app/documentation/translations/appTranslatedAttributes.php"); + + return Command::SUCCESS; + } +} diff --git a/app/Console/Commands/GrgsDev/TranslatedAttributesToJson.php b/app/Console/Commands/GrgsDev/TranslatedAttributesToJson.php new file mode 100644 index 00000000..7d5ecf18 --- /dev/null +++ b/app/Console/Commands/GrgsDev/TranslatedAttributesToJson.php @@ -0,0 +1,66 @@ +error("Arquivo appTranslatedAttributes.php não encontrado!"); + return Command::FAILURE; + } + + // Carregar o array de traduções + $translatedAttributes = include $translatedFilePath; + // Processar o array para ajustar as chaves + $formattedAttributes = $this->formatKeys($translatedAttributes); + // Converter o array para JSON com opções para não escapar caracteres Unicode + $jsonOutput = json_encode($formattedAttributes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + + // Caminho para o arquivo de saída + $outputFilePath = base_path('documentation/translations/translatedAttributes.json'); + + // Escrever o conteúdo JSON no arquivo + File::put($outputFilePath, $jsonOutput); + + $this->info("Arquivo translatedAttributes.json criado com sucesso em " . base_path('documentation/translations/translatedAttributes.json')); + + return Command::SUCCESS; + } + + /** + * Formata as chaves do array removendo sublinhados e capitalizando as palavras com espaços entre elas. + * + * @param array $attributes + * @return array + */ + private function formatKeys(array $attributes): array + { + $formatted = []; + + foreach ($attributes as $lang => $translations) { + $formatted[$lang] = []; + + foreach ($translations as $key => $value) { + // Substitui sublinhados por espaços e capitaliza palavras + $formattedKey = ucwords(str_replace('_', ' ', $key)); + $formattedValue = ucwords(str_replace('_', ' ', $value)); + + $formatted[$lang][$formattedKey] = $formattedValue; + } + } + + return $formatted; + } +} diff --git a/app/Console/Commands/SeedLogSubjectTypes.php b/app/Console/Commands/SeedLogSubjectTypes.php new file mode 100644 index 00000000..c07bcbe1 --- /dev/null +++ b/app/Console/Commands/SeedLogSubjectTypes.php @@ -0,0 +1,64 @@ +getFilenameWithoutExtension(); + $fullClassName = "App\\Models\\$modelName"; + + // Verifica se a classe realmente existe + if (class_exists($fullClassName)) { + // Verifica se a tabela existe + if (Schema::hasTable((new $fullClassName)->getTable())) { + $whatSubjectName = 'name'; // Default + + // Obtém os atributos fillable da classe + $fillableAttributes = (new $fullClassName)->getFillable(); + + // Verifica se 'title' ou 'name' estão presentes no fillable + if (in_array('title', $fillableAttributes)) { + $whatSubjectName = 'title'; + } elseif (in_array('name', $fillableAttributes)) { + $whatSubjectName = 'name'; + } + + LogSubjectType::updateOrCreate( + ['type' => $fullClassName], + [ + 'alias' => $modelName, // Altere conforme necessário + 'what_subject_name' => $whatSubjectName // Define o que subject_name de acordo com a verificação + ] + ); + $this->logCommandExecution("Added: $fullClassName with what_subject_name = $whatSubjectName", true); + $this->info("Added: $fullClassName with what_subject_name = $whatSubjectName"); + } else { + $this->logCommandExecution("Table does not exist for class: $fullClassName", false); + $this->warn("Table does not exist for class: $fullClassName"); + } + } else { + $this->logCommandExecution("Table does not exist for class: $fullClassName", false); + $this->warn("Class does not exist: $fullClassName"); + } + } + + $this->info('LogSubjectTypes seeded successfully!'); + } +} diff --git a/app/Http/Controllers/Api/V1/AbstractContracts/Gender/GenderController.php b/app/Http/Controllers/Api/V1/AbstractContracts/Gender/GenderController.php new file mode 100644 index 00000000..63691eea --- /dev/null +++ b/app/Http/Controllers/Api/V1/AbstractContracts/Gender/GenderController.php @@ -0,0 +1,584 @@ +only(['search', 'sort', 'per_page', 'only_trashed']); + Log::debug("filters", $filters); + + $finalFilters = [ + 'search' => $request->filter['Search'] ?? null, + 'sort' => $request->sort, + 'per_page' => (int)$request->per_page, + 'only_trashed' => $request->filter['OnlyTrashed'] ?? false, + ]; + $query = QueryService::query( + Gender::class, + Gender::ALLOWEDFILTERS(), + Gender::ALLOWEDINCLUDES(), + Gender::ALLOWEDSORTS(), + Gender::DEFAULTSORT(), + Gender::DEFAULTINCLUDES() + )->paginate(request('per_page'))->withQueryString(); + if (request()->wantsJson()) { + return $this->sendResponse(new GenderResource($query)); + } else { + return Inertia::render('params/genders/Index', [ + 'genders' => GenderResource::collection($query), + 'filters' => $finalFilters + ]); + } + } + + /** + * Show Gender by ID. + * @urlParam gender_id int required No-example + * @queryParam include Allowed: activeMotives,activities Relacionamentos que podem ser incluídos na resposta No-example + */ + public function show(string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId, Gender::ALLOWEDINCLUDES(), Gender::DEFAULTINCLUDES()); + if (request()->wantsJson()) { + return $this->sendResponse(new GenderResource($item)); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + /** + * Store Gender. + */ + public function store(StoreGenderRequest $request) + { + $data = []; + foreach ($request->all() as $key => $value) { + if (!is_null($value)) { + $data[$key] = $value; + } + } + // TRANSLATEDS + if (!empty($request->name)) { + $translated = TranslatorGoogle::translate($request->name); + $data['name'] = $translated['original_text']; + $data['name_translated'] = $translated['translations']; + $data['original_locale'] = $translated['source_language']; + } + + + // UPLOAD de icon + $storageIcon = Gender::ICON_STORAGE; + $savedNameIcon = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $uploadData = []; + try { + if ($request->hasFile('icon')) { + $uploadData = UploadService::putFile($request->file('icon'), $storageIcon); + } else { + if (!empty($request->icon) && strpos($request->icon, ';base64')) { + $uploadData = UploadService::putFile($request->icon, $storageIcon); + } + } + if ($uploadData) { + $savedNameIcon = $uploadData['saved_name']; + $originalFileName = $uploadData['original_name']; + $fileSize = $uploadData['size']; + $fileExtension = $uploadData['extension']; + } + } catch (\Throwable $th) { + throw $th; + } + if ($savedNameIcon) { + $data['icon'] = $savedNameIcon; + $data['icon_file_name'] = $originalFileName; + $data['icon_file_size'] = $fileSize; + $data['icon_file_extension'] = $fileExtension; + } + DB::beginTransaction(); + try { + $item = Gender::create($data); + $motive = 'Registro Inicial'; + if ($item->is_active) { + StatusService::active($item, $motive, Auth::user()->id); + } else { + StatusService::deactive($item, $motive, Auth::user()->id); + } + + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + + if ($savedNameIcon) { + UploadService::removeFile($savedNameIcon, $storageIcon); + } + throw $th; + } + if (request()->wantsJson()) { + return $this->sendResponse(new GenderResource($item)); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Update Gender by ID. + * @urlParam gender_id int required No-example + */ + public function update(UpdateGenderRequest $request, string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + $data = []; + foreach ($request->all() as $key => $value) { + if (!is_null($value) && $item->{$key} !== $value) { + $data[$key] = $value; + } + } + $nameTranslateds = []; + if (!empty($request->name) && ($request->name != $item->name)) { + $translated = TranslatorGoogle::translate($request->name); + $data['name'] = $translated['original_text']; + $nameTranslateds = $translated['translations']; + $data['original_locale'] = $translated['source_language']; + } + + + // UPLOAD de icon + $oldSavedNameIcon = $item->icon; + $storageIcon = Gender::ICON_STORAGE; + $savedNameIcon = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $uploadData = []; + try { + if ($request->hasFile('icon')) { + $uploadData = UploadService::putFile($request->file('icon'), $storageIcon); + } else { + if (!empty($request->icon) && strpos($request->icon, ';base64')) { + $uploadData = UploadService::putFile($request->icon, $storageIcon); + } + } + if ($uploadData) { + $savedNameIcon = $uploadData['saved_name']; + $originalFileName = $uploadData['original_name']; + $fileSize = $uploadData['size']; + $fileExtension = $uploadData['extension']; + } + } catch (\Throwable $th) { + throw $th; + } + if ($savedNameIcon) { + $data['icon'] = $savedNameIcon; + $data['icon_file_name'] = $originalFileName; + $data['icon_file_size'] = $fileSize; + $data['icon_file_extension'] = $fileExtension; + } + DB::beginTransaction(); + try { + if (!empty($data)) { + $item->update($data); + } + if ($nameTranslateds) { + $item->setTranslations('name_translated', $nameTranslateds); + $item->save(); + } + + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + + if ($savedNameIcon) { + UploadService::removeFile($savedNameIcon, $storageIcon); + } + throw $th; + } + + if ($savedNameIcon && $oldSavedNameIcon) { + UploadService::removeFile($oldSavedNameIcon, $storageIcon); + } + if (request()->wantsJson()) { + return $this->sendResponse(new GenderResource($item)); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Delete Gender by ID. + * @urlParam gender_id int required No-example + */ + public function destroy(string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + DB::beginTransaction(); + try { + $item->delete(); + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + /** + * Restore Gender. + * @urlParam gender_id int required No-example + */ + public function restore($genderId) + { + $item = QueryService::getOrFailTrashedById(Gender::class, $genderId); + DB::beginTransaction(); + try { + $item->restore(); + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + /** + * Force Delete Gender. + * @urlParam gender_id int required No-example + */ + public function forceDelete($genderId) + { + $item = QueryService::getOrFailTrashedById(Gender::class, $genderId); + DB::beginTransaction(); + try { + $item->forceDelete(); + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + + /** + * Change icon. + * @urlParam gender_id int required No-example + */ + public function changeIcon(ChangeGenderIconRequest $request, string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + $oldSavedNameIcon = $item->icon; + $storageIcon = Gender::ICON_STORAGE; + $savedNameIcon = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $uploadData = []; + + try { + if ($request->hasFile('icon')) { + $uploadData = UploadService::putFile($request->file('icon'), $storageIcon); + } else { + if (!empty($request->icon) && strpos($request->icon, ';base64')) { + $uploadData = UploadService::putFile($request->icon, $storageIcon); + } + } + if ($uploadData) { + $savedNameIcon = $uploadData['saved_name']; + $originalFileName = $uploadData['original_name']; + $fileSize = $uploadData['size']; + $fileExtension = $uploadData['extension']; + } + } catch (\Throwable $th) { + throw $th; + } + if ($savedNameIcon) { + $data['icon'] = $savedNameIcon; + $data['icon_file_name'] = $originalFileName; + $data['icon_file_size'] = $fileSize; + $data['icon_file_extension'] = $fileExtension; + + //SAVE DATA + DB::beginTransaction(); + try { + $item->update($data); + if ($oldSavedNameIcon) { + UploadService::removeFile($oldSavedNameIcon, $storageIcon); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + if ($savedNameIcon) { + UploadService::removeFile($savedNameIcon, $storageIcon); + } + throw $th; + } + } + + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + /** + * Clear icon. + * @urlParam gender_id int required No-example + */ + public function clearIcon(string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + $oldSavedNameIcon = $item->icon; + $storageIcon = Gender::ICON_STORAGE; + $savedNameIcon = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $data = []; + + $data['icon'] = $savedNameIcon; + $data['icon_file_name'] = $originalFileName; + $data['icon_file_size'] = $fileSize; + $data['icon_file_extension'] = $fileExtension; + //SAVE DATA + DB::beginTransaction(); + try { + $item->update($data); + if ($oldSavedNameIcon) { + UploadService::removeFile($oldSavedNameIcon, $storageIcon); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + + + /** + * Active Gender. + * @urlParam gender_id int required No-example + */ + public function active(ChangeGenderIsActiveRequest $request, string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + if ($item->is_active) { + return $this->sendSuccess(); + } + DB::beginTransaction(); + try { + $item->update([ + 'is_active' => 1, + ]); + $motive = 'Sem motivo indicado'; + if ($request->motive) { + $motive = $request->motive; + } + + if ($item->is_active) { + StatusService::active($item, $motive, Auth::user()->id); + } else { + StatusService::deactive($item, $motive, Auth::user()->id); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + /** + * Deactive Gender. + * @urlParam gender_id int required No-example + */ + public function deactive(ChangeGenderIsActiveRequest $request, string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + if (!$item->is_active) { + return $this->sendSuccess(); + } + DB::beginTransaction(); + try { + $item->update([ + 'is_active' => 0, + ]); + $motive = 'Sem motivo indicado'; + if ($request->motive) { + $motive = $request->motive; + } + + if ($item->is_active) { + StatusService::active($item, $motive, Auth::user()->id); + } else { + StatusService::deactive($item, $motive, Auth::user()->id); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } + + /** + * Toggle IsActive. + * @urlParam gender_id int required No-example + */ + public function toggleIsActive(string $genderId) + { + $item = QueryService::getOrFailById(Gender::class, $genderId); + + DB::beginTransaction(); + try { + if (!$item->is_active) { + $item->update([ + 'is_active' => 1, + ]); + } else { + $item->update([ + 'is_active' => 0, + ]); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with( + 'success', + __('The action was executed successfully.') + ); + } + } +} diff --git a/app/Http/Controllers/Api/V1/AbstractContracts/Log/ActivityLogController.php b/app/Http/Controllers/Api/V1/AbstractContracts/Log/ActivityLogController.php new file mode 100644 index 00000000..4dbe9662 --- /dev/null +++ b/app/Http/Controllers/Api/V1/AbstractContracts/Log/ActivityLogController.php @@ -0,0 +1,79 @@ +only(['search', 'sort', 'per_page']); + Log::debug("filters", $filters); + + $finalFilters = [ + 'search' => $request->filter['Search'] ?? null, + 'sort' => $request->sort, + 'per_page' => $request->per_page + ]; + + $query = QueryService::query( + ActivityLog::class, + ActivityLog::ALLOWEDFILTERS(), + ActivityLog::ALLOWEDINCLUDES(), + ActivityLog::ALLOWEDSORTS(), + ActivityLog::DEFAULTSORT(), + ActivityLog::DEFAULTINCLUDES() + )->paginate(request('per_page'))->withQueryString(); + + + + // $query = QueryBuilder::for(ActivityLog::class) + // ->allowedFilters([ + // AllowedFilter::exact('event'), // Filtra por evento (created, updated, deleted) + // AllowedFilter::exact('subject_type'), // Filtra pelo tipo de subject (modelo afetado) + // AllowedFilter::exact('subject_id'), // Filtra pelo ID do subject + // AllowedFilter::scope('subject_name'), // Filtra pelo nome do subject + // AllowedFilter::exact('causer_id'), // Filtra pelo ID do causer + // AllowedFilter::scope('causer_name'), // Filtra pelo nome do causer + // ]) + // ->with(['subject', 'causer']) // Carrega os relacionamentos 'subject' e 'causer' + // ->paginate(request('per_page'))->withQueryString(); + if (request()->wantsJson()) { + return $this->sendResponse(new ActivityLogResource($query)); + } else { + return Inertia::render('logs/activityLogs/Index', [ + 'activityLogs' => ActivityLogResource::collection($query), + 'filters' => $finalFilters + ]); + } + } +} diff --git a/app/Http/Controllers/Api/V1/AbstractContracts/Params/LocaleController.php b/app/Http/Controllers/Api/V1/AbstractContracts/Params/LocaleController.php new file mode 100644 index 00000000..e9b4e395 --- /dev/null +++ b/app/Http/Controllers/Api/V1/AbstractContracts/Params/LocaleController.php @@ -0,0 +1,150 @@ +validate([ + 'locale' => 'required|in:pt_BR,en,fr,it,de,es' + ]); + + // Não precisa retornar nada - o middleware SetLocale vai lidar com o header + return back(); + } + + /** + * List Locales . + * + * @queryParam page int Indique o número da página desejada No-example + * @queryParam per_page int Indique quantos registros deve conter cada página[default=50] No-example + * @queryParam filter[id] No-example + * @queryParam filter[name] No-example + * @queryParam filter[original_locale] No-example + * @queryParam filter[Trashed] No-example + * @queryParam filter[Search] Digite o texto ou parte do texto que procura na lista No-example + * @queryParam sort Allowed: id,name,original_locale,created_at Classifica a lista. Para classificação descendente coloque o - na frente(-id) No-example + * + */ + public function index() + { + $query = QueryService::query( + Locale::class, + Locale::ALLOWEDFILTERS(), + Locale::ALLOWEDINCLUDES(), + Locale::ALLOWEDSORTS(), + Locale::DEFAULTSORT() + )->paginate(request('per_page'))->withQueryString(); + + return LocaleResource::collection($query); + } + + /** + * Store a Locale. + */ + public function store(StoreLocaleRequest $request) + { + if (!empty($request->name)) { + $translated = TranslatorGoogle::translate($request->name); + $objectToSaveData['name'] = $translated['original_text']; + $objectToSaveData['display_name'] = $translated['translations']; + $objectToSaveData['original_locale'] = $translated['source_language']; + } + if (!empty($request->alias)) { + $objectToSaveData['alias'] = $request->alias; + } + + if (!empty($request->priority)) { + $objectToSaveData['priority'] = $request->priority; + } + + DB::beginTransaction(); + try { + $locale = Locale::create($objectToSaveData); + + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + return $this->sendResponse(new LocaleResource($locale)); + } + + /** + * Display the specified locale by ID. + * @urlParam locale_id int required No-example + */ + public function show($id) + { + $locale = QueryService::findOrFail(Locale::class, 'id', $id); + return $this->sendResponse(new LocaleResource($locale)); + } + + + /** + * Update the specified locale in storage. + * @urlParam locale_id int required No-example + */ + public function update(UpdateLocaleRequest $request, $id) + { + $displayNames = []; + $objectToSaveData = []; + $objectToUpdate = QueryService::findOrFail(Locale::class, 'id', $id); + if (!empty($request->name) && ($request->name != $objectToUpdate->name)) { + $translated = TranslatorGoogle::translate($request->name); + $objectToSaveData['name'] = $translated['original_text']; + $displayNames = $translated['translations']; + $objectToSaveData['original_locale'] = $translated['source_language']; + } + if (!empty($request->alias) && ($request->alias != $objectToUpdate->alias)) { + $objectToSaveData['alias'] = $request->alias; + } + + if (!empty($request->priority) && ($request->priority != $objectToUpdate->priority)) { + $objectToSaveData['priority'] = $request->priority; + } + DB::beginTransaction(); + try { + if ($objectToSaveData) { + $objectToUpdate->update($objectToSaveData); + } + if ($displayNames) { + $objectToUpdate->setTranslations('display_name', $displayNames); + $objectToUpdate->save(); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + return $this->sendSuccess(); + } + + /** + * Remove the specified locale from storage. + * @urlParam locale_id int required No-example + */ + public function destroy($id) + { + $locale = QueryService::findOrFail(Locale::class, 'id', $id); + $locale->delete(); + return $this->sendSuccess(); + } +} diff --git a/app/Http/Controllers/Api/V1/Gender/GenderController.php b/app/Http/Controllers/Api/V1/Gender/GenderController.php new file mode 100644 index 00000000..c03c86be --- /dev/null +++ b/app/Http/Controllers/Api/V1/Gender/GenderController.php @@ -0,0 +1,17 @@ +only(['search', 'sort', 'per_page', 'only_trashed']); + Log::debug("filters", $filters); + $onlyTrashed = false; + if (!empty($request->filter['OnlyTrashed'])) { + $onlyTrashed = true; + } + $finalFilters = [ + 'search' => $request->filter['Search'] ?? null, + 'sort' => $request->sort, + 'per_page' => (int)$request->per_page, + 'only_trashed' => $onlyTrashed, + + ]; + $users = QueryService::query( + User::class, + User::ALLOWEDFILTERS(), + User::ALLOWEDINCLUDES(), + User::ALLOWEDSORTS(), + User::DEFAULTSORT(), + user::DEFAULTINCLUDES() + )->paginate(request('per_page', 10))->withQueryString(); + // Log::debug("message", ['users' => $users]); + return Inertia::render('users/Index', [ + 'users' => UserResource::collection($users), + 'filters' => $finalFilters + ]); + } + + // Salvar novo usuário + public function store(UserRequest $request) + { + $data = []; + foreach ($request->validated() as $key => $value) { + if (!is_null($value)) { + $data[$key] = $value; + } + } + + // UPLOAD de avatar + $storageAvatar = User::AVATAR_STORAGE; + $savedNameAvatar = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $uploadData = []; + try { + if ($request->hasFile('avatar')) { + $uploadData = UploadService::putFile($request->file('avatar'), $storageAvatar); + } else { + if (!empty($request->avatar) && strpos($request->avatar, ';base64')) { + $uploadData = UploadService::putFile($request->avatar, $storageAvatar); + } + } + if ($uploadData) { + $savedNameAvatar = $uploadData['saved_name']; + $originalFileName = $uploadData['original_name']; + $fileSize = $uploadData['size']; + $fileExtension = $uploadData['extension']; + } + } catch (\Throwable $th) { + throw $th; + } + if ($savedNameAvatar) { + $data['avatar'] = $savedNameAvatar; + $data['original_file_name'] = $originalFileName; + // $data['avatar_file_size'] = $fileSize; + // $data['avatar_file_extension'] = $fileExtension; + } + $user = User::create($data); + $motives = []; + $translateds = TranslatorGoogle::translate('Cadastro inicial'); + $motives = $translateds['translations']; + + $user->approvedMotives()->create([ + 'approved_status' => '1', + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $user->activeMotives()->create([ + 'is_active' => false, // Usuário criado não está ativo por padrão + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + return back()->with('success', __('The action was executed successfully.')); + } + + // Atualizar usuário + public function update(UserRequest $request, User $user) + { + $item = QueryService::getOrFailById(User::class, $user->id); + $data = []; + foreach ($request->validated() as $key => $value) { + if (!is_null($value) && $item->{$key} !== $value) { + $data[$key] = $value; + } + } + // UPLOAD de avatar + $oldSavedNameAvatar = $item->avatar; + + $storageAvatar = User::AVATAR_STORAGE; + $savedNameAvatar = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $uploadData = []; + Log::debug("user", ['user' => $user]); + Log::debug("request", ['request' => $request->all()]); + Log::debug("data", $data); + + + if ($request->has('remove_avatar') && $request->remove_avatar) { + // Remover avatar existente + if ($oldSavedNameAvatar) { + UploadService::removeFile($oldSavedNameAvatar, $storageAvatar); + $data['avatar'] = ''; + $data['original_file_name'] = ''; + // $data['avatar_file_size'] = 0; + // $data['avatar_file_extension'] = ''; + } + } else { + try { + if ($request->hasFile('avatar')) { + $uploadData = UploadService::putFile($request->file('avatar'), $storageAvatar); + } else { + if (!empty($request->avatar) && strpos($request->avatar, ';base64')) { + $uploadData = UploadService::putFile($request->avatar, $storageAvatar); + } + } + if ($uploadData) { + $savedNameAvatar = $uploadData['saved_name']; + $originalFileName = $uploadData['original_name']; + $fileSize = $uploadData['size']; + $fileExtension = $uploadData['extension']; + } + } catch (\Throwable $th) { + throw $th; + } + if ($savedNameAvatar) { + $data['avatar'] = $savedNameAvatar; + $data['original_file_name'] = $originalFileName; + // $data['avatar_file_size'] = $fileSize; + // $data['avatar_file_extension'] = $fileExtension; + } + } + + DB::beginTransaction(); + try { + if (!empty($data)) { + $item->update($data); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + if ($savedNameAvatar) { + UploadService::removeFile($savedNameAvatar, $storageAvatar); + } + throw $th; + } + + if ($savedNameAvatar && $oldSavedNameAvatar) { + UploadService::removeFile($oldSavedNameAvatar, $storageAvatar); + } + + + return back()->with('success', __('The action was executed successfully.')); + } + + // Excluir usuário + public function destroy(User $user) + { + $user->delete(); + return back()->with('success', __('The action was executed successfully.')); + } + + //TRASHED + /** + * Show Project TRASHED by ID. + * @urlParam user_id int required No-example + * @queryParam include Allowed: activities Relacionamentos que podem ser incluídos na resposta No-example + */ + public function showTrashed(string $userId) + { + $item = QueryService::getOrFailTrashedById(User::class, $userId, User::ALLOWEDINCLUDES(), User::DEFAULTINCLUDES()); + + // Carrega as roles e permissions do usuário + $userRoles = $item->getRoleNames(); + $userPermissions = $item->getAllPermissions()->pluck('name'); + + if (request()->wantsJson()) { + return $this->sendResponse(new UserResource($item)); + } else { + return Inertia::render('users/Show', [ + 'user' => new UserResource($item), + 'userRoles' => $userRoles, + 'userPermissions' => $userPermissions, + ])->with('success', __('The action was executed successfully.')); + } + } + /** + * Restore User. + * @urlParam user_id int required No-example + */ + public function restore($userId) + { + $item = QueryService::getOrFailTrashedById(User::class, $userId); + DB::beginTransaction(); + try { + $item->restore(); + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Force Delete User. + * @urlParam user_id int required No-example + */ + public function forceDelete($userId) + { + $item = QueryService::getOrFailTrashedById(User::class, $userId); + DB::beginTransaction(); + try { + $item->forceDelete(); + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Active User. + * @urlParam user_id int required No-example + */ + public function active(ChangePlatformParamIsActiveRequest $request, string $userId) + { + $item = QueryService::getOrFailById(User::class, $userId); + if ($item->is_active) { + return $this->sendSuccess(); + } + DB::beginTransaction(); + try { + $item->update([ + 'is_active' => 1, + ]); + $motive = 'Sem motivo indicado'; + if ($request->motive) { + $motive = $request->motive; + } + + if ($item->is_active) { + StatusService::active($item, $motive, Auth::user()->id); + } else { + StatusService::deactive($item, $motive, Auth::user()->id); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Deactive User. + * @urlParam user_id int required No-example + */ + public function deactive(ChangePlatformParamIsActiveRequest $request, string $userId) + { + $item = QueryService::getOrFailById(User::class, $userId); + if (!$item->is_active) { + return $this->sendSuccess(); + } + DB::beginTransaction(); + try { + $item->update([ + 'is_active' => 0, + ]); + $motive = 'Sem motivo indicado'; + if ($request->motive) { + $motive = $request->motive; + } + + if ($item->is_active) { + StatusService::active($item, $motive, Auth::user()->id); + } else { + StatusService::deactive($item, $motive, Auth::user()->id); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Toggle IsActive. + * @urlParam user_id int required No-example + */ + public function toggleIsActive(string $userId) + { + $item = QueryService::getOrFailById(User::class, $userId); + + DB::beginTransaction(); + try { + if (!$item->is_active) { + $item->update([ + 'is_active' => 1, + ]); + } else { + $item->update([ + 'is_active' => 0, + ]); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + + /** + * Toggle approvedStatus. + * @urlParam user_id int required No-example + * @urlParam approved_status int required No-example + */ + public function toggleApproveStatus(string $userId, string $status = '2') + { + request()->validate([ + 'reason' => ['required', 'string', 'max:300'], + 'status' => ['required', 'in:1,2,3,4,5'], + ], [ + 'reason.required' => __('O motivo é obrigatório.'), + 'reason.max' => __('O motivo deve ter no máximo 300 caracteres.'), + 'status.in' => __('Status inválido.'), + ]); + + $reason = request('reason'); + $status = request('status', $status); + // if (!in_array($status, User::APPROVED_STATUS)) { + // return $this->sendError(__('Status inválido.'), 422); + // } + + $item = QueryService::getOrFailById(User::class, $userId); + if ($item->approved_status !== $status) { + + $motives = []; + $translateds = TranslatorGoogle::translate($reason); + $motives = $translateds['translations']; + DB::beginTransaction(); + try { + if ($item->approved_status !== $status) { + $item->update([ + 'approved_status' => $status, + // Salve o motivo se desejar, ex: 'approve_reason' => $reason, + ]); + $item->approvedMotives()->create([ + 'approved_status' => $status, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } + public function toggleApproveStatusxxx(string $userId, string $status = '2') + { + $item = QueryService::getOrFailById(User::class, $userId); + DB::beginTransaction(); + try { + if ($item->approved_status !== $status) { + $item->update([ + 'approved_status' => $status, + ]); + } + DB::commit(); + } catch (\Throwable $th) { + DB::rollBack(); + throw $th; + } + if (request()->wantsJson()) { + return $this->sendSuccess(); + } else { + return back()->with('success', __('The action was executed successfully.')); + } + } +} diff --git a/app/Http/Controllers/Api/V1/Params/LocaleController.php b/app/Http/Controllers/Api/V1/Params/LocaleController.php new file mode 100644 index 00000000..6e7b0845 --- /dev/null +++ b/app/Http/Controllers/Api/V1/Params/LocaleController.php @@ -0,0 +1,16 @@ +filter['Search'])) { + $search = request()->filter['Search']; + } + + $per_page = '10'; + if (!empty(request()->per_page)) { + $per_page = request()->per_page; + } + + $sort = ''; + if (!empty(request()->sort)) { + $sort = request()->sort; + } + + $page = ''; + if (!empty(request()->page)) { + $page = request()->page; + } + $filters = [ + 'search' => $search, // Pass the search query to the view + 'per_page' => $per_page, // Pass the perPage value to the view + 'sort' => $sort, // Pass the sort value to the view + 'page' => $page, + ]; + + return $filters; + } +} diff --git a/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Auth/AuthenticatedSessionController.php index dbb93653..d4d97395 100644 --- a/app/Http/Controllers/Auth/AuthenticatedSessionController.php +++ b/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -2,17 +2,30 @@ namespace App\Http\Controllers\Auth; -use App\Http\Controllers\Controller; -use App\Http\Requests\Auth\LoginRequest; -use Illuminate\Http\RedirectResponse; +use App\Models\User; +use Inertia\Inertia; +use Inertia\Response; +use App\Models\LoginLog; +use App\Models\UserLogin; +use App\Traits\ApiResponse; use Illuminate\Http\Request; +use Reefki\DeviceDetector\Device; +use Illuminate\Support\Facades\Log; +use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; +use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Route; -use Inertia\Inertia; -use Inertia\Response; +use App\Http\Requests\Auth\LoginRequest; +use DeviceDetector\Parser\Client\Browser; +use DeviceDetector\Parser\OperatingSystem; +use Illuminate\Validation\ValidationException; +use App\Http\Resources\Api\V1\User\UserResource; +use App\Http\Requests\Api\V1\Auth\UserLoginSanctumRequest; class AuthenticatedSessionController extends Controller { + use ApiResponse; /** * Show the login page. */ @@ -24,6 +37,136 @@ public function create(Request $request): Response ]); } + public function loginNew(UserLoginSanctumRequest $request) + { + try { + + + $user = User::where('email', $request->identifier) + ->orWhere('nickname', $request->identifier) + ->first(); + + $logData = [ + 'identifier' => $request->identifier, + 'ip_address' => $request->ip(), + 'user_agent' => $request->userAgent(), + 'status' => 'success' + ]; + + if (!$user || (!Hash::check($request->password, $user->password) && + !Hash::check($request->pin_code, $user->pin_code))) { + $logData['status'] = 'invalid_credentials'; + $logData['error_message'] = 'Credenciais inválidas'; + LoginLog::create($logData); + + throw ValidationException::withMessages([ + 'identifier' => ['As credenciais fornecidas estão incorretas.'], + ]); + } + + $logData['user_id'] = $user->id; + + //verificar is_active e + + // Verificar o tipo de login do usuário + if ($user->is_active !== true) { + $logData['status'] = 'is_not_active'; + $logData['error_message'] = 'Usuário não está ativo'; + LoginLog::create($logData); + + throw ValidationException::withMessages([ + 'identifier' => ['Usuário inativado.'], + ]); + } + if ($user->approved_status !== User::APPROVED_STATUS_APPROVED) { + $logData['status'] = 'is_not_approved'; + $logData['error_message'] = 'Usuário está bloqueado'; + LoginLog::create($logData); + + throw ValidationException::withMessages([ + 'identifier' => ['Usuário bloqueado.'], + ]); + } + + + + $device = Device::detectRequest($request); + $osInfo = $device->getOs(); + $device_type = $device->getDeviceName(); + $brand = $device->getBrandName(); + $model = $device->getModel(); + $osFamily = OperatingSystem::getOsFamily($device->getOs('name')); + $browserFamily = Browser::getBrowserFamily($device->getClient('name')); + + $deviceInfoTest = [ + 'browser' => $device->getClient('name'), + 'browser_version' => $device->getClient('version'), + 'platform' => $device->getOs('name'), + 'device_type' => $device->getDeviceName(), + 'is_mobile' => $device->isMobile(), + 'is_tablet' => $device->isTablet(), + 'is_desktop' => $device->isDesktop(), + 'osInfo' => $device->getOs(), + 'brand' => $device->getBrandName(), + 'model' => $device->getModel(), + 'osFamily' => OperatingSystem::getOsFamily($device->getOs('name')), + 'browserFamily' => Browser::getBrowserFamily($device->getClient('name')), + + + ]; + Log::debug("Log device infos", $deviceInfoTest); + $deviceInfo = [ + 'browser' => $device->getClient('name'), + 'browser_version' => $device->getClient('version'), + 'platform' => $device->getOs('name'), + 'device_type' => $device->getDeviceName(), + 'is_mobile' => $device->isMobile(), + 'is_tablet' => $device->isTablet(), + 'is_desktop' => $device->isDesktop(), + ]; + + + $token = $user->createToken(json_encode($deviceInfo), expiresAt: $expiresAt); + $loginData = [ + 'user_id' => $user->id, + 'ip_address' => $request->ip(), + 'token_id' => $token->accessToken->id, + 'browser' => $device->getClient('name'), + 'browser_version' => $device->getClient('version'), + 'platform' => $device->getOs('name'), + 'device_type' => $device->getDeviceName(), + 'is_mobile' => $device->isMobile(), + 'is_tablet' => $device->isTablet(), + 'is_desktop' => $device->isDesktop(), + ]; + UserLogin::create($loginData); + LoginLog::create($logData); + $success['token'] = $token->plainTextToken; + $success['expires_at'] = null; + $success['user'] = new UserResource($user); + return $this->sendResponse($success, __('User login successfully')); + + // return response()->json([ + // 'token' => $token->plainTextToken, + // 'expires_at' => $expiresAt ? $expiresAt->toDateTimeString() : null + // ]); + } catch (\Exception $e) { + LoginLog::create([ + 'identifier' => $request->identifier, + 'ip_address' => $request->ip(), + 'user_agent' => $request->userAgent(), + 'status' => 'error', + 'error_message' => $e->getMessage() + ]); + + throw $e; + } + } + + + + + /** * Handle an incoming authentication request. */ diff --git a/app/Http/Controllers/SystemDevelopment/ModelGenerateController.php b/app/Http/Controllers/SystemDevelopment/ModelGenerateController.php new file mode 100644 index 00000000..038cc7cf --- /dev/null +++ b/app/Http/Controllers/SystemDevelopment/ModelGenerateController.php @@ -0,0 +1,320 @@ +getModelDirectory(); + + // Verifica e cria o diretório se não existir + if (!file_exists($directory)) { + mkdir($directory, 0755, true); + } + + return $directory . '/' . $model; + } + + /** + * Display a listing of the resource. + * + * @param Request $request + * @return \Inertia\Response + */ + + public function index(Request $request) + { + // 1. CAPTURAR INPUTS + $filters = $request->validate([ + 'search' => 'nullable|string', + 'sort_field' => 'string|in:name,version,attributes_count,relations_count,updated_at', + 'sort_direction' => 'string|in:asc,desc', + 'per_page' => 'integer|min:5|max:100', + ]); + + // Usando valores padrão com o helper data_get + $search = data_get($filters, 'search'); + $sortField = data_get($filters, 'sort_field', 'updated_at'); + $sortDirection = data_get($filters, 'sort_direction', 'desc'); + $perPage = data_get($filters, 'per_page', 10); + + $finalFilters = [ + 'search' => $search, + 'sort_field' => $sortField, + 'sort_direction' => $sortDirection, + 'per_page' => (int) $perPage, // Garante que seja um inteiro + ]; + // Pega todos os modelos (idealmente do cache, como no ponto 1) + $allModels = $this->getAllModels(); + + // 2. APLICAR FILTROS E ORDENAÇÃO COM COLLECTIONS + $modelsCollection = collect($allModels) + ->when($search, function ($collection) use ($search) { + // A busca com `filter` da Collection + return $collection->filter(function ($model) use ($search) { + return stripos($model['name'], $search) !== false; + }); + }) + ->sortBy($sortField, SORT_REGULAR, $sortDirection === 'desc'); + + // 3. PAGINAÇÃO + $paginatedModels = new LengthAwarePaginator( + $modelsCollection->forPage(Paginator::resolveCurrentPage('page'), $perPage)->values(), + $modelsCollection->count(), + $perPage, + Paginator::resolveCurrentPage('page'), + ['path' => $request->url()] + ); + $paginatedModels->appends($finalFilters); + // 4. RENDERIZAR RESPOSTA + return Inertia::render('systemDevelopment/model/Index', [ + 'models' => $paginatedModels, + 'filters' => $finalFilters, // Retorna os filtros validados + ]); + } + + public function create() + { + return Inertia::render('systemDevelopment/model/Create', [ + 'defaults' => $this->getDefaultModelStructure() + ]); + } + public function store(StoreModelRequest $request) + { + $validated = $request->validated(); + $filename = $validated['name'] . '.json'; + $path = $this->getModelPath($filename); + + try { + file_put_contents( + $path, + json_encode(array_merge($validated, [ + 'created_at' => now()->toDateTimeString(), + 'updated_at' => now()->toDateTimeString(), + ]), JSON_PRETTY_PRINT) + ); + + return redirect()->route('models-generate.show', basename($filename, '.json')) + ->with('success', 'Model created successfully'); + } catch (\Exception $e) { + return back()->with('error', 'Failed to create model: ' . $e->getMessage()); + } finally { + // Limpa o cache de modelos para garantir que a lista atualizada seja carregada + Cache::forget('models.all'); + } + } + + public function show(string $model) + { + $path = $this->getModelPath($model . '.json'); + + if (!file_exists($path)) { + abort(404); + } + + $content = json_decode(file_get_contents($path), true); + + return Inertia::render('systemDevelopment/model/Show', [ + 'model' => array_merge($content, ['name' => $model]) + ]); + } + public function edit(string $model) + { + $path = $this->getModelPath($model . '.json'); + + if (!file_exists($path)) { + abort(404); + } + + $content = json_decode(file_get_contents($path), true); + + return Inertia::render('systemDevelopment/model/Edit', [ + 'model' => array_merge($content, ['name' => $model]) + ]); + } + + + public function update(UpdateModelRequest $request, string $model) + { + $path = $this->getModelPath($model . '.json'); + $newFilename = $request->name . '.json'; + $newPath = $this->getModelPath($newFilename); + + // Verifica se o arquivo existe + if (!file_exists($path)) { + abort(404); + } + + try { + $validated = $request->validated(); + + // Carrega o conteúdo atual do arquivo para preservar o created_at + $currentContent = json_decode(file_get_contents($path), true); + $createdAt = $currentContent['created_at'] ?? now()->toDateTimeString(); + + if ($path !== $newPath && file_exists($newPath)) { + throw new \Exception('A model with this name already exists'); + } + + file_put_contents( + $newPath, + json_encode(array_merge($validated, [ + 'created_at' => $createdAt, // Mantém o created_at original + 'updated_at' => now()->toDateTimeString(), + ]), JSON_PRETTY_PRINT) + ); + + if ($path !== $newPath) { + unlink($path); + } + + return redirect()->route('models-generate.show', basename($newFilename, '.json')) + ->with('success', 'Model updated successfully'); + } catch (\Exception $e) { + return back()->with('error', 'Failed to update model: ' . $e->getMessage()); + } finally { + // Limpa o cache de modelos para garantir que a lista atualizada seja carregada + Cache::forget('models.all'); + } + } + public function destroy(string $model) + { + Log::debug('Deleting model: ' . $model); + $path = $this->getModelPath($model . '.json'); + Log::debug('Model path: ' . $path); + Log::debug('File exists: ' . (file_exists($path) ? 'true' : 'false')); + if (!file_exists($path)) { + abort(404); + } + + try { + unlink($path); + return redirect()->back() + ->with('success', 'Model deleted successfully'); + } catch (\Exception $e) { + return back()->with('error', 'Failed to delete model: ' . $e->getMessage()); + } finally { + // Limpa o cache de modelos para garantir que a lista atualizada seja carregada + Cache::forget('models.all'); + } + } + + + public function export(string $model, string $format) + { + $path = $this->getModelPath($model . '.json'); + + if (!file_exists($path)) { + abort(404); + } + + $content = json_decode(file_get_contents($path), true); + $exporter = new ModelExporter($content); + + return $exporter->export($format, $model); + } + + private function getDefaultModelStructure(): array + { + return [ + 'version' => 'V1', + 'softDeletes' => true, + 'timestamps' => true, + 'useIsActive' => false, + 'useApprovedStatus' => false, + 'useScribe' => false, + 'authorize' => false, + 'logsActivity' => false, + 'clearsResponseCache' => false, + 'attributes' => [ + [ + 'name' => 'id', + 'type' => 'string', + 'length' => 255, + 'max' => 255, + 'min' => 0, + 'precision' => 0, + 'scale' => 0, + 'validate' => true, + 'required' => true, + 'nullable' => false, + 'unique' => true, + 'translated' => false, + + 'sortAble' => true, + 'filterAble' => true, + 'exactFilter' => false, + 'serachAble' => false, + + 'description' => 'The unique identifier', + 'example' => '1234567890', + ] + ], + 'relations' => [] + ]; + } + + private function getAllModels() + { + // A chave do cache. + $cacheKey = 'models.all'; + + // Cache::rememberForever irá executar a função e salvar o resultado + // para sempre. Ele só executará a função novamente se o cache for limpo. + return Cache::rememberForever($cacheKey, function () { + $directory = $this->getModelDirectory(); + + if (!File::exists($directory)) { + // Se o diretório não existe, retorna um array vazio. + // A criação pode ser movida para um comando ou outro local. + return []; + } + + $allModels = []; + // Use o facade File para uma melhor abstração + $files = File::glob($directory . '/*.json'); + + foreach ($files as $file) { + $content = json_decode(File::get($file), true); + + // Adiciona uma verificação para JSONs inválidos + if (json_last_error() !== JSON_ERROR_NONE) { + // Opcional: Logar o erro para saber qual arquivo está corrompido + // Log::warning("Arquivo JSON inválido encontrado: " . $file); + continue; // Pula para o próximo arquivo + } + + $allModels[] = [ + 'name' => File::name($file), // Mais limpo que basename($file, '.json') + 'version' => $content['version'] ?? 'V1', + 'attributes_count' => count($content['attributes'] ?? []), + 'relations_count' => count($content['relations'] ?? []), + 'updated_at' => $content['updated_at'] ?? date('Y-m-d H:i:s', File::lastModified($file)), + ]; + } + + return $allModels; + }); + } +} diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 62b69f31..fc64251f 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -38,14 +38,43 @@ public function version(Request $request): ?string public function share(Request $request): array { [$message, $author] = str(Inspiring::quotes()->random())->explode('-'); + $user = $request->user(); + // Preparar dados de roles e permissions + $authData = [ + 'user' => null, + 'roles' => [], + 'permissions' => [] + ]; + $locale = app()->getLocale(); + + if ($request->hasHeader('X-Locale')) { + $locale = $request->header('X-Locale'); + if ($locale) { + app()->setLocale($locale); + } + } + + if ($user) { + // Carregar roles e permissions (evitar N+1 query problem) + $user->load('roles', 'permissions'); + + $authData = [ + 'user' => $user, + 'roles' => $user->getRoleNames(), // Retorna apenas os nomes das roles + 'permissions' => $user->getAllPermissions()->pluck('name') // Retorna todos os nomes de permissions + ]; + } return [ ...parent::share($request), 'name' => config('app.name'), 'quote' => ['message' => trim($message), 'author' => trim($author)], - 'auth' => [ - 'user' => $request->user(), - ], + 'locale' => $locale, + 'auth' => $authData, + + // 'auth' => [ + // 'user' => $request->user(), + // ], 'ziggy' => [ ...(new Ziggy)->toArray(), 'location' => $request->url(), diff --git a/app/Http/Middleware/SetLocale copy.php b/app/Http/Middleware/SetLocale copy.php new file mode 100644 index 00000000..5f784b14 --- /dev/null +++ b/app/Http/Middleware/SetLocale copy.php @@ -0,0 +1,48 @@ +getLocale(); + + // 1. Verifica o header X-Locale (enviado pelo Inertia) + if ($request->hasHeader('X-Locale')) { + $locale = $request->header('X-Locale'); + if (in_array($locale, $supportedLocales)) { + app()->setLocale($locale); + return $next($request); + } + } + + // 2. Verifica o parâmetro na requisição (para rotas POST/PATCH) + if ($request->has('locale')) { + $locale = $request->input('locale'); + if (in_array($locale, $supportedLocales)) { + app()->setLocale($locale); + return $next($request); + } + } + + // 3. Verifica o cookie (para primeira visita) + if ($request->hasCookie('preferred_language')) { + $locale = $request->cookie('preferred_language'); + if (in_array($locale, $supportedLocales)) { + app()->setLocale($locale); + return $next($request); + } + } + + // 4. Usa o locale padrão + app()->setLocale($defaultLocale); + + return $next($request)->withCookie(cookie()->forever('preferred_language', $defaultLocale)); + } +} diff --git a/app/Http/Middleware/SetLocale.php b/app/Http/Middleware/SetLocale.php new file mode 100644 index 00000000..b8bf0f75 --- /dev/null +++ b/app/Http/Middleware/SetLocale.php @@ -0,0 +1,24 @@ +header('X-Locale') + ?? $request->cookie('preferred_language') + ?? config('app.locale'); + + app()->setLocale($locale); + + return $next($request)->cookie( + 'preferred_language', + $locale, + 60 * 24 * 365 // 1 ano + ); + } +} diff --git a/app/Http/Requests/Api/V1/Auth/UserLoginSanctumRequest.php b/app/Http/Requests/Api/V1/Auth/UserLoginSanctumRequest.php new file mode 100644 index 00000000..fad73c7e --- /dev/null +++ b/app/Http/Requests/Api/V1/Auth/UserLoginSanctumRequest.php @@ -0,0 +1,48 @@ +|string> + */ + public function rules() + { + return [ + 'identifier' => 'required', + 'password' => 'required_without:pin_code', + 'pin_code' => 'required_without:password|digits:6', + ]; + } + + public function bodyParameters() + { + return [ + 'identifier' => [ + 'description' => 'Informe E-Mail ou username', + 'example' => 'user@app.com', + ], + 'password' => [ + 'description' => 'Informe sua Senha de registro.', + 'example' => 'password', + ], + 'pin_code' => [ + 'description' => 'Informe seu PIN de 6 dígitos.', + 'example' => '123456', + ], + ]; + } +} diff --git a/app/Http/Requests/Api/V1/Gender/ChangeGenderIconRequest.php b/app/Http/Requests/Api/V1/Gender/ChangeGenderIconRequest.php new file mode 100644 index 00000000..1636f026 --- /dev/null +++ b/app/Http/Requests/Api/V1/Gender/ChangeGenderIconRequest.php @@ -0,0 +1,34 @@ + 'required|image|mimes:' . $supportedImageMimes . '|max:2048', + ]; + } + + public function bodyParameters() + { + return [ + 'icon' => [ + 'description' => 'icon to represent', + ], + ]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Api/V1/Gender/ChangeGenderIsActiveRequest.php b/app/Http/Requests/Api/V1/Gender/ChangeGenderIsActiveRequest.php new file mode 100644 index 00000000..1ef4d47d --- /dev/null +++ b/app/Http/Requests/Api/V1/Gender/ChangeGenderIsActiveRequest.php @@ -0,0 +1,38 @@ + + */ + public function rules(): array + { + return [ + 'motive' => 'nullable|string', + ]; + } + + public function bodyParameters() + { + return [ + 'motive' => [ + 'description' => 'Descrição do motivo.', + 'example' => 'Não apresentou a documentação', + ], + ]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Api/V1/Gender/StoreGenderRequest.php b/app/Http/Requests/Api/V1/Gender/StoreGenderRequest.php new file mode 100644 index 00000000..49de60d1 --- /dev/null +++ b/app/Http/Requests/Api/V1/Gender/StoreGenderRequest.php @@ -0,0 +1,53 @@ + 'required|string|max:255|' . Rule::unique(Gender::class,'name'), + 'icon' => 'nullable|image|mimes:' . $supportedImageMimes . '|max:255' + ]; + } + + protected function prepareForValidation() + { + $this->merge([ + 'is_active' => 0, + + ]); + + + } + + public function bodyParameters() + { + return [ + 'name' => [ + 'description' => 'Determina o gênero', + 'example' => 'male' + ], + 'icon' => [ + 'description' => 'icon to represent', + ], + + ]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Api/V1/Gender/UpdateGenderRequest.php b/app/Http/Requests/Api/V1/Gender/UpdateGenderRequest.php new file mode 100644 index 00000000..7dde3b29 --- /dev/null +++ b/app/Http/Requests/Api/V1/Gender/UpdateGenderRequest.php @@ -0,0 +1,52 @@ + 'sometimes|nullable|string|max:255|' . Rule::unique(Gender::class)->whereNull('deleted_at')->ignore($this->gender_id), + 'icon' => 'sometimes|nullable|image|mimes:' . $supportedImageMimes . '|max:255' + ]; + } + + protected function prepareForValidation() + { + $this->merge([ + + ]); + + + } + + public function bodyParameters() + { + return [ + 'name' => [ + 'description' => 'Determina o gênero', + 'example' => 'male' + ], + 'icon' => [ + 'description' => 'icon to represent', + ], + + ]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php index 25746424..9950378a 100644 --- a/app/Http/Requests/Auth/LoginRequest.php +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -2,15 +2,25 @@ namespace App\Http\Requests\Auth; +use App\Models\User; +use App\Models\LoginLog; +use App\Models\UserLogin; +use App\Traits\ApiResponse; +use Illuminate\Support\Str; +use Reefki\DeviceDetector\Device; use Illuminate\Auth\Events\Lockout; -use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Auth; +use DeviceDetector\Parser\Client\Browser; + +use DeviceDetector\Parser\OperatingSystem; +use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\RateLimiter; -use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; class LoginRequest extends FormRequest { + use ApiResponse; /** * Determine if the user is authorized to make this request. */ @@ -49,6 +59,83 @@ public function authenticate(): void ]); } + $device = Device::detectRequest($this); + $osInfo = $device->getOs(); + $device_type = $device->getDeviceName(); + $brand = $device->getBrandName(); + $model = $device->getModel(); + $osFamily = OperatingSystem::getOsFamily($device->getOs('name')); + $browserFamily = Browser::getBrowserFamily($device->getClient('name')); + $deviceInfo = [ + 'browser' => $device->getClient('name'), + 'browser_version' => $device->getClient('version'), + 'platform' => $device->getOs('name'), + 'device_type' => $device->getDeviceName(), + 'is_mobile' => $device->isMobile(), + 'is_tablet' => $device->isTablet(), + 'is_desktop' => $device->isDesktop(), + 'osInfo' => $osInfo, + 'brand' => $brand, + 'model' => $model, + 'osFamily' => $osFamily, + 'browserFamily' => $browserFamily, + ]; + Log::debug("Log device infos", $deviceInfo); + + $loginData = [ + 'user_id' => Auth::user()->id, + 'ip_address' => $this->ip(), + 'token_id' => '12565555555', // Placeholder, replace with actual token ID if needed + 'browser' => $device->getClient('name'), + 'browser_version' => $device->getClient('version'), + 'platform' => $device->getOs('name'), + 'device_type' => $device->getDeviceName(), + 'is_mobile' => $device->isMobile(), + 'is_tablet' => $device->isTablet(), + 'is_desktop' => $device->isDesktop(), + ]; + UserLogin::create($loginData); + //verificar is_active + if (!Auth::user()->is_active) { + LoginLog::create([ + 'identifier' => $this->email, + 'ip_address' => $this->ip(), + 'user_agent' => $this->userAgent(), + 'status' => 'is_not_active', + 'error_message' => 'Usuário não está ativo', + 'user_id' => Auth::user()->id, + ]); + Auth::logout(); + RateLimiter::hit($this->throttleKey()); + throw ValidationException::withMessages([ + 'email' => 'Usuário não está ativo', + ]); + } + if (Auth::user()->approved_status !== User::APPROVED_STATUS_APPROVED) { + LoginLog::create([ + 'identifier' => $this->email, + 'ip_address' => $this->ip(), + 'user_agent' => $this->userAgent(), + 'status' => 'is_not_approved', + 'error_message' => 'Usuário está ' . Auth::user()->approved_status_text, + 'user_id' => Auth::user()->id, + ]); + $error = Auth::user()->approved_status_text; + Auth::logout(); + RateLimiter::hit($this->throttleKey()); + throw ValidationException::withMessages([ + 'email' => 'Usuário está ' . $error, + ]); + } + // Log successful login + LoginLog::create([ + 'identifier' => $this->email, + 'ip_address' => $this->ip(), + 'user_agent' => $this->userAgent(), + 'status' => 'success', + 'user_id' => Auth::user()->id, + ]); + RateLimiter::clear($this->throttleKey()); } @@ -80,6 +167,6 @@ public function ensureIsNotRateLimited(): void */ public function throttleKey(): string { - return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip()); + return Str::transliterate(Str::lower($this->string('email')) . '|' . $this->ip()); } } diff --git a/app/Http/Requests/SystemDevelopment/StoreModelRequest.php b/app/Http/Requests/SystemDevelopment/StoreModelRequest.php new file mode 100644 index 00000000..789918b7 --- /dev/null +++ b/app/Http/Requests/SystemDevelopment/StoreModelRequest.php @@ -0,0 +1,162 @@ + [ + 'required', + 'string', + 'max:255', + 'regex:/^[A-Z][a-zA-Z0-9]*$/', + function ($attribute, $value, $fail) { + $filename = Str::slug($value) . '.json'; + if (Storage::exists("models/{$filename}")) { + $fail('A model with this name already exists.'); + } + } + ], + 'version' => 'required|string|max:10', + 'softDeletes' => 'boolean', + 'timestamps' => 'boolean', + 'useIsActive' => 'boolean', + 'useApprovedStatus' => 'boolean', + 'useScribe' => 'boolean', + 'authorize' => 'boolean', + 'logsActivity' => 'boolean', + 'clearsResponseCache' => 'boolean', + 'attributes' => 'required|array|min:1', + 'attributes.*.name' => 'required|string|max:255|distinct|regex:/^[a-z_][a-z0-9_]*$/', + 'attributes.*.type' => [ + 'required', + Rule::in([ + // Tipos inteiros + 'bigInteger', + 'integer', + 'tinyInteger', + 'smallInteger', + 'mediumInteger', + 'unsignedBigInteger', + 'unsignedInteger', + 'unsignedMediumInteger', + 'unsignedSmallInteger', + 'unsignedTinyInteger', + + // Tipos morphs + 'morphs', + 'nullableMorphs', + 'numericMorphs', + 'nullableNumericMorphs', + 'uuidMorphs', + 'nullableUuidMorphs', + 'ulidMorphs', + 'nullableUlidMorphs', + + // Tipos booleanos + 'boolean', + + // Tipos decimais + 'decimal', + 'float', + 'double', + + // Tipos texto + 'string', + 'char', + 'text', + 'mediumText', + 'longText', + 'email', + + // Tipos binários + 'binary', + + // Tipos data/hora + 'date', + 'datetime', + 'dateTime', + 'timestamp', + 'timeStamp', + 'time', + 'year', + + // Tipos JSON + 'json', + 'jsonb', + + // Tipos UUID/IDs + 'uuid', + 'foreignId', + 'foreignUuid', + + // Enumerações + 'enum', + 'set', + + // Tipos geométricos + 'geometry', + 'point', + 'linestring', + 'polygon', + 'geometryCollection', + 'multipoint', + 'multilinestring', + 'multipolygon', + + // Tipos de endereço + 'ipAddress', + 'macAddress', + + // Tipos especiais + 'file', + 'image', + 'video' + ]) + ], + 'attributes.*.length' => 'nullable|integer|min:0|max:65535', + 'attributes.*.precision' => 'nullable|integer|min:0|max:65', + 'attributes.*.scale' => 'nullable|integer|min:0|max:30', + 'attributes.*.values' => 'nullable|array', + 'attributes.*.values.*' => 'string|max:255', + 'attributes.*.max' => 'nullable|integer|min:0', + 'attributes.*.min' => 'nullable|integer|min:0', + 'attributes.*.validate' => 'boolean', + + 'attributes.*.required' => 'boolean', + 'attributes.*.nullable' => 'boolean', + 'attributes.*.unique' => 'boolean', + 'attributes.*.translated' => 'boolean', + + 'attributes.*.sortAble' => 'boolean', + 'attributes.*.filterAble' => 'boolean', + 'attributes.*.exactFilter' => 'boolean', + 'attributes.*.searchAble' => 'boolean', + + 'attributes.*.description' => 'nullable|string|max:500', + 'attributes.*.example' => 'nullable|string|max:255', + 'relations' => 'nullable|array', + 'relations.*.name' => 'required_with:relations|string|max:255', + 'relations.*.type' => [ + 'required_with:relations', + Rule::in(['belongsTo', 'hasMany', 'belongsToMany', 'hasOne']) + ], + 'relations.*.default' => 'boolean', + + 'relations.*.related' => 'required_with:relations|string|max:255', + 'relations.*.description' => 'nullable|string|max:500', + ]; + } +} diff --git a/app/Http/Requests/SystemDevelopment/UpdateModelRequest.php b/app/Http/Requests/SystemDevelopment/UpdateModelRequest.php new file mode 100644 index 00000000..54189ecd --- /dev/null +++ b/app/Http/Requests/SystemDevelopment/UpdateModelRequest.php @@ -0,0 +1,18 @@ + 'required|string|max:255', + 'email' => 'required|string|email|max:255|unique:users,email', + 'password' => 'required|string|min:8|confirmed', + 'avatar' => 'nullable|image|mimes:' . $supportedImageMimes . '|max:2048', + 'username' => 'nullable|string|max:255|unique:users,username', + 'pin_code' => 'nullable|numeric|max:999999|min:1', + 'locale' => 'nullable|string|max:5', + 'nickname' => 'nullable|string|max:20', + ]; + + if ($this->isMethod('put') || $this->isMethod('patch')) { + $rules['email'] = 'required|string|email|max:255|unique:users,email,' . $this->user->id; + $rules['username'] = 'nullable|string|max:255|unique:users,username,' . $this->user->id; + $rules['password'] = 'nullable|string|min:8|confirmed'; + } + + return $rules; + } +} diff --git a/app/Http/Resources/Api/V1/Acl/RoleResource.php b/app/Http/Resources/Api/V1/Acl/RoleResource.php new file mode 100644 index 00000000..0581596b --- /dev/null +++ b/app/Http/Resources/Api/V1/Acl/RoleResource.php @@ -0,0 +1,31 @@ + $this->id, + 'name' => $this->name, + 'guard_name' => $this->guard_name, + // 'permissions' => PermissionResource::collection($this->whenLoaded('permissions')), + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + 'updated_at' => [ + 'default' => $this->updated_at, + 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + ], + ]; + } +} diff --git a/app/Http/Resources/Api/V1/ActiveMotive/ActiveMotiveResource.php b/app/Http/Resources/Api/V1/ActiveMotive/ActiveMotiveResource.php new file mode 100644 index 00000000..4fd2cef6 --- /dev/null +++ b/app/Http/Resources/Api/V1/ActiveMotive/ActiveMotiveResource.php @@ -0,0 +1,50 @@ + + */ + public function toArray(Request $request): array + { + $subjectTypeAlias = LogSubjectType::where('type', $this->subject_type)->value('alias'); + $subject = $this->subject; // Acesso ao sujeito através do método existente + $subjectName = $subject ? ($subject->name ?? $subject->title ?? 'Unknown') : 'Unknown'; + + return [ + 'id' => $this->id, + 'is_active' => $this->is_active, + 'is_active_text' => $this->is_active_text, + 'subject_type' => $this->subject_type, + 'subject_id' => $this->subject_id, + 'subject_name' => $subjectName, + + 'causer_type' => $this->causer_type, + 'causer_id' => $this->causer_id, + 'causer_name' => optional($this->causer)->name, // Nome do causer se disponível + + 'motive' => $this->motive, + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + // 'updated_at' => [ + // 'default' => $this->updated_at, + // 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + // 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + // 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + // ], + ]; + } +} diff --git a/app/Http/Resources/Api/V1/ActivityLog/ActivityLogResource.php b/app/Http/Resources/Api/V1/ActivityLog/ActivityLogResource.php new file mode 100644 index 00000000..3a42d32f --- /dev/null +++ b/app/Http/Resources/Api/V1/ActivityLog/ActivityLogResource.php @@ -0,0 +1,52 @@ + + */ + public function toArray(Request $request): array + { + $subjectTypeAlias = LogSubjectType::where('type', $this->subject_type)->value('alias'); + $subject = $this->subject; // Acesso ao sujeito através do método existente + $subjectName = $subject ? ($subject->name ?? $subject->title ?? 'Unknown') : 'Unknown'; + + return [ + 'id' => $this->id, + 'subject_type' => $this->subject_type, + 'subject_type_alias' => $subjectTypeAlias ?? 'Unknown', // Valor padrão se o alias não existir + 'event' => $this->event, + 'subject_id' => $this->subject_id, + 'subject_name' => $subjectName, + 'causer_type' => $this->causer_type, + 'causer_id' => $this->causer_id, + 'causer_name' => optional($this->causer)->name, // Nome do causer se disponível + 'properties' => $this->properties, + + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + 'updated_at' => [ + 'default' => $this->updated_at, + 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + ], + + + 'description' => $this->description, + ]; + } +} diff --git a/app/Http/Resources/Api/V1/ApprovedStatusMotive/ApprovedStatusMotiveResource.php b/app/Http/Resources/Api/V1/ApprovedStatusMotive/ApprovedStatusMotiveResource.php new file mode 100644 index 00000000..b536dafb --- /dev/null +++ b/app/Http/Resources/Api/V1/ApprovedStatusMotive/ApprovedStatusMotiveResource.php @@ -0,0 +1,44 @@ + + */ + public function toArray(Request $request): array + { + $subjectTypeAlias = LogSubjectType::where('type', $this->subject_type)->value('alias'); + $subject = $this->subject; // Acesso ao sujeito através do método existente + $subjectName = $subject ? ($subject->name ?? $subject->title ?? 'Unknown') : 'Unknown'; + + return [ + 'id' => $this->id, + 'approved_status' => $this->approved_status, + 'approved_status_text' => $this->approved_status_text, + 'subject_type' => $this->subject_type, + 'subject_id' => $this->subject_id, + 'subject_name' => $subjectName, + 'causer_type' => $this->causer_type, + 'causer_id' => $this->causer_id, + 'causer_name' => optional($this->causer)->name, // Nome do causer se disponível + + 'motive' => $this->motive, + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + + ]; + } +} diff --git a/app/Http/Resources/Api/V1/Gender/GenderResource.php b/app/Http/Resources/Api/V1/Gender/GenderResource.php new file mode 100644 index 00000000..ea7215a2 --- /dev/null +++ b/app/Http/Resources/Api/V1/Gender/GenderResource.php @@ -0,0 +1,54 @@ + $this->id, + 'name' => $this->name, + 'name_translated' => $this->name_translated, + 'icon' => $this->icon, + 'icon_url' => $this->icon_url, + 'icon_file_name' => $this->icon_file_name, + 'icon_file_extension' => $this->icon_file_extension, + 'icon_file_size' => $this->icon_file_size, + 'original_locale' => $this->original_locale, + 'is_active' => $this->is_active, + 'is_active_text' => $this->is_active_text, + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + 'updated_at' => [ + 'default' => $this->updated_at, + 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + ], + 'deleted_at' => [ + 'default' => $this->deleted_at, + 'short' => $this->deleted_at ? Carbon::parse($this->deleted_at)->isoFormat('L') : null, + 'short_with_time' => $this->deleted_at ? Carbon::parse($this->deleted_at)->isoFormat('L LT') : null, + 'human' => $this->deleted_at ? Carbon::parse($this->deleted_at)->diffForHumans() : null, + ], + 'users' => UserResource::collection($this->whenLoaded('users')), + 'active_motives' => ActiveMotiveResource::collection($this->whenLoaded('activeMotives')), + 'activities' => ActivityLogResource::collection($this->whenLoaded('activities')) + ]; + } +} \ No newline at end of file diff --git a/app/Http/Resources/Api/V1/PasswordResetLog/FailedPasswordResetResource.php b/app/Http/Resources/Api/V1/PasswordResetLog/FailedPasswordResetResource.php new file mode 100644 index 00000000..cd05eaf8 --- /dev/null +++ b/app/Http/Resources/Api/V1/PasswordResetLog/FailedPasswordResetResource.php @@ -0,0 +1,29 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'username' => $this->username, + 'email' => $this->email, + 'device' => $this->device, + 'ip_address' => $this->ip_address, + 'user' => new UserResource($this->whenLoaded('user')), + 'attempted_at' => $this->attempted_at, + ]; + } +} diff --git a/app/Http/Resources/Api/V1/PasswordResetLog/SuccessfulPasswordResetResource.php b/app/Http/Resources/Api/V1/PasswordResetLog/SuccessfulPasswordResetResource.php new file mode 100644 index 00000000..e8cbf957 --- /dev/null +++ b/app/Http/Resources/Api/V1/PasswordResetLog/SuccessfulPasswordResetResource.php @@ -0,0 +1,28 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'username' => $this->username, + 'email' => $this->email, + 'device' => $this->device, + 'ip_address' => $this->ip_address, + 'user' => new UserResource($this->whenLoaded('user')), + 'reset_at' => $this->reset_at, + ]; + } +} diff --git a/app/Http/Resources/Api/V1/Profile/ProfileResource.php b/app/Http/Resources/Api/V1/Profile/ProfileResource.php new file mode 100644 index 00000000..87f64741 --- /dev/null +++ b/app/Http/Resources/Api/V1/Profile/ProfileResource.php @@ -0,0 +1,65 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'last_name' => $this->last_name, + 'full_name' => $this->full_name, + 'email' => $this->email, + 'username' => $this->username, + 'locale' => $this->locale, + 'genre' => $this->genre, + 'phone' => $this->phone, + 'group_id' => $this->group_id, + 'sub_group_id' => $this->sub_group_id, + + 'send_notifications' => $this->send_notifications, + 'use_term' => $this->use_term, + 'is_active' => $this->is_active, + 'is_active_text' => $this->is_active_text, + 'approved_status' => $this->approved_status, + 'approved_status_text' => $this->approved_status_text, + 'avatar_url' => $this->avatar_url, + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + 'updated_at' => [ + 'default' => $this->updated_at, + 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + ], + 'active_motives' => ActiveMotiveResource::collection($this->whenLoaded('activeMotives')), + 'approved_status_motives' => ApprovedStatusMotiveResource::collection($this->whenLoaded('approvedMotives')), + + 'roles' => RoleResource::collection($this->whenLoaded('roles')), + 'activities' => ActivityLogResource::collection($this->whenLoaded('activities')), + + // 'tokens' => ActivityResource::collection($this->whenLoaded('tokens')), + + ]; + } +} diff --git a/app/Http/Resources/Api/V1/User/UserNotificationResource.php b/app/Http/Resources/Api/V1/User/UserNotificationResource.php new file mode 100644 index 00000000..fdfa8e97 --- /dev/null +++ b/app/Http/Resources/Api/V1/User/UserNotificationResource.php @@ -0,0 +1,56 @@ + $this->id, + 'type' => $this->type, + 'notifiable_type' => $this->notifiable_type, + 'notifiable_id' => $this->notifiable_id, + 'data' => $this->data, + 'read_at' => [ + 'default' => $this->read_at, + 'short' => $this->read_at ? Carbon::parse($this->read_at)->isoFormat('L') : null, + 'short_with_time' => $this->read_at ? Carbon::parse($this->read_at)->isoFormat('L LT') : null, + 'human' => $this->read_at ? Carbon::parse($this->read_at)->diffForHumans() : null, + ], + // 'read_at' => $this->read_at?->toDateTimeString(), + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + 'updated_at' => [ + 'default' => $this->updated_at, + 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + ], + // Relacionamentos (se necessário) + 'notifiable' => $this->whenLoaded('notifiable'), + + // Links + // 'links' => [ + // 'self' => route('api.notifications.show', $this->id), + // 'mark_as_read' => route('api.notifications.mark-as-read', $this->id), + // ], + ]; + } +} diff --git a/app/Http/Resources/Api/V1/User/UserResource.php b/app/Http/Resources/Api/V1/User/UserResource.php new file mode 100644 index 00000000..042b989e --- /dev/null +++ b/app/Http/Resources/Api/V1/User/UserResource.php @@ -0,0 +1,65 @@ + $this->id, + 'name' => $this->name, + 'email' => $this->email, + 'username' => $this->username, + 'pin_code' => $this->pin_code, + 'locale' => $this->locale, + 'nickname' => $this->nickname, + 'is_active' => $this->is_active, + 'is_active_text' => $this->is_active_text, + 'approved_status' => $this->approved_status, + 'approved_status_text' => $this->approved_status_text, + 'email_verified_at' => [ + 'default' => $this->email_verified_at, + 'short' => $this->email_verified_at ? Carbon::parse($this->email_verified_at)->isoFormat('L') : null, + 'short_with_time' => $this->email_verified_at ? Carbon::parse($this->email_verified_at)->isoFormat('L LT') : null, + 'human' => $this->email_verified_at ? Carbon::parse($this->email_verified_at)->diffForHumans() : null, + ], + 'avatar' => $this->avatar, + 'avatar_url' => $this->avatar_url, + 'original_file_name' => $this->original_file_name, + 'created_at' => [ + 'default' => $this->created_at, + 'short' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L') : null, + 'short_with_time' => $this->created_at ? Carbon::parse($this->created_at)->isoFormat('L LT') : null, + 'human' => $this->created_at ? Carbon::parse($this->created_at)->diffForHumans() : null, + ], + 'updated_at' => [ + 'default' => $this->updated_at, + 'short' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L') : null, + 'short_with_time' => $this->updated_at ? Carbon::parse($this->updated_at)->isoFormat('L LT') : null, + 'human' => $this->updated_at ? Carbon::parse($this->updated_at)->diffForHumans() : null, + ], + 'deleted_at' => [ + 'default' => $this->deleted_at, + 'short' => $this->deleted_at ? Carbon::parse($this->deleted_at)->isoFormat('L') : null, + 'short_with_time' => $this->deleted_at ? Carbon::parse($this->deleted_at)->isoFormat('L LT') : null, + 'human' => $this->deleted_at ? Carbon::parse($this->deleted_at)->diffForHumans() : null, + ], + 'registeredBy' => new UserResource($this->whenLoaded('registeredBy')), + + 'activities' => ActivityLogResource::collection($this->whenLoaded('activities')), + 'actions' => ActivityLogResource::collection($this->whenLoaded('actions')), + 'approvedMotives' => ApprovedStatusMotiveResource::collection($this->whenLoaded('approvedMotives')), + 'roles' => RoleResource::collection($this->whenLoaded('roles')), + ]; + } +} diff --git a/app/Models/AbstractContracts/ActiveHistoric.php b/app/Models/AbstractContracts/ActiveHistoric.php new file mode 100644 index 00000000..217da943 --- /dev/null +++ b/app/Models/AbstractContracts/ActiveHistoric.php @@ -0,0 +1,100 @@ + 'ACTIVE', '0' => 'INACTIVE']; + + public $guarded = []; + /** + * The attributes that are mass assignable. + * + * @var array + */ + // protected $fillable = [ + // 'causer_type', + // 'causer_id', + // 'is_active', + // 'motive', + // ]; + + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'is_active' => 'boolean', + ]; + + //APPENDS + protected $appends = [ + 'is_active_text', + ]; + + public function getIsActiveTextAttribute() + { + if ($this->is_active) { + return __(self::IS_ACTIVE_TEXT[1]); + } + return __(self::IS_ACTIVE_TEXT[0]); + } + + //SCOPES + public function scopeSubjectName(Builder $query, ?string $subjectName) + { + if ($subjectName) { + return $query->whereHas('subject', function ($subQuery) use ($subjectName) { + // Obter o que_subject_name a partir do LogSubjectType + $subjectType = LogSubjectType::where('type', $this->subject_type)->first(); + $fieldName = $subjectType ? $subjectType->what_subject_name : 'name'; // Padrão para 'name' + $subQuery->where($fieldName, 'like', "%{$subjectName}%"); + }); + } + return $query; + } + + // Escopo para filtrar por nome do causer (nome do responsável pela ação) + public function scopeCauserName(Builder $query, $name) + { + return $query->whereHas('causer', function ($q) use ($name) { + $q->where('name', 'like', "%{$name}%"); + }); + } + + //RELATIONS + /** + * Get all of the models that own comments. + */ + // public function subject() + // { + // return $this->morphTo(); + // } + + public function subject(): MorphTo + { + // if (config('activitylog.subject_returns_soft_deleted_models')) { + // return $this->morphTo()->withTrashed(); + // } + + return $this->morphTo(); + } + + public function causer(): MorphTo + { + return $this->morphTo(); + } +} diff --git a/app/Models/AbstractContracts/ActivityLog.php b/app/Models/AbstractContracts/ActivityLog.php new file mode 100644 index 00000000..21f7a985 --- /dev/null +++ b/app/Models/AbstractContracts/ActivityLog.php @@ -0,0 +1,288 @@ +where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + $query->whereDate('deleted_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('created_at', $month) + ->whereDay('created_at', $day); + $query->whereMonth('updated_at', $month) + ->whereDay('updated_at', $day); + $query->whereMonth('deleted_at', $month) + ->whereDay('deleted_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('created_at', $day); + $query->whereDay('updated_at', $day); + $query->whereDay('deleted_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('created_at', $month); + $query->whereMonth('updated_at', $month); + $query->whereMonth('deleted_at', $month); + } else { + $query->orWhere('subject_type', 'LIKE', "%$search%"); + $query->orWhere('subject_id', 'LIKE', "%$search%"); + $query->orWhere('subject_name', 'LIKE', "%$search%"); + $query->orWhere('event', 'LIKE', "%$search%"); + $query->orWhere('causer_type', 'LIKE', "%$search%"); + $query->orWhere('causer_id', 'LIKE', "%$search%"); + $query->orWhereHas('causer', function ($q) use ($search) { + $q->where('name', 'like', "%{$search}%"); + }); + $query->orWhereHas('subject', function ($q) use ($search) { + // Obter o que_subject_name a partir do LogSubjectType + $subjectType = LogSubjectType::where('type', $this->subject_type)->first(); + $fieldName = $subjectType ? $subjectType->what_subject_name : 'name'; // Padrão para 'name' + $q->where($fieldName, 'like', "%{$search}%"); + }); + } + }); + } + } + public function scopeSubjectName(Builder $query, ?string $subjectName) + { + if ($subjectName) { + return $query->whereHas('subject', function ($subQuery) use ($subjectName) { + // Obter o que_subject_name a partir do LogSubjectType + $subjectType = LogSubjectType::where('type', $this->subject_type)->first(); + $fieldName = $subjectType ? $subjectType->what_subject_name : 'name'; // Padrão para 'name' + $subQuery->where($fieldName, 'like', "%{$subjectName}%"); + }); + } + return $query; + } + + // Escopo para filtrar por nome do causer (nome do responsável pela ação) + public function scopeCauserName(Builder $query, $name) + { + return $query->whereHas('causer', function ($q) use ($name) { + $q->where('name', 'like', "%{$name}%"); + }); + } + + public function scopeCreatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeCreatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeCreatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeCreatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('created_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeCreatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('created_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeCreatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('created_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeCreatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('created_at', DateService::currentMonth()) + ->whereYear('created_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeCreatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeCreatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + + // Método para obter o nome ou título do sujeito + public function getSubjectDisplayNameAttribute() + { + $subject = $this->subject; + + if ($subject) { + // Retornar 'title' se existir, caso contrário, retornar 'name' + return $subject->title ?? $subject->name ?? 'Unknown'; + } + + return 'Unknown'; + } + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * id,name,IsActive,IsNotActive,CreatedAt,CreatedAtBefore,CreatedAtAfter,CreatedAtBetween,CreatedAtCurrentDay,CreatedAtCurrentWeek,CreatedAtCurrentMonth,CreatedAtLastDays,CreatedAtNextDays,UpdatedAt,UpdatedAtBefore,UpdatedAtAfter,UpdatedAtBetween,UpdatedAtCurrentDay,UpdatedAtCurrentWeek,UpdatedAtCurrentMonth,UpdatedAtLastDays,UpdatedAtNextDays,DeletedAt,DeletedAtBefore,DeletedAtAfter,DeletedAtBetween,DeletedAtCurrentDay,DeletedAtCurrentWeek,DeletedAtCurrentMonth,DeletedAtLastDays,DeletedAtNextDays,WithTrashed,OnlyTrashed,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::exact('id'), + AllowedFilter::exact('event'), // Filtra por evento (created, updated, deleted) + AllowedFilter::exact('subject_type'), // Filtra pelo tipo de subject (modelo afetado) + AllowedFilter::exact('subject_id'), // Filtra pelo ID do subject + AllowedFilter::scope('subject_name'), // Filtra pelo nome do subject + AllowedFilter::exact('causer_id'), // Filtra pelo ID do causer + AllowedFilter::scope('causer_name'), // Filtra pelo nome do causer + AllowedFilter::scope('CreatedAt'), + AllowedFilter::scope('CreatedAtBefore'), + AllowedFilter::scope('CreatedAtAfter'), + AllowedFilter::scope('CreatedAtBetween'), + AllowedFilter::scope('CreatedAtCurrentDay'), + AllowedFilter::scope('CreatedAtCurrentWeek'), + AllowedFilter::scope('CreatedAtCurrentMonth'), + AllowedFilter::scope('CreatedAtLastDays'), + AllowedFilter::scope('CreatedAtNextDays'), + AllowedFilter::scope('UpdatedAt'), + AllowedFilter::scope('UpdatedAtBefore'), + AllowedFilter::scope('UpdatedAtAfter'), + AllowedFilter::scope('UpdatedAtBetween'), + AllowedFilter::scope('UpdatedAtCurrentDay'), + AllowedFilter::scope('UpdatedAtCurrentWeek'), + AllowedFilter::scope('UpdatedAtCurrentMonth'), + AllowedFilter::scope('UpdatedAtLastDays'), + AllowedFilter::scope('UpdatedAtNextDays'), + AllowedFilter::scope('DeletedAt'), + AllowedFilter::scope('DeletedAtBefore'), + AllowedFilter::scope('DeletedAtAfter'), + AllowedFilter::scope('DeletedAtBetween'), + AllowedFilter::scope('DeletedAtCurrentDay'), + AllowedFilter::scope('DeletedAtCurrentWeek'), + AllowedFilter::scope('DeletedAtCurrentMonth'), + AllowedFilter::scope('DeletedAtLastDays'), + AllowedFilter::scope('DeletedAtNextDays'), + AllowedFilter::scope('WithTrashed'), + AllowedFilter::scope('OnlyTrashed'), + + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes relationships. + * users,subject,causer + */ + public static function ALLOWEDINCLUDES() + { + return ['subject', 'causer']; + } + + /** + * The allowed sorts attributes. + * id,subject_type,subject_name,event,causer_type,causer_name,created_at,updated_at,deleted_at + */ + public static function ALLOWEDSORTS() + { + return ['id', 'subject_type', 'subject_name', 'event', 'causer_type', 'causer_name', 'created_at', 'updated_at', 'deleted_at']; + } + + /** + * The Default sorts attributes. + * name + */ + public static function DEFAULTSORT() + { + return ['-created_at']; + } + + /** + * The default includes relationships. + * users + */ + public static function DEFAULTINCLUDES() + { + return ['subject', 'causer']; + } +} diff --git a/app/Models/AbstractContracts/ApproveHistoric.php b/app/Models/AbstractContracts/ApproveHistoric.php new file mode 100644 index 00000000..ed34bd50 --- /dev/null +++ b/app/Models/AbstractContracts/ApproveHistoric.php @@ -0,0 +1,123 @@ + 'ANALISYS', '2' => 'APPROVED', '3' => 'UNAPPROVED', '4' => 'BLOCKED', '5' => 'CANCELED']; + const IS_ACTIVE_TEXT = ['1' => 'ACTIVE', '0' => 'INACTIVE']; + + public $guarded = []; + /** + * The attributes that are mass assignable. + * + * @var array + */ + // protected $fillable = [ + // 'causer_type', + // 'causer_id', + + // 'approved_status', + // 'motive', + // ]; + + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + // + ]; + + + //APPENDS + protected $appends = [ + 'approved_status_text', + ]; + + public function getApprovedStatusTextAttribute() + { + return __(self::APPROVED_STATUS_TEXT[$this->approved_status]); + } + + //SCOPES + public function scopeSubjectName(Builder $query, ?string $subjectName) + { + if ($subjectName) { + return $query->whereHas('subject', function ($subQuery) use ($subjectName) { + // Obter o que_subject_name a partir do LogSubjectType + $subjectType = LogSubjectType::where('type', $this->subject_type)->first(); + $fieldName = $subjectType ? $subjectType->what_subject_name : 'name'; // Padrão para 'name' + $subQuery->where($fieldName, 'like', "%{$subjectName}%"); + }); + } + return $query; + } + + // Escopo para filtrar por nome do causer (nome do responsável pela ação) + public function scopeCauserName(Builder $query, $name) + { + return $query->whereHas('causer', function ($q) use ($name) { + $q->where('name', 'like', "%{$name}%"); + }); + } + + public function scopeAnalisys(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_ANALISYS); + } + + public function scopeApproved(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_APPROVED); + } + + public function scopeUnapproved(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_UNAPPROVED); + } + + public function scopeBlocked(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_BLOCKED); + } + + + //RELATIONS + /** + * Get all of the models that own comments. + */ + public function subject(): MorphTo + { + // if (config('activitylog.subject_returns_soft_deleted_models')) { + // return $this->morphTo()->withTrashed(); + // } + return $this->morphTo(); + } + + public function causer(): MorphTo + { + return $this->morphTo(); + } +} diff --git a/app/Models/AbstractContracts/CommandLog.php b/app/Models/AbstractContracts/CommandLog.php new file mode 100644 index 00000000..c05c15ba --- /dev/null +++ b/app/Models/AbstractContracts/CommandLog.php @@ -0,0 +1,167 @@ +where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('executed_at', $month) + ->whereDay('executed_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('executed_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('executed_at', $month); + } else { + $query->orWhere('command', 'LIKE', "%$search%"); + } + }); + } + } + + public function scopeExecutedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeExecutedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeExecutedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeExecutedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('executed_at', [$parsedStartDate->format('Y-m-d'), $parsedEndDate->format('Y-m-d')]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('executed_at', $parsedDate); + }); + } + } + + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * command,status,ExecutedAt,ExecutedAtBefore,ExecutedAtAfter,ExecutedAtBetween,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::partial('command'), + AllowedFilter::exact('status'), + + AllowedFilter::scope('ExecutedAt'), + AllowedFilter::scope('ExecutedAtBefore'), + AllowedFilter::scope('ExecutedAtAfter'), + AllowedFilter::scope('ExecutedAtBetween'), + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes attributes. + * + */ + public static function ALLOWEDINCLUDES() + { + return []; + } + + /** + * The allowed sorts attributes. + * executed_at + */ + public static function ALLOWEDSORTS() + { + return ['executed_at']; + } + + /** + * The Default sorts attributes. + * executed_at + */ + public static function DEFAULTSORT() + { + return ['executed_at']; + } +} diff --git a/app/Models/AbstractContracts/DeletedRecord.php b/app/Models/AbstractContracts/DeletedRecord.php new file mode 100644 index 00000000..38632c8d --- /dev/null +++ b/app/Models/AbstractContracts/DeletedRecord.php @@ -0,0 +1,189 @@ +where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('deleted_at', $month) + ->whereDay('deleted_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('deleted_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('deleted_at', $month); + } + }); + } + } + + public function scopeDeletedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeDeletedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeDeletedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeDeletedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('deleted_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('deleted_at', $parsedDate); + }); + } + } + + + + // public function scopeSubjectName(Builder $query, ?string $subjectName) + // { + // if ($subjectName) { + // return $query->whereHas('subject', function ($subQuery) use ($subjectName) { + // // Obter o que_subject_name a partir do LogSubjectType + // $subjectType = LogSubjectType::where('type', $this->subject_type)->first(); + // $fieldName = $subjectType ? $subjectType->what_subject_name : 'name'; // Padrão para 'name' + // $subQuery->where($fieldName, 'like', "%{$subjectName}%"); + // }); + // } + // return $query; + // } + + // Escopo para filtrar por nome do causer (nome do responsável pela ação) + public function scopeCauserName(Builder $query, $name) + { + return $query->whereHas('causer', function ($q) use ($name) { + $q->where('name', 'like', "%{$name}%"); + }); + } + + public function subject() + { + return $this->morphTo(); + } + public function causer() + { + return $this->morphTo(); + } + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * DeletedAt,DeletedAtBefore,DeletedAtAfter,DeletedAtBetween,CauserName,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::scope('DeletedAt'), + AllowedFilter::scope('DeletedAtBefore'), + AllowedFilter::scope('DeletedAtAfter'), + AllowedFilter::scope('DeletedAtBetween'), + AllowedFilter::scope('CauserName'), + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes attributes. + * + */ + public static function ALLOWEDINCLUDES() + { + return []; + } + + /** + * The allowed sorts attributes. + * deleted_at + */ + public static function ALLOWEDSORTS() + { + return ['deleted_at']; + } + + /** + * The Default sorts attributes. + * deleted_at + */ + public static function DEFAULTSORT() + { + return ['deleted_at']; + } +} diff --git a/app/Models/AbstractContracts/Gender.php b/app/Models/AbstractContracts/Gender.php new file mode 100644 index 00000000..5850c763 --- /dev/null +++ b/app/Models/AbstractContracts/Gender.php @@ -0,0 +1,385 @@ + 'INACTIVE', '1' => 'ACTIVE']; + + + + use HasDateScopes; + protected $dateFields = ['created_at', 'updated_at', 'deleted_at']; + protected $cascadeDeletes = []; + + + protected $fillable = [ + 'name', + 'icon', + 'icon_file_name', + 'icon_file_size', + 'icon_file_extension', + 'original_locale', + 'is_active', + 'deleted_by_parent', + ]; + + protected $casts = [ + 'name' => 'string', + 'icon' => 'string', + 'original_locale' => 'string', + 'is_active' => 'boolean', + 'deleted_by_parent' => 'boolean', + ]; + + // APPENDS + protected $appends = [ + 'icon_url', + 'is_active_text' + ]; + + public function getIsActiveTextAttribute() + { + return __(self::IS_ACTIVE_TEXT[$this->is_active]); + } + + public function getIconUrlAttribute() + { + $storage = self::ICON_STORAGE . '/'; + if (!$this->icon) { + return null; // asset('noimage.png'); + } + return Storage::url($storage . $this->icon); + } + + + // INCLUDES + + public function activeMotives() + { + return $this->morphMany(ActiveHistoric::class, 'subject'); + } + + + + // SCOPES + + public function scopeSearch(Builder $builder, string $search) + { + $parsedDate = DateService::parseDate($search); + + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + $query->whereDate('deleted_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('created_at', $month) + ->whereDay('created_at', $day); + $query->whereMonth('updated_at', $month) + ->whereDay('updated_at', $day); + $query->whereMonth('deleted_at', $month) + ->whereDay('deleted_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('created_at', $day); + $query->whereDay('updated_at', $day); + $query->whereDay('deleted_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('created_at', $month); + $query->whereMonth('updated_at', $month); + $query->whereMonth('deleted_at', $month); + } else { + $query->orWhere('name', 'LIKE', "%$search%"); + $query->orWhereHas('translations', fn($q) => $q->where('name_translated', 'LIKE', "%$search%")); + } + }); + } + } + + + public function scopeIsActive(Builder $query): void + { + $query->where('is_active', 1); + } + + + public function scopeIsNotActive(Builder $query): void + { + $query->where('is_active', 0); + } + + + public function scopeDeletedAt(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'deleted_at', 'At', $date); + } + + public function scopeDeletedAtBefore(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtBefore', $date); + } + + public function scopeDeletedAtAfter(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtAfter', $date); + } + + public function scopeDeletedAtBetween(Builder $builder, $startDate, $endDate) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtBetween', $startDate, $endDate); + } + + public function scopeDeletedAtCurrentDay(Builder $builder) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtCurrentDay'); + } + + public function scopeDeletedAtCurrentWeek(Builder $builder) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtCurrentWeek'); + } + + public function scopeDeletedAtCurrentMonth(Builder $builder) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtCurrentMonth'); + } + + public function scopeDeletedAtLastDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtLastDays', $days); + } + + public function scopeDeletedAtNextDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'deleted_at', 'AtNextDays', $days); + } + + public function scopeCreatedAt(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'created_at', 'At', $date); + } + + public function scopeCreatedAtBefore(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'created_at', 'AtBefore', $date); + } + + public function scopeCreatedAtAfter(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'created_at', 'AtAfter', $date); + } + + public function scopeCreatedAtBetween(Builder $builder, $startDate, $endDate) + { + return $this->applyDateScope($builder, 'created_at', 'AtBetween', $startDate, $endDate); + } + + public function scopeCreatedAtCurrentDay(Builder $builder) + { + return $this->applyDateScope($builder, 'created_at', 'AtCurrentDay'); + } + + public function scopeCreatedAtCurrentWeek(Builder $builder) + { + return $this->applyDateScope($builder, 'created_at', 'AtCurrentWeek'); + } + + public function scopeCreatedAtCurrentMonth(Builder $builder) + { + return $this->applyDateScope($builder, 'created_at', 'AtCurrentMonth'); + } + + public function scopeCreatedAtLastDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'created_at', 'AtLastDays', $days); + } + + public function scopeCreatedAtNextDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'created_at', 'AtNextDays', $days); + } + + public function scopeUpdatedAt(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'updated_at', 'At', $date); + } + + public function scopeUpdatedAtBefore(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'updated_at', 'AtBefore', $date); + } + + public function scopeUpdatedAtAfter(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'updated_at', 'AtAfter', $date); + } + + public function scopeUpdatedAtBetween(Builder $builder, $startDate, $endDate) + { + return $this->applyDateScope($builder, 'updated_at', 'AtBetween', $startDate, $endDate); + } + + public function scopeUpdatedAtCurrentDay(Builder $builder) + { + return $this->applyDateScope($builder, 'updated_at', 'AtCurrentDay'); + } + + public function scopeUpdatedAtCurrentWeek(Builder $builder) + { + return $this->applyDateScope($builder, 'updated_at', 'AtCurrentWeek'); + } + + public function scopeUpdatedAtCurrentMonth(Builder $builder) + { + return $this->applyDateScope($builder, 'updated_at', 'AtCurrentMonth'); + } + + public function scopeUpdatedAtLastDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'updated_at', 'AtLastDays', $days); + } + + public function scopeUpdatedAtNextDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'updated_at', 'AtNextDays', $days); + } + + + public function scopeWithTrashed($query) + { + return $query->withTrashed(); + } + + public function scopeOnlyTrashed($query) + { + return $query->onlyTrashed(); + } + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * id,name,IsActive,IsNotActive,CreatedAt,CreatedAtBefore,CreatedAtAfter,CreatedAtBetween,CreatedAtCurrentDay,CreatedAtCurrentWeek,CreatedAtCurrentMonth,CreatedAtLastDays,CreatedAtNextDays,UpdatedAt,UpdatedAtBefore,UpdatedAtAfter,UpdatedAtBetween,UpdatedAtCurrentDay,UpdatedAtCurrentWeek,UpdatedAtCurrentMonth,UpdatedAtLastDays,UpdatedAtNextDays,DeletedAt,DeletedAtBefore,DeletedAtAfter,DeletedAtBetween,DeletedAtCurrentDay,DeletedAtCurrentWeek,DeletedAtCurrentMonth,DeletedAtLastDays,DeletedAtNextDays,WithTrashed,OnlyTrashed,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::exact('id'), + AllowedFilter::partial('name'), + AllowedFilter::scope('IsActive'), + AllowedFilter::scope('IsNotActive'), + AllowedFilter::scope('CreatedAt'), + AllowedFilter::scope('CreatedAtBefore'), + AllowedFilter::scope('CreatedAtAfter'), + AllowedFilter::scope('CreatedAtBetween'), + AllowedFilter::scope('CreatedAtCurrentDay'), + AllowedFilter::scope('CreatedAtCurrentWeek'), + AllowedFilter::scope('CreatedAtCurrentMonth'), + AllowedFilter::scope('CreatedAtLastDays'), + AllowedFilter::scope('CreatedAtNextDays'), + AllowedFilter::scope('UpdatedAt'), + AllowedFilter::scope('UpdatedAtBefore'), + AllowedFilter::scope('UpdatedAtAfter'), + AllowedFilter::scope('UpdatedAtBetween'), + AllowedFilter::scope('UpdatedAtCurrentDay'), + AllowedFilter::scope('UpdatedAtCurrentWeek'), + AllowedFilter::scope('UpdatedAtCurrentMonth'), + AllowedFilter::scope('UpdatedAtLastDays'), + AllowedFilter::scope('UpdatedAtNextDays'), + AllowedFilter::scope('DeletedAt'), + AllowedFilter::scope('DeletedAtBefore'), + AllowedFilter::scope('DeletedAtAfter'), + AllowedFilter::scope('DeletedAtBetween'), + AllowedFilter::scope('DeletedAtCurrentDay'), + AllowedFilter::scope('DeletedAtCurrentWeek'), + AllowedFilter::scope('DeletedAtCurrentMonth'), + AllowedFilter::scope('DeletedAtLastDays'), + AllowedFilter::scope('DeletedAtNextDays'), + AllowedFilter::scope('WithTrashed'), + AllowedFilter::scope('OnlyTrashed'), + + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes relationships. + * users,activeMotives,activities + */ + public static function ALLOWEDINCLUDES() + { + return ['activeMotives', 'activities']; + } + + /** + * The allowed sorts attributes. + * id,name,is_active,created_at,updated_at,deleted_at + */ + public static function ALLOWEDSORTS() + { + return ['id', 'name', 'is_active', 'created_at', 'updated_at', 'deleted_at']; + } + + /** + * The Default sorts attributes. + * name + */ + public static function DEFAULTSORT() + { + return ['name']; + } + + /** + * The default includes relationships. + * users + */ + public static function DEFAULTINCLUDES() + { + return ['activeMotives', 'activities']; + } + + + // ACTYVITY LOGS + public function getActivitylogOptions(): LogOptions + { + return LogOptions::defaults()->logFillable()->dontSubmitEmptyLogs()->logOnlyDirty(); + } +} diff --git a/app/Models/AbstractContracts/LogSubjectType.php b/app/Models/AbstractContracts/LogSubjectType.php new file mode 100644 index 00000000..88e827a0 --- /dev/null +++ b/app/Models/AbstractContracts/LogSubjectType.php @@ -0,0 +1,12 @@ + 'string', + 'ip_address' => 'string', + 'user_agent' => 'string', + 'status' => 'string', + 'error_message' => 'string', + 'user_id' => 'integer', + 'deleted_by_parent' => 'boolean', + ]; + + // APPENDS + protected $appends = [ + + ]; + + + // INCLUDES + public function user() { return $this->belongsTo(User::class); } + + // SCOPES + + public function scopeSearch(Builder $builder, string $search) + { + $parsedDate = DateService::parseDate($search); + + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('created_at', $month) + ->whereDay('created_at', $day); + $query->whereMonth('updated_at', $month) + ->whereDay('updated_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('created_at', $day); + $query->whereDay('updated_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('created_at', $month); + $query->whereMonth('updated_at', $month); + } else { + $query->orWhere('identifier', 'LIKE', "%$search%"); + $query->orWhere('ip_address', 'LIKE', "%$search%"); + $query->orWhere('user_agent', 'LIKE', "%$search%"); + $query->orWhere('status', 'LIKE', "%$search%"); + $query->orWhere('error_message', 'LIKE', "%$search%"); + } + }); + } + } + + + + public function scopeCreatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeCreatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeCreatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeCreatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('created_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeCreatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('created_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeCreatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('created_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeCreatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('created_at', DateService::currentMonth()) + ->whereYear('created_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeCreatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeCreatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + public function scopeUpdatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeUpdatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeUpdatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeUpdatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('updated_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeUpdatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('updated_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeUpdatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('updated_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeUpdatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('updated_at', DateService::currentMonth()) + ->whereYear('updated_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeUpdatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('updated_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeUpdatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('updated_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * id,identifier,ip_address,user_agent,status,error_message,user_id,CreatedAt,CreatedAtBefore,CreatedAtAfter,CreatedAtBetween,CreatedAtCurrentDay,CreatedAtCurrentWeek,CreatedAtCurrentMonth,CreatedAtLastDays,CreatedAtNextDays,UpdatedAt,UpdatedAtBefore,UpdatedAtAfter,UpdatedAtBetween,UpdatedAtCurrentDay,UpdatedAtCurrentWeek,UpdatedAtCurrentMonth,UpdatedAtLastDays,UpdatedAtNextDays,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::exact('id'), + AllowedFilter::partial('identifier'), + AllowedFilter::partial('ip_address'), + AllowedFilter::partial('user_agent'), + AllowedFilter::partial('status'), + AllowedFilter::partial('error_message'), + AllowedFilter::exact('user_id'), + AllowedFilter::scope('CreatedAt'), + AllowedFilter::scope('CreatedAtBefore'), + AllowedFilter::scope('CreatedAtAfter'), + AllowedFilter::scope('CreatedAtBetween'), + AllowedFilter::scope('CreatedAtCurrentDay'), + AllowedFilter::scope('CreatedAtCurrentWeek'), + AllowedFilter::scope('CreatedAtCurrentMonth'), + AllowedFilter::scope('CreatedAtLastDays'), + AllowedFilter::scope('CreatedAtNextDays'), + AllowedFilter::scope('UpdatedAt'), + AllowedFilter::scope('UpdatedAtBefore'), + AllowedFilter::scope('UpdatedAtAfter'), + AllowedFilter::scope('UpdatedAtBetween'), + AllowedFilter::scope('UpdatedAtCurrentDay'), + AllowedFilter::scope('UpdatedAtCurrentWeek'), + AllowedFilter::scope('UpdatedAtCurrentMonth'), + AllowedFilter::scope('UpdatedAtLastDays'), + AllowedFilter::scope('UpdatedAtNextDays'), + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes relationships. + * user + */ + public static function ALLOWEDINCLUDES() + { + return ['user']; + } + + /** + * The allowed sorts attributes. + * id,identifier,ip_address,user_agent,status,error_message,created_at,updated_at + */ + public static function ALLOWEDSORTS() + { + return ['id', 'identifier', 'ip_address', 'user_agent', 'status', 'error_message', 'created_at', 'updated_at']; + } + + /** + * The Default sorts attributes. + * identifier,ip_address,user_agent,status,error_message + */ + public static function DEFAULTSORT() + { + return ['identifier', 'ip_address', 'user_agent', 'status', 'error_message']; + } + + /** + * The default includes relationships. + * user + */ + public static function DEFAULTINCLUDES() + { + return ['user']; + } + +} diff --git a/app/Models/AbstractContracts/User.php b/app/Models/AbstractContracts/User.php new file mode 100644 index 00000000..aaaac00d --- /dev/null +++ b/app/Models/AbstractContracts/User.php @@ -0,0 +1,648 @@ + 'INACTIVE', '1' => 'ACTIVE']; + const APPROVED_STATUS_ANALISYS = '1'; + const APPROVED_STATUS_APPROVED = '2'; + const APPROVED_STATUS_UNAPPROVED = '3'; + const APPROVED_STATUS_BLOCKED = '4'; + const APPROVED_STATUS_CANCELED = '5'; + const APPROVED_STATUS_TEXT = ['1' => 'ANALISYS', '2' => 'APPROVED', '3' => 'UNAPPROVED', '4' => 'BLOCKED', '5' => 'CANCELED']; + + + + // CASCADE DELETES + protected $cascadeDeletes = []; + + + protected $fillable = [ + 'name', + 'username', + 'nickname', + 'email', + 'email_verified_at', + 'password', + 'pin_code', + 'remember_token', + 'profile_type_id', + 'send_notifications', + 'use_term_accepted', + 'is_active', + 'approved_status', + 'deleted_by_parent', + ]; + + protected $casts = [ + 'name' => 'string', + 'username' => 'string', + 'nickname' => 'string', + 'email' => 'string', + 'email_verified_at' => 'datetime', + 'password' => 'string', + 'pin_code' => 'string', + 'remember_token' => 'string', + 'profile_type_id' => 'integer', + 'send_notifications' => 'boolean', + 'use_term_accepted' => 'boolean', + 'is_active' => 'boolean', + 'approved_status' => 'string', + 'deleted_by_parent' => 'boolean', + ]; + + // APPENDS + protected $appends = [ + 'is_active_text', + 'approved_status_text' + ]; + + public function getIsActiveTextAttribute() + { + return __(self::IS_ACTIVE_TEXT[$this->is_active]); + } + + public function getApprovedStatusTextAttribute() + { + return __(self::APPROVED_STATUS_TEXT[$this->approved_status]); + } + + + // INCLUDES + public function profile_type() + { + return $this->belongsTo(ProfileType::class); + } + + public function activeMotives() + { + return $this->morphMany(ActiveHistoric::class, 'subject'); + } + + + public function approvedMotives() + { + return $this->morphMany(ApproveHistoric::class, 'subject'); + } + + /** + * Get the user logins for the user. + */ + public function userLogins() + { + return $this->hasMany(UserLogin::class); + } + + /** + * Get the login logs for the user. + */ + public function loginLogs() + { + return $this->hasMany(LoginLog::class, 'identifier', 'email') + ->orWhere('identifier', $this->nickname); + } + + /** + * Get the user's most recent login. + */ + public function latestLogin() + { + return $this->hasOne(UserLogin::class)->latestOfMany(); + } + + // SCOPES + + public function scopeSearch(Builder $builder, string $search) + { + $parsedDate = DateService::parseDate($search); + + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate->format('Y-m-d')); + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('email_verified_at', $month) + ->whereDay('email_verified_at', $day); + $query->whereMonth('created_at', $month) + ->whereDay('created_at', $day); + $query->whereMonth('updated_at', $month) + ->whereDay('updated_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('email_verified_at', $day); + $query->whereDay('created_at', $day); + $query->whereDay('updated_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('email_verified_at', $month); + $query->whereMonth('created_at', $month); + $query->whereMonth('updated_at', $month); + } else { + $query->orWhere('name', 'LIKE', "%$search%"); + $query->orWhere('username', 'LIKE', "%$search%"); + $query->orWhere('nickname', 'LIKE', "%$search%"); + $query->orWhere('email', 'LIKE', "%$search%"); + } + }); + } + } + + public function scopeSendNotifications(Builder $query): void + { + $query->where('send_notifications', 1); + } + + + public function scopeNotSendNotifications(Builder $query): void + { + $query->where('send_notifications', 0); + } + + public function scopeUseTermAccepted(Builder $query): void + { + $query->where('use_term_accepted', 1); + } + + + public function scopeNotUseTermAccepted(Builder $query): void + { + $query->where('use_term_accepted', 0); + } + + + public function scopeIsActive(Builder $query): void + { + $query->where('is_active', 1); + } + + + public function scopeIsNotActive(Builder $query): void + { + $query->where('is_active', 0); + } + + public function scopeAnalisys(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_ANALISYS); + } + + public function scopeApproved(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_APPROVED); + } + + public function scopeUnapproved(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_UNAPPROVED); + } + + public function scopeBlocked(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_BLOCKED); + } + + public function scopeCanceled(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_CANCELED); + } + + + public function scopeCreatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeCreatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeCreatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeCreatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('created_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeCreatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('created_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeCreatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('created_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeCreatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('created_at', DateService::currentMonth()) + ->whereYear('created_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeCreatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeCreatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + public function scopeUpdatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeUpdatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeUpdatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeUpdatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('updated_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeUpdatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('updated_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeUpdatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('updated_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeUpdatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('updated_at', DateService::currentMonth()) + ->whereYear('updated_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeUpdatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('updated_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeUpdatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('updated_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + public function scopeEmailVerifiedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeEmailVerifiedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeEmailVerifiedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeEmailVerifiedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('email_verified_at', [$parsedStartDate->format('Y-m-d'), $parsedEndDate->format('Y-m-d')]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeEmailVerifiedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('email_verified_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeEmailVerifiedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('email_verified_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeEmailVerifiedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('email_verified_at', DateService::currentMonth()) + ->whereYear('email_verified_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeEmailVerifiedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('email_verified_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeEmailVerifiedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('email_verified_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + + public function scopeWithTrashed($query) + { + return $query->withTrashed(); + } + + public function scopeOnlyTrashed($query) + { + return $query->onlyTrashed(); + } + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * id,name,username,nickname,email,EmailVerifiedAt,EmailVerifiedAtBefore,EmailVerifiedAtAfter,EmailVerifiedAtBetween,EmailVerifiedAtCurrentDay,EmailVerifiedAtCurrentWeek,EmailVerifiedAtCurrentMonth,EmailVerifiedAtLastDays,EmailVerifiedAtNextDays,profile_type_id,IsActive,IsNotActive,Analisys,Approved,Unapproved,Blocked,Canceled,CreatedAt,CreatedAtBefore,CreatedAtAfter,CreatedAtBetween,CreatedAtCurrentDay,CreatedAtCurrentWeek,CreatedAtCurrentMonth,CreatedAtLastDays,CreatedAtNextDays,UpdatedAt,UpdatedAtBefore,UpdatedAtAfter,UpdatedAtBetween,UpdatedAtCurrentDay,UpdatedAtCurrentWeek,UpdatedAtCurrentMonth,UpdatedAtLastDays,UpdatedAtNextDays,WithTrashed,OnlyTrashed,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::exact('id'), + AllowedFilter::partial('name'), + AllowedFilter::partial('username'), + AllowedFilter::partial('nickname'), + AllowedFilter::partial('email'), + AllowedFilter::scope('EmailVerifiedAt'), + AllowedFilter::scope('EmailVerifiedAtBefore'), + AllowedFilter::scope('EmailVerifiedAtAfter'), + AllowedFilter::scope('EmailVerifiedAtBetween'), + AllowedFilter::scope('EmailVerifiedAtCurrentDay'), + AllowedFilter::scope('EmailVerifiedAtCurrentWeek'), + AllowedFilter::scope('EmailVerifiedAtCurrentMonth'), + AllowedFilter::scope('EmailVerifiedAtLastDays'), + AllowedFilter::scope('EmailVerifiedAtNextDays'), + AllowedFilter::exact('profile_type_id'), + AllowedFilter::scope('IsActive'), + AllowedFilter::scope('IsNotActive'), + AllowedFilter::scope('Analisys'), + AllowedFilter::scope('Approved'), + AllowedFilter::scope('Unapproved'), + AllowedFilter::scope('Blocked'), + AllowedFilter::scope('Canceled'), + AllowedFilter::scope('CreatedAt'), + AllowedFilter::scope('CreatedAtBefore'), + AllowedFilter::scope('CreatedAtAfter'), + AllowedFilter::scope('CreatedAtBetween'), + AllowedFilter::scope('CreatedAtCurrentDay'), + AllowedFilter::scope('CreatedAtCurrentWeek'), + AllowedFilter::scope('CreatedAtCurrentMonth'), + AllowedFilter::scope('CreatedAtLastDays'), + AllowedFilter::scope('CreatedAtNextDays'), + AllowedFilter::scope('UpdatedAt'), + AllowedFilter::scope('UpdatedAtBefore'), + AllowedFilter::scope('UpdatedAtAfter'), + AllowedFilter::scope('UpdatedAtBetween'), + AllowedFilter::scope('UpdatedAtCurrentDay'), + AllowedFilter::scope('UpdatedAtCurrentWeek'), + AllowedFilter::scope('UpdatedAtCurrentMonth'), + AllowedFilter::scope('UpdatedAtLastDays'), + AllowedFilter::scope('UpdatedAtNextDays'), + AllowedFilter::scope('WithTrashed'), + AllowedFilter::scope('OnlyTrashed'), + + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes attributes. + * profile_type,userLogins,loginLogs,latestLogin,activeMotives,approvedMotives,activities + */ + public static function ALLOWEDINCLUDES() + { + return ['profile_type', 'userLogins', 'loginLogs', 'latestLogin', 'latestLogin', 'activeMotives', 'approvedMotives', 'activities']; + } + /** + * The allowed includes attributes. + * profile_type,latestLogin + */ + public static function DEFAULTINCLUDES() + { + return ['profile_type', 'latestLogin']; + } + + + /** + * The allowed sorts attributes. + * id,name,username,nickname,email,email_verified_at,is_active,created_at,updated_at + */ + public static function ALLOWEDSORTS() + { + return ['id', 'name', 'username', 'nickname', 'email', 'email_verified_at', 'is_active', 'created_at', 'updated_at']; + } + + /** + * The Default sorts attributes. + * name,username,nickname,email,email_verified_at + */ + public static function DEFAULTSORT() + { + return ['name', 'username', 'nickname', 'email', 'email_verified_at']; + } + + + // ACTYVITY LOGS + public function getActivitylogOptions(): LogOptions + { + return LogOptions::defaults()->logFillable()->dontSubmitEmptyLogs(); + } +} diff --git a/app/Models/AbstractContracts/UserLogin.php b/app/Models/AbstractContracts/UserLogin.php new file mode 100644 index 00000000..764a911a --- /dev/null +++ b/app/Models/AbstractContracts/UserLogin.php @@ -0,0 +1,552 @@ + 'string', + 'ip_address' => 'string', + 'browser' => 'string', + 'browser_version' => 'string', + 'platform' => 'string', + 'device_type' => 'string', + 'is_mobile' => 'boolean', + 'is_tablet' => 'boolean', + 'is_desktop' => 'boolean', + 'logout_at' => 'datetime', + 'session_duration' => 'integer', + 'user_id' => 'integer', + 'deleted_by_parent' => 'boolean', + ]; + + // APPENDS + protected $appends = [ + + ]; + + + // INCLUDES + public function user() { return $this->belongsTo(User::class); } + + // SCOPES + + public function scopeSearch(Builder $builder, string $search) + { + $parsedDate = DateService::parseDate($search); + + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', $parsedDate->format('Y-m-d')); + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (exemplo: dia/mês ou apenas mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + // Exemplo: 29/03 (dia/mês) + list($day, $month) = explode('/', $search); + $query->whereMonth('logout_at', $month) + ->whereDay('logout_at', $day); + $query->whereMonth('created_at', $month) + ->whereDay('created_at', $day); + $query->whereMonth('updated_at', $month) + ->whereDay('updated_at', $day); + } elseif (preg_match('/^\d{1,2}\/\$/', $search)) { + // Exemplo: 29/ (somente dia) + $day = str_replace('/', '', $search); + $query->whereDay('logout_at', $day); + $query->whereDay('created_at', $day); + $query->whereDay('updated_at', $day); + } elseif (preg_match('/^\/\d{1,2}$/', $search)) { + // Exemplo: /05 (somente mês) + $month = str_replace('/', '', $search); + $query->whereMonth('logout_at', $month); + $query->whereMonth('created_at', $month); + $query->whereMonth('updated_at', $month); + } else { + $query->orWhere('token_id', 'LIKE', "%$search%"); + $query->orWhere('ip_address', 'LIKE', "%$search%"); + $query->orWhere('browser', 'LIKE', "%$search%"); + $query->orWhere('browser_version', 'LIKE', "%$search%"); + $query->orWhere('platform', 'LIKE', "%$search%"); + $query->orWhere('device_type', 'LIKE', "%$search%"); + } + }); + } + } + + public function scopeIsMobile(Builder $query): void + { + $query->where('is_mobile', 1); + } + + + public function scopeNotIsMobile(Builder $query): void + { + $query->where('is_mobile', 0); + } + + public function scopeIsTablet(Builder $query): void + { + $query->where('is_tablet', 1); + } + + + public function scopeNotIsTablet(Builder $query): void + { + $query->where('is_tablet', 0); + } + + public function scopeIsDesktop(Builder $query): void + { + $query->where('is_desktop', 1); + } + + + public function scopeNotIsDesktop(Builder $query): void + { + $query->where('is_desktop', 0); + } + + + + public function scopeCreatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeCreatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeCreatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeCreatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('created_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('created_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeCreatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('created_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeCreatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('created_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeCreatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('created_at', DateService::currentMonth()) + ->whereYear('created_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeCreatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeCreatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('created_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + public function scopeUpdatedAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeUpdatedAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeUpdatedAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeUpdatedAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('updated_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('updated_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeUpdatedAtCurrentDay(Builder $builder) + { + return $builder->whereDate('updated_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeUpdatedAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('updated_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeUpdatedAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('updated_at', DateService::currentMonth()) + ->whereYear('updated_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeUpdatedAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('updated_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeUpdatedAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('updated_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + public function scopeLogoutAt(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', $parsedDate); + }); + } + } + + // Scope for dates before a given date + public function scopeLogoutAtBefore(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', '<=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', $parsedDate); + }); + } + } + + // Scope for dates after a given date + public function scopeLogoutAtAfter(Builder $builder, $date) + { + $parsedDate = DateService::parseDate($date); + if ($parsedDate) { + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', '>=', $parsedDate->format('Y-m-d')); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', $parsedDate); + }); + } + } + + // Scope for dates between a start and end date + public function scopeLogoutAtBetween(Builder $builder, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + + if ($parsedStartDate && $parsedEndDate) { + $builder->where(function ($query) use ($parsedStartDate, $parsedEndDate) { + $query->whereBetween('logout_at', [ + $parsedStartDate->startOfDay(), + $parsedEndDate->endOfDay() + ]); + }); + } else { + $parsedDate = DateService::parseDate('1912-01-01'); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('logout_at', $parsedDate); + }); + } + } + + // Scope para filtrar por dia atual + public function scopeLogoutAtCurrentDay(Builder $builder) + { + return $builder->whereDate('logout_at', DateService::today()->format('Y-m-d')); + } + + // Scope para filtrar por semana atual + public function scopeLogoutAtCurrentWeek(Builder $builder) + { + return $builder->whereBetween('logout_at', [DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), DateService::currentEndOfWeek()->format('Y-m-d 23:59:59')]); + } + + // Scope para filtrar por mês atual + public function scopeLogoutAtCurrentMonth(Builder $builder) + { + return $builder->whereMonth('logout_at', DateService::currentMonth()) + ->whereYear('logout_at', DateService::currentYear()); + } + + // Scope para filtrar por anteriores X dias + public function scopeLogoutAtLastDays(Builder $builder, int $days) + { + return $builder->whereBetween('logout_at', [DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), DateService::today()->format('Y-m-d 23:59:59')]); + } + // Scope para filtrar por próximos X dias + public function scopeLogoutAtNextDays(Builder $builder, int $days) + { + return $builder->whereBetween('logout_at', [DateService::today()->format('Y-m-d 00:00:00'), DateService::currentNextDays($days)->format('Y-m-d 23:59:59')]); + } + + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * id,token_id,ip_address,browser,browser_version,platform,device_type,is_mobile,IsMobile,NotIsMobile,is_tablet,IsTablet,NotIsTablet,is_desktop,IsDesktop,NotIsDesktop,LogoutAt,LogoutAtBefore,LogoutAtAfter,LogoutAtBetween,LogoutAtCurrentDay,LogoutAtCurrentWeek,LogoutAtCurrentMonth,LogoutAtLastDays,LogoutAtNextDays,user_id,CreatedAt,CreatedAtBefore,CreatedAtAfter,CreatedAtBetween,CreatedAtCurrentDay,CreatedAtCurrentWeek,CreatedAtCurrentMonth,CreatedAtLastDays,CreatedAtNextDays,UpdatedAt,UpdatedAtBefore,UpdatedAtAfter,UpdatedAtBetween,UpdatedAtCurrentDay,UpdatedAtCurrentWeek,UpdatedAtCurrentMonth,UpdatedAtLastDays,UpdatedAtNextDays,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::exact('id'), + AllowedFilter::partial('token_id'), + AllowedFilter::partial('ip_address'), + AllowedFilter::partial('browser'), + AllowedFilter::partial('browser_version'), + AllowedFilter::partial('platform'), + AllowedFilter::partial('device_type'), + AllowedFilter::exact('is_mobile'), + AllowedFilter::scope('IsMobile'), + AllowedFilter::scope('NotIsMobile'), + AllowedFilter::exact('is_tablet'), + AllowedFilter::scope('IsTablet'), + AllowedFilter::scope('NotIsTablet'), + AllowedFilter::exact('is_desktop'), + AllowedFilter::scope('IsDesktop'), + AllowedFilter::scope('NotIsDesktop'), + AllowedFilter::scope('LogoutAt'), + AllowedFilter::scope('LogoutAtBefore'), + AllowedFilter::scope('LogoutAtAfter'), + AllowedFilter::scope('LogoutAtBetween'), + AllowedFilter::scope('LogoutAtCurrentDay'), + AllowedFilter::scope('LogoutAtCurrentWeek'), + AllowedFilter::scope('LogoutAtCurrentMonth'), + AllowedFilter::scope('LogoutAtLastDays'), + AllowedFilter::scope('LogoutAtNextDays'), + AllowedFilter::exact('user_id'), + AllowedFilter::scope('CreatedAt'), + AllowedFilter::scope('CreatedAtBefore'), + AllowedFilter::scope('CreatedAtAfter'), + AllowedFilter::scope('CreatedAtBetween'), + AllowedFilter::scope('CreatedAtCurrentDay'), + AllowedFilter::scope('CreatedAtCurrentWeek'), + AllowedFilter::scope('CreatedAtCurrentMonth'), + AllowedFilter::scope('CreatedAtLastDays'), + AllowedFilter::scope('CreatedAtNextDays'), + AllowedFilter::scope('UpdatedAt'), + AllowedFilter::scope('UpdatedAtBefore'), + AllowedFilter::scope('UpdatedAtAfter'), + AllowedFilter::scope('UpdatedAtBetween'), + AllowedFilter::scope('UpdatedAtCurrentDay'), + AllowedFilter::scope('UpdatedAtCurrentWeek'), + AllowedFilter::scope('UpdatedAtCurrentMonth'), + AllowedFilter::scope('UpdatedAtLastDays'), + AllowedFilter::scope('UpdatedAtNextDays'), + AllowedFilter::scope('Search'), + + ]; + } + + /** + * The allowed includes relationships. + * user + */ + public static function ALLOWEDINCLUDES() + { + return ['user']; + } + + /** + * The allowed sorts attributes. + * id,token_id,ip_address,browser,browser_version,platform,device_type,is_mobile,is_tablet,is_desktop,logout_at,created_at,updated_at + */ + public static function ALLOWEDSORTS() + { + return ['id', 'token_id', 'ip_address', 'browser', 'browser_version', 'platform', 'device_type', 'is_mobile', 'is_tablet', 'is_desktop', 'logout_at', 'created_at', 'updated_at']; + } + + /** + * The Default sorts attributes. + * token_id,ip_address,browser,browser_version,platform,device_type,is_mobile,is_tablet,is_desktop,logout_at + */ + public static function DEFAULTSORT() + { + return ['token_id', 'ip_address', 'browser', 'browser_version', 'platform', 'device_type', 'is_mobile', 'is_tablet', 'is_desktop', 'logout_at']; + } + + /** + * The default includes relationships. + * user + */ + public static function DEFAULTINCLUDES() + { + return ['user']; + } + +} diff --git a/app/Models/ActiveHistoric.php b/app/Models/ActiveHistoric.php new file mode 100644 index 00000000..422e198f --- /dev/null +++ b/app/Models/ActiveHistoric.php @@ -0,0 +1,10 @@ + TrimCast::class, + ]; +} diff --git a/app/Models/ActivityLog.php b/app/Models/ActivityLog.php new file mode 100644 index 00000000..6b4f1024 --- /dev/null +++ b/app/Models/ActivityLog.php @@ -0,0 +1,11 @@ + TrimCast::class, + ]; +} diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php new file mode 100644 index 00000000..c2fda5ec --- /dev/null +++ b/app/Models/BaseModel.php @@ -0,0 +1,27 @@ +logFillable()->dontSubmitEmptyLogs(); + } + + /** + * The number of models to return for pagination. + * + * @var int + */ + protected $perPage = 500; +} diff --git a/app/Models/CommandLog.php b/app/Models/CommandLog.php new file mode 100644 index 00000000..f48c8bc7 --- /dev/null +++ b/app/Models/CommandLog.php @@ -0,0 +1,10 @@ + TrimCast::class, + ]; +} diff --git a/app/Models/LogSubjectType.php b/app/Models/LogSubjectType.php new file mode 100644 index 00000000..1d2cff5a --- /dev/null +++ b/app/Models/LogSubjectType.php @@ -0,0 +1,10 @@ + */ use HasFactory, Notifiable; + use SoftDeletes; + use CascadeSoftDeletes; + use HasRoles; + use HasDateScopes; + use LogsActivity; + use CausesActivity; + // ACTYVITY LOGS + public function getActivitylogOptions(): LogOptions + { + return LogOptions::defaults()->logFillable()->dontSubmitEmptyLogs()->logExcept(['password', 'remember_token'])->logOnlyDirty(); + } + const AVATAR_STORAGE = 'image/user_avatar'; + const APPROVED_STATUS_ANALISYS = '1'; + const APPROVED_STATUS_APPROVED = '2'; + const APPROVED_STATUS_UNAPPROVED = '3'; + const APPROVED_STATUS_BLOCKED = '4'; + const APPROVED_STATUS_CANCELED = '5'; + const APPROVED_STATUS_TEXT = ['1' => 'ANALISYS', '2' => 'APPROVED', '3' => 'UNAPPROVED', '4' => 'BLOCKED', '5' => 'CANCELED']; + const IS_ACTIVE_TEXT = ['1' => 'ACTIVE', '0' => 'INACTIVE']; /** * The attributes that are mass assignable. * @@ -19,8 +50,18 @@ class User extends Authenticatable */ protected $fillable = [ 'name', + 'username', 'email', 'password', + 'pin_code', + 'locale', + 'nickname', + 'is_active', + 'approved_status', + 'registered_by', + 'avatar', + 'original_file_name', + ]; /** @@ -43,6 +84,343 @@ protected function casts(): array return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', + 'pin_code' => 'hashed', + 'is_active' => 'boolean', + 'approved_status' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'registered_by' => 'integer', + 'avatar' => 'string', + 'original_file_name' => 'string', + 'locale' => 'string', + 'nickname' => 'string', + ]; + } + + protected $dateFields = ['created_at', 'updated_at']; + + + // APPENDS + protected $appends = [ + 'avatar_url', + 'approved_status_text', + 'is_active_text' + ]; + + public function getIsActiveTextAttribute() + { + if ($this->is_active) { + return __(self::IS_ACTIVE_TEXT[1]); + } + return __(self::IS_ACTIVE_TEXT[0]); + } + + public function getAvatarUrlAttribute() + { + $storage = self::AVATAR_STORAGE . '/'; + + if (!$this->avatar) { + return null; //asset('noimage.png'); + } + return Storage::url($storage) . $this->avatar; + } + + public function getApprovedStatusTextAttribute() + { + return __(self::APPROVED_STATUS_TEXT[$this->approved_status]); + } + + // RELATIONSHIPS + public function registeredBy() + { + return $this->belongsTo(User::class, 'registered_by'); + } + public function activeMotives() + { + return $this->morphMany(ActiveHistoric::class, 'subject'); + } + + public function approvedMotives() + { + return $this->morphMany(ApproveHistoric::class, 'subject'); + } + + + // SCOPES + + public function scopeSearch(Builder $builder, string $search) + { + Log::debug("Search term", ['search' => $search]); + + $parsedDate = DateService::parseDate($search); + + if ($parsedDate) { + Log::debug("Valid date detected", ['parsedDate' => $parsedDate->format('Y-m-d')]); + $builder->where(function ($query) use ($parsedDate) { + $query->whereDate('email_verified_at', $parsedDate) + ->orWhereDate('created_at', $parsedDate) + ->orWhereDate('updated_at', $parsedDate); + }); + } else { + $builder->where(function ($query) use ($search) { + // Busca parcial de datas (dia/mês) + if (preg_match('/^\d{1,2}\/\d{1,2}$/', $search)) { + list($day, $month) = explode('/', $search); + $query->where(function ($q) use ($day, $month) { + $q->whereMonth('email_verified_at', $month) + ->whereDay('email_verified_at', $day) + ->orWhereMonth('created_at', $month) + ->whereDay('created_at', $day) + ->orWhereMonth('updated_at', $month) + ->whereDay('updated_at', $day); + }); + } + // Somente dia + elseif (preg_match('/^\d{1,2}\/$/', $search)) { + $day = str_replace('/', '', $search); + $query->where(function ($q) use ($day) { + $q->whereDay('email_verified_at', $day) + ->orWhereDay('created_at', $day) + ->orWhereDay('updated_at', $day); + }); + } + // Somente mês + elseif (preg_match('/^\/\d{1,2}$/', $search)) { + $month = str_replace('/', '', $search); + $query->where(function ($q) use ($month) { + $q->whereMonth('email_verified_at', $month) + ->orWhereMonth('created_at', $month) + ->orWhereMonth('updated_at', $month); + }); + } + // Busca textual + else { + $query->where('name', 'like', "%$search%") + ->orWhere('email', 'like', "%$search%") + ->orWhere('username', 'like', "%$search%") + ->orWhere('nickname', 'like', "%$search%"); + } + }); + } + } + + public function scopeIsActive(Builder $query): void + { + $query->where('is_active', 1); + } + + + public function scopeIsNotActive(Builder $query): void + { + $query->where('is_active', 0); + } + + public function scopeAnalisys(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_ANALISYS); + } + + public function scopeApproved(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_APPROVED); + } + + public function scopeUnapproved(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_UNAPPROVED); + } + + public function scopeBlocked(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_BLOCKED); + } + + public function scopeCanceled(Builder $query): void + { + $query->where('approved_status', $this::APPROVED_STATUS_CANCELED); + } + + public function scopeCreatedAt(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'created_at', 'At', $date); + } + + public function scopeCreatedAtBefore(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'created_at', 'AtBefore', $date); + } + + public function scopeCreatedAtAfter(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'created_at', 'AtAfter', $date); + } + + public function scopeCreatedAtBetween(Builder $builder, $startDate, $endDate) + { + return $this->applyDateScope($builder, 'created_at', 'AtBetween', $startDate, $endDate); + } + + public function scopeCreatedAtCurrentDay(Builder $builder) + { + return $this->applyDateScope($builder, 'created_at', 'AtCurrentDay'); + } + + public function scopeCreatedAtCurrentWeek(Builder $builder) + { + return $this->applyDateScope($builder, 'created_at', 'AtCurrentWeek'); + } + + public function scopeCreatedAtCurrentMonth(Builder $builder) + { + return $this->applyDateScope($builder, 'created_at', 'AtCurrentMonth'); + } + + public function scopeCreatedAtLastDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'created_at', 'AtLastDays', $days); + } + + public function scopeCreatedAtNextDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'created_at', 'AtNextDays', $days); + } + + public function scopeUpdatedAt(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'updated_at', 'At', $date); + } + + public function scopeUpdatedAtBefore(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'updated_at', 'AtBefore', $date); + } + + public function scopeUpdatedAtAfter(Builder $builder, $date) + { + return $this->applyDateScope($builder, 'updated_at', 'AtAfter', $date); + } + + public function scopeUpdatedAtBetween(Builder $builder, $startDate, $endDate) + { + return $this->applyDateScope($builder, 'updated_at', 'AtBetween', $startDate, $endDate); + } + + public function scopeUpdatedAtCurrentDay(Builder $builder) + { + return $this->applyDateScope($builder, 'updated_at', 'AtCurrentDay'); + } + + public function scopeUpdatedAtCurrentWeek(Builder $builder) + { + return $this->applyDateScope($builder, 'updated_at', 'AtCurrentWeek'); + } + + public function scopeUpdatedAtCurrentMonth(Builder $builder) + { + return $this->applyDateScope($builder, 'updated_at', 'AtCurrentMonth'); + } + + public function scopeUpdatedAtLastDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'updated_at', 'AtLastDays', $days); + } + + public function scopeUpdatedAtNextDays(Builder $builder, int $days) + { + return $this->applyDateScope($builder, 'updated_at', 'AtNextDays', $days); + } + + public function scopeWithTrashed($query) + { + return $query->withTrashed(); + } + + public function scopeOnlyTrashed($query) + { + return $query->onlyTrashed(); + } + + // QUERY BUILDER + + /** + * The allowed filters attributes. + * id,name,email,username,nickname,IsActive,IsNotActive,Analisys,Approved,Unapproved,Blocked,Canceled,CreatedAt,CreatedAtBefore,CreatedAtAfter,CreatedAtBetween,CreatedAtCurrentDay,CreatedAtCurrentWeek,CreatedAtCurrentMonth,CreatedAtLastDays,CreatedAtNextDays,UpdatedAt,UpdatedAtBefore,UpdatedAtAfter,UpdatedAtBetween,UpdatedAtCurrentDay,UpdatedAtCurrentWeek,UpdatedAtCurrentMonth,UpdatedAtLastDays,UpdatedAtNextDays,WithTrashed,OnlyTrashed,Search + */ + public static function ALLOWEDFILTERS() + { + return [ + AllowedFilter::exact('id'), + AllowedFilter::partial('name'), + AllowedFilter::partial('email'), + AllowedFilter::partial('username'), + AllowedFilter::partial('nickname'), + AllowedFilter::scope('IsActive'), + AllowedFilter::scope('IsNotActive'), + AllowedFilter::scope('Analisys'), + AllowedFilter::scope('Approved'), + AllowedFilter::scope('Unapproved'), + AllowedFilter::scope('Blocked'), + AllowedFilter::scope('Canceled'), + AllowedFilter::scope('CreatedAt'), + AllowedFilter::scope('CreatedAtBefore'), + AllowedFilter::scope('CreatedAtAfter'), + AllowedFilter::scope('CreatedAtBetween'), + AllowedFilter::scope('CreatedAtCurrentDay'), + AllowedFilter::scope('CreatedAtCurrentWeek'), + AllowedFilter::scope('CreatedAtCurrentMonth'), + AllowedFilter::scope('CreatedAtLastDays'), + AllowedFilter::scope('CreatedAtNextDays'), + AllowedFilter::scope('UpdatedAt'), + AllowedFilter::scope('UpdatedAtBefore'), + AllowedFilter::scope('UpdatedAtAfter'), + AllowedFilter::scope('UpdatedAtBetween'), + AllowedFilter::scope('UpdatedAtCurrentDay'), + AllowedFilter::scope('UpdatedAtCurrentWeek'), + AllowedFilter::scope('UpdatedAtCurrentMonth'), + AllowedFilter::scope('UpdatedAtLastDays'), + AllowedFilter::scope('UpdatedAtNextDays'), + AllowedFilter::scope('WithTrashed'), + AllowedFilter::scope('OnlyTrashed'), + + AllowedFilter::scope('Search'), + ]; } + + /** + * The allowed includes relationships. + * registeredBy,roles,actions,activities + */ + public static function ALLOWEDINCLUDES() + { + return ['registeredBy', 'roles', 'actions', 'activities', 'approvedMotives', 'activeMotives']; + } + + /** + * The allowed sorts attributes. + * id,name,email,created_at,updated_at + */ + public static function ALLOWEDSORTS() + { + return ['id', 'name', 'email', 'nickname', 'username', 'created_at', 'updated_at', 'deleted_at', 'is_active', 'approved_status', 'registered_by']; + } + + /** + * The Default sorts attributes. + * -created_at,name,id + */ + public static function DEFAULTSORT() + { + return ['-created_at', 'name', 'id']; + } + + /** + * The default includes relationships. + * registeredBy,roles,actions,activities + */ + public static function DEFAULTINCLUDES() + { + return ['registeredBy', 'roles', 'actions', 'activities', 'approvedMotives', 'activeMotives']; + } } diff --git a/app/Models/UserLogin.php b/app/Models/UserLogin.php new file mode 100644 index 00000000..6858f9d3 --- /dev/null +++ b/app/Models/UserLogin.php @@ -0,0 +1,10 @@ +startOfWeek(); + } + + public static function currentEndOfWeek() + { + return Carbon::now()->endOfWeek(); + } + + public static function currentMonth() + { + return Carbon::now()->month; + } + + public static function currentYear() + { + return Carbon::now()->year; + } + + public static function currentLastDays(int $days) + { + return Carbon::today()->subDays($days); + } + + public static function currentNextDays(int $days) + { + return Carbon::today()->addDays($days); + } + + + /** + * Parses a time string into a Carbon instance. + * + * This method accepts time strings in various formats: + * - "HH" (e.g., "12") + * - "HH:MM" (e.g., "12:30") + * - "HH:MM:SS" (e.g., "12:30:45") + * + * If the provided time string matches one of these formats, it extracts the + * hours, minutes, and seconds. If minutes or seconds are not provided, they + * default to 0. + * + * @param string $time The time string to parse. + * @return \Carbon\Carbon|null Returns a Carbon instance representing the + * parsed time, or null if the format is invalid. + */ + public static function parseTime($time) + { + // Verifica se o formato é HH:MM:SS, HH:MM ou HH + if (preg_match('/^(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/', $time, $matches)) { + $hours = intval($matches[1]); + $minutes = isset($matches[2]) ? intval($matches[2]) : 0; // Default para 0 se não houver minutos + $seconds = isset($matches[3]) ? intval($matches[3]) : 0; // Default para 0 se não houver segundos + + // Validando os intervalos de horas, minutos e segundos + if ($hours < 0 || $hours > 23 || $minutes < 0 || $minutes > 59 || $seconds < 0 || $seconds > 59) { + return null; // Retorna null se algum valor estiver fora dos limites + } + + // Retorna um objeto Carbon se o tempo for válido + return Carbon::createFromTime($hours, $minutes, $seconds); + } + + // Retorna null se o formato for inválido + return null; + } + + /** + * Parses a date string into a Carbon instance using various formats. + * + * This method attempts to interpret a given date string using a list of + * predefined formats. It supports a wide range of date and time formats, + * including: + * - Standard formats: "Y-m-d H:i:s", "d/m/Y", "m-d-Y", etc. + * - ISO 8601 formats: "Y-m-d\TH:i:s", "Y-m-d H:i:sP", etc. + * - RFC 2822 formats: "D, d M Y H:i:s O", "D, d M Y H:i:s T", etc. + * - Unix timestamp (e.g., "U"). + * + * If the input date string matches one of the formats, it will return a + * Carbon instance representing the parsed date and time. If none of the + * formats match the input string, it returns null. + * + * @param string $date The date string to parse. + * @return \Carbon\Carbon|null Returns a Carbon instance representing the + * parsed date, or null if none of the formats match the input. + */ + + public static function parseDate(string $date) + { + // List of formats to try + $formats = [ + 'Y-m-d H:i:s', + 'Y-m-d H:i', + 'Y-m-d H', + 'Y-m-d', + 'Y/m/d H:i:s', + 'Y/m/d H:i', + 'Y/m/d', + 'd/m/Y H:i:s', + 'd/m/Y H:i', + 'd/m/Y', + 'd.m.Y H:i:s', + 'd.m.Y H:i', + 'd.m.Y', + + 'm-d-Y H:i:s', + 'm-d-Y H:i', + 'm-d-Y', + 'U', // Timestamp Unix + 'D, d M Y H:i:s O', // RFC 2822 + 'D, d M Y H:i:s T', // RFC 2822 + 'Y-m-d\TH:i:sP', // ISO 8601 + 'Y-m-d\TH:i:s', // ISO 8601 + 'Y-m-d\TH:i', // ISO 8601 + 'Y-m-d H:i:sP', // com zona horária + 'Y-m-d H:i:sO', // com zona horária + ]; + + // Try to parse the date using the given formats + foreach ($formats as $format) { + try { + // Attempt to parse the date + $parsedDate = Carbon::createFromFormat($format, $date); + + // Check if the parsed date matches the exact input + if ($parsedDate && $parsedDate->format($format) === $date) { + return $parsedDate; + } + } catch (\Exception $e) { + // Continue trying other formats + continue; + } + } + + // If no format matches, return null + return null; + } + + /** + * Calculates the difference between two dates in various time units. + * + * This method takes two date inputs, parses them, and computes the + * difference in multiple units, including hours, days, weeks, + * fortnights, months, bimesters, quadrimesters, semesters, and years. + * + * The dates are parsed using the `parseDate` method. If either of + * the dates is invalid, an exception will be thrown indicating + * the invalid format. + * + * @param mixed $startDate The starting date, which can be a string + * or a Carbon instance. + * @param mixed $endDate The ending date, which can also be a string + * or a Carbon instance. + * + * @return array An associative array containing the differences + * in various time units. The keys include: + * - 'hours': Difference in hours + * - 'days': Difference in days + * - 'weeks': Difference in weeks + * - 'fortnights': Difference in fortnights (1 fortnight = 14 days) + * - 'months': Difference in months + * - 'bimesters': Difference in bimesters (1 bimester = 2 months) + * - 'quadrimesters': Difference in quadrimesters (1 quadrimester = 4 months) + * - 'semesters': Difference in semesters (1 semester = 6 months) + * - 'years': Difference in years + * + * @throws \Exception If either date is invalid, an exception will be thrown + * with the message 'Invalid date format'. + * + * Example usage: + * $startDate = '2023-01-01'; + * $endDate = '2024-01-01'; + * $difference = DateService::calculateDateDifference($startDate, $endDate); + * + * Expected response: + * [ + * 'hours' => 8760, + * 'days' => 365, + * 'weeks' => 52, + * 'fortnights' => 26, + * 'months' => 12, + * 'bimesters' => 6, + * 'quadrimesters' => 3, + * 'semesters' => 2, + * 'years' => 1, + * ] + */ + public static function calculateDateDifference($startDate, $endDate) + { + // Parse the dates using the parseDate method + $start = self::parseDate($startDate); + $end = self::parseDate($endDate); + + if (!$start || !$end) { + throw new \Exception('Invalid date format'); + } + + // Calculate differences in various units + return [ + 'hours' => $start->diffInHours($end), + 'days' => $start->diffInDays($end), + 'weeks' => $start->diffInWeeks($end), + 'fortnights' => floor($start->diffInDays($end) / 14), // 1 fortnight = 14 days + 'months' => $start->diffInMonths($end), + 'bimesters' => floor($start->diffInMonths($end) / 2), // 1 bimester = 2 months + 'quadrimesters' => floor($start->diffInMonths($end) / 4), // 1 quadrimester = 4 months + 'semesters' => floor($start->diffInMonths($end) / 6), // 1 semester = 6 months + 'years' => $start->diffInYears($end), + ]; + } + + /** + * Calculates a future date based on a start date and a time input. + * + * This method takes a start date and a time input string, which specifies + * the amount of time to add (in various units) to the start date. The function + * parses the start date and time input, and then adds the appropriate amount of + * time based on the specified unit. + * + * The time input can be a string such as "5 days", "2 months", or "3 years". + * If the start date or time input is invalid, an exception will be thrown. + * + * @param mixed $startDate The starting date, which can be a string + * or a Carbon instance. + * @param string $timeInput A string representing the amount of time to + * add to the start date. It should be in the format + * of " ", where can be + * "hours", "days", "weeks", "fortnights", + * "months", "bimesters", "quadrimesters", + * "semesters", or "years". + * + * @return Carbon A Carbon instance representing the calculated future date + * after adding the specified time to the start date. + * + * @throws \Exception If the start date format is invalid, or if the time input + * format is invalid, or if the time unit is unrecognized, + * an exception will be thrown with an appropriate message. + * + * Example usage: + * $startDate = '2023-01-01'; + * $timeInput = '2 months'; + * $futureDate = DateService::calculateFutureDate($startDate, $timeInput); + * + * Expected response (if $startDate is '2023-01-01' and $timeInput is '2 months'): + * '2023-03-01 00:00:00' (or similar depending on time components of the original date) + */ + public static function calculateFutureDate($startDate, int $timeInput) + { + // Parse the start date + $start = self::parseDate($startDate); + + if (!$start) { + throw new \Exception('Invalid start date format'); + } + + // Extract the value and unit from the input string + if (preg_match('/(\d+)\s*(\w+)/', $timeInput, $matches)) { + $value = intval($matches[1]); // The number + $unit = strtolower($matches[2]); // The unit (e.g. "days", "months") + } else { + throw new \Exception('Invalid time input format'); + } + + // Determine the unit and add the appropriate amount of time + switch ($unit) { + case 'hours': + case 'hour': + return $start->addHours($value); + case 'days': + case 'day': + return $start->addDays($value); + case 'weeks': + case 'week': + return $start->addWeeks($value); + case 'fortnights': // quinzenas + case 'fortnight': + return $start->addDays($value * 14); + case 'months': + case 'month': + return $start->addMonths($value); + case 'bimesters': // bimestres + case 'bimester': + return $start->addMonths($value * 2); + case 'quadrimesters': // quadrimestres + case 'quadrimester': + return $start->addMonths($value * 4); + case 'semesters': + case 'semester': + return $start->addMonths($value * 6); + case 'years': + case 'year': + return $start->addYears($value); + default: + throw new \Exception('Invalid time unit'); + } + } + + /** + * Calculates a new date based on a start date and a time input. + * + * This method takes a start date, a time input string, and a boolean + * flag indicating whether to calculate a future or past date. The function + * parses the start date and time input, then either adds or subtracts the + * specified amount of time from the start date based on the value of + * the `$isFuture` parameter. + * + * The time input should be a string formatted as " ", where + * can be "hours", "days", "weeks", "fortnights", "months", + * "bimesters", "quadrimesters", "semesters", or "years". + * If the start date or time input is invalid, an exception will be thrown. + * + * @param mixed $startDate The starting date, which can be a string + * or a Carbon instance. + * @param string $timeInput A string representing the amount of time to + * add or subtract from the start date. + * The format should be " ". + * @param bool $isFuture A boolean indicating whether to calculate a + * future date (true) or a past date (false). + * + * @return Carbon A Carbon instance representing the calculated date + * after applying the specified time adjustment to the start date. + * + * @throws \Exception If the start date format is invalid, if the time input + * format is invalid, if the time unit is unrecognized, + * or if the method fails to process, an exception + * will be thrown with an appropriate message. + * + * Example usage: + * $startDate = '2023-01-01'; + * $timeInput = '2 months'; + * $futureDate = DateService::calculateDate($startDate, $timeInput, true); // Future date + * $pastDate = DateService::calculateDate($startDate, $timeInput, false); // Past date + * + * Expected response (if $startDate is '2023-01-01' and $timeInput is '2 months'): + * For future date: '2023-03-01 00:00:00' (or similar depending on time components) + * For past date: '2022-11-30 00:00:00' (or similar depending on time components) + */ + public static function calculateDate($startDate, $timeInput, $isFuture = true) + { + // Parse the start date + $start = self::parseDate($startDate); + + if (!$start) { + throw new \Exception('Invalid start date format'); + } + + // Extract the value and unit from the input string + if (preg_match('/(\d+)\s*(\w+)/', $timeInput, $matches)) { + $value = intval($matches[1]); // The number + $unit = strtolower($matches[2]); // The unit (e.g. "days", "months") + } else { + throw new \Exception('Invalid time input format'); + } + + // Choose the correct method to subtract or add time based on $isFuture + $method = $isFuture ? 'add' : 'sub'; + + // Determine the unit and apply the appropriate method + switch ($unit) { + case 'hours': + case 'hour': + return $start->{$method . 'Hours'}($value); + case 'days': + case 'day': + return $start->{$method . 'Days'}($value); + case 'weeks': + case 'week': + return $start->{$method . 'Weeks'}($value); + case 'fortnights': // quinzenas + case 'fortnight': + return $start->{$method . 'Days'}($value * 14); + case 'months': + case 'month': + return $start->{$method . 'Months'}($value); + case 'bimesters': // bimestres + case 'bimester': + return $start->{$method . 'Months'}($value * 2); + case 'quadrimesters': // quadrimestres + case 'quadrimester': + return $start->{$method . 'Months'}($value * 4); + case 'semesters': + case 'semester': + return $start->{$method . 'Months'}($value * 6); + case 'years': + case 'year': + return $start->{$method . 'Years'}($value); + default: + throw new \Exception('Invalid time unit'); + } + } + + + /** + * Generates date ranges based on a specified period. + * + * This function allows you to create date intervals such as weeks, biweeks, months, + * bimonths, trimesters, semesters, and years within a date range defined by a start + * date and an end date. Desired intervals can be specified through an array. If no + * intervals are specified, all available intervals will be generated. + * + * @param Carbon $startDate The start date of the range. + * @param Carbon $endDate The end date of the range. + * @param array $desiredIntervals An optional array of strings representing the desired + * intervals. Accepted values are: + * 'weekly', 'biweekly', 'monthly', 'bimonthly', + * 'quarterly', 'quadrimonthly', 'semiannually', and 'yearly'. + * If not specified, all intervals will be used. + * + * @return array An associative array containing the generated date intervals. Each key + * in the array corresponds to a desired interval and contains an array of + * intervals with 'start' and 'end', representing the beginning and ending + * dates of each interval. + * + * Example usage: + * $startDate = Carbon::parse('2023-01-01'); + * $endDate = Carbon::parse('2023-12-31'); + * $dateRanges = DateService::generateDateRanges($startDate, $endDate, ['weekly', 'monthly']); + * + * Expected response: + * [ + * 'weekly' => [ + * ['start' => '2023-01-02', 'end' => '2023-01-08'], + * ['start' => '2023-01-09', 'end' => '2023-01-15'], + * // ...continues + * ], + * 'monthly' => [ + * ['start' => '2023-01-01', 'end' => '2023-01-31'], + * ['start' => '2023-02-01', 'end' => '2023-02-28'], + * // ...continues + * ] + * ] + */ + public static function generateDateRanges(Carbon $startDate, Carbon $endDate, array $desiredIntervals = []) + { + $intervals = []; + + // Define todos os intervalos possíveis + $allIntervals = [ + 'weekly' => '1 week', + 'biweekly' => '2 weeks', + 'monthly' => '1 month', + 'bimonthly' => '2 months', + 'quarterly' => '3 months', + 'quadrimonthly' => '4 months', + 'semiannually' => '6 months', + 'yearly' => '1 year', + ]; + + // Se não houver intervalos desejados, use todos os intervalos + if (empty($desiredIntervals)) { + $desiredIntervals = array_keys($allIntervals); + } + + // Helper function to generate date ranges based on a period + function getRanges($startDate, $endDate, $period) + { + $ranges = []; + foreach ($period as $date) { + $start = $date->start; + $end = $date->end->greaterThan($endDate) ? $endDate : $date->end; + $ranges[] = ['start' => $start->toDateString(), 'end' => $end->toDateString()]; + } + return $ranges; + } + + // Itera sobre os intervalos desejados e gera as datas + foreach ($desiredIntervals as $interval) { + if (array_key_exists($interval, $allIntervals)) { + switch ($interval) { + case 'weekly': + $weekPeriod = CarbonPeriod::create($startDate->copy()->startOfWeek(), $allIntervals[$interval], $endDate); + $intervals['weekly'] = getRanges( + $startDate, + $endDate, + $weekPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy()->startOfWeek(), + 'end' => $date->copy()->endOfWeek(), + ]; + }) + ); + break; + + case 'biweekly': + $biWeekPeriod = CarbonPeriod::create($startDate->copy(), $allIntervals[$interval], $endDate); + $intervals['biweekly'] = getRanges( + $startDate, + $endDate, + $biWeekPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy(), + 'end' => $date->copy()->addWeeks(2)->subDay(), + ]; + }) + ); + break; + + case 'monthly': + $monthPeriod = CarbonPeriod::create($startDate->copy()->startOfMonth(), $allIntervals[$interval], $endDate); + $intervals['monthly'] = getRanges( + $startDate, + $endDate, + $monthPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy()->startOfMonth(), + 'end' => $date->copy()->endOfMonth(), + ]; + }) + ); + break; + + case 'bimonthly': + $biMonthPeriod = CarbonPeriod::create($startDate->copy(), $allIntervals[$interval], $endDate); + $intervals['bimonthly'] = getRanges( + $startDate, + $endDate, + $biMonthPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy(), + 'end' => $date->copy()->addMonths(2)->subDay(), + ]; + }) + ); + break; + + case 'quarterly': + $quarterPeriod = CarbonPeriod::create($startDate->copy(), $allIntervals[$interval], $endDate); + $intervals['quarterly'] = getRanges( + $startDate, + $endDate, + $quarterPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy(), + 'end' => $date->copy()->addMonths(3)->subDay(), + ]; + }) + ); + break; + + case 'quadrimonthly': + $quadMonthPeriod = CarbonPeriod::create($startDate->copy(), $allIntervals[$interval], $endDate); + $intervals['quadrimonthly'] = getRanges( + $startDate, + $endDate, + $quadMonthPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy(), + 'end' => $date->copy()->addMonths(4)->subDay(), + ]; + }) + ); + break; + + case 'semiannually': + $semiAnnualPeriod = CarbonPeriod::create($startDate->copy(), $allIntervals[$interval], $endDate); + $intervals['semiannually'] = getRanges( + $startDate, + $endDate, + $semiAnnualPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy(), + 'end' => $date->copy()->addMonths(6)->subDay(), + ]; + }) + ); + break; + + case 'yearly': + $yearPeriod = CarbonPeriod::create($startDate->copy()->startOfYear(), $allIntervals[$interval], $endDate); + $intervals['yearly'] = getRanges( + $startDate, + $endDate, + $yearPeriod->map(function ($date) { + return (object)[ + 'start' => $date->copy()->startOfYear(), + 'end' => $date->copy()->endOfYear(), + ]; + }) + ); + break; + } + } + } + + return $intervals; + } + + public function getZodiacSign($birthdate) + { + $date = self::parseDate($birthdate); + + if (!$date) { + throw new \InvalidArgumentException("Formato de data inválido. Use o formato Y-m-d."); + } + + $month = $date->format('m'); + $day = $date->format('d'); + + if (($month == 1 && $day >= 20) || ($month == 2 && $day <= 18)) { + return 'Aquário'; + } elseif (($month == 2 && $day >= 19) || ($month == 3 && $day <= 20)) { + return 'Peixes'; + } elseif (($month == 3 && $day >= 21) || ($month == 4 && $day <= 19)) { + return 'Áries'; + } elseif (($month == 4 && $day >= 20) || ($month == 5 && $day <= 20)) { + return 'Touro'; + } elseif (($month == 5 && $day >= 21) || ($month == 6 && $day <= 20)) { + return 'Gêmeos'; + } elseif (($month == 6 && $day >= 21) || ($month == 7 && $day <= 22)) { + return 'Câncer'; + } elseif (($month == 7 && $day >= 23) || ($month == 8 && $day <= 22)) { + return 'Leão'; + } elseif (($month == 8 && $day >= 23) || ($month == 9 && $day <= 22)) { + return 'Virgem'; + } elseif (($month == 9 && $day >= 23) || ($month == 10 && $day <= 22)) { + return 'Libra'; + } elseif (($month == 10 && $day >= 23) || ($month == 11 && $day <= 21)) { + return 'Escorpião'; + } elseif (($month == 11 && $day >= 22) || ($month == 12 && $day <= 21)) { + return 'Sagitário'; + } elseif (($month == 12 && $day >= 22) || ($month == 1 && $day <= 19)) { + return 'Capricórnio'; + } else { + throw new \InvalidArgumentException("Data de nascimento inválida."); + } + } +} diff --git a/app/Services/ForSelectService.php b/app/Services/ForSelectService.php new file mode 100644 index 00000000..ba56b868 --- /dev/null +++ b/app/Services/ForSelectService.php @@ -0,0 +1,42 @@ + + */ + public static function fromModels(Collection $models, string $idField = 'id', string $nameField = 'name'): array + { + return $models->map(function (Model $model) use ($idField, $nameField) { + return [ + 'id' => $model->{$idField}, + 'name' => $model->{$nameField} + ]; + })->all(); + } + + public static function fromQuery($query, string $idField = 'id', string $nameField = 'name'): array + { + return self::fromModels($query->get(), $idField, $nameField); + } + + public static function fromArray(array $items, string $idKey = 'id', string $nameKey = 'name'): array + { + return array_map(function ($item) use ($idKey, $nameKey) { + return [ + 'id' => $item[$idKey], + 'name' => $item[$nameKey] + ]; + }, $items); + } +} diff --git a/app/Services/GeneratorService.php b/app/Services/GeneratorService.php new file mode 100644 index 00000000..5b3f480f --- /dev/null +++ b/app/Services/GeneratorService.php @@ -0,0 +1,27 @@ +model = $model; + } + + public function export(string $format, string $modelName) + { + return match ($format) { + 'typescript' => $this->exportTypeScript($modelName), + 'pdf' => $this->exportPdf($modelName), + 'json' => $this->exportRawJson($modelName), + default => $this->exportRawJson($modelName), + // 'prisma' => $this->exportPrisma($modelName), + // 'eloquent' => $this->exportEloquent($modelName), + // 'openapi' => $this->exportOpenAPI($modelName), + // default => $this->exportRawJson($modelName), + }; + } + + private function exportTypeScript(string $modelName) + { + $tsCode = "interface {$modelName} {\n"; + + foreach ($this->model['attributes'] as $attr) { + $tsType = $this->mapToTypeScriptType($attr['type']); + $optional = ($attr['nullable'] ?? false) ? '?' : ''; + $tsCode .= " {$attr['name']}{$optional}: {$tsType};\n"; + } + + $tsCode .= "}\n"; + + return response($tsCode, 200, [ + 'Content-Type' => 'text/typescript', + 'Content-Disposition' => "attachment; filename=\"{$modelName}.ts\"" + ]); + } + + private function mapToTypeScriptType(string $type): string + { + return match ($type) { + 'integer', 'unsignedBigInteger', 'decimal', 'float' => 'number', + 'boolean' => 'boolean', + 'date', 'datetime', 'timestamp' => 'Date | string', + default => 'string', + }; + } + + private function exportPdf(string $modelName) + { + $html = $this->generatePdfHtml($modelName); + + $pdf = Pdf::loadHTML($html) + ->setPaper('a4', 'portrait') + ->setOption('isRemoteEnabled', true); + + return $pdf->download("{$modelName}_model.pdf"); + } + + private function generatePdfHtml(string $modelName): string + { + $model = $this->model; + $features = $this->getEnabledFeatures(); + $createdAt = $model['created_at'] ?? now()->toDateTimeString(); + $updatedAt = $model['updated_at'] ?? now()->toDateTimeString(); + + $html = << + + + + {$modelName} Model Documentation + + + +
+

{$modelName} Model Documentation

+
+

Version: {$model['version']}

+
+ Features:
+HTML; + + // Adiciona features ativadas + foreach ($features as $feature) { + $html .= "{$feature}"; + } + + $html .= << +
+
+ +

Attributes

+ + + + + + + + + + + +HTML; + + // Adiciona atributos + foreach ($model['attributes'] as $attr) { + $validation = $this->formatValidation($attr); + $options = $this->formatOptions($attr); + + $html .= << + + + + + +HTML; + } + + $html .= << +
NameTypeValidationOptionsDescription
{$attr['name']}{$attr['type']}{$validation}{$options} +HTML; + $html .= isset($attr['description']) ? $attr['description'] : ''; + $html .= << +
+HTML; + + // Adiciona relacionamentos se existirem + if (!empty($model['relations'])) { + $html .= <<Relationships + + + + + + + + + + +HTML; + + foreach ($model['relations'] as $rel) { + $description = isset($rel['description']) ? $rel['description'] : ''; + $html .= << + + + + + +HTML; + } + + $html .= << +
NameTypeRelated ModelDescription
{$rel['name']}{$this->formatRelationType($rel['type'])}{$rel['related']}{$description}
+HTML; + } + + // Adiciona metadados + $html .= << +

Created: {$createdAt}

+

Last Updated: {$updatedAt}

+
+ + +HTML; + + return $html; + } + + private function getEnabledFeatures(): array + { + $features = []; + $featureMap = [ + 'softDeletes' => 'Soft Deletes', + 'timestamps' => 'Timestamps', + 'useIsActive' => 'Is Active', + 'useApprovedStatus' => 'Approved Status', + 'useScribe' => 'Scribe Docs', + 'authorize' => 'Authorization', + 'logsActivity' => 'Activity Logs', + 'clearsResponseCache' => 'Clears Cache' + ]; + + foreach ($featureMap as $key => $label) { + if (!empty($this->model[$key]) && $this->model[$key]) { + $features[] = $label; + } + } + + return $features; + } + + private function formatValidation(array $attr): string + { + $validations = []; + if ($attr['required'] ?? false) $validations[] = 'Required'; + if ($attr['nullable'] ?? false) $validations[] = 'Nullable'; + if ($attr['unique'] ?? false) $validations[] = 'Unique'; + if ($attr['validate'] ?? false) $validations[] = 'Validated'; + + return implode(', ', $validations) ?: '-'; + } + + private function formatOptions(array $attr): string + { + $options = []; + if ($attr['sortAble'] ?? false) $options[] = 'Sortable'; + if ($attr['filterAble'] ?? false) $options[] = 'Filterable'; + if ($attr['searchAble'] ?? false) $options[] = 'Searchable'; + if ($attr['translated'] ?? false) $options[] = 'Translated'; + + return implode(', ', $options) ?: '-'; + } + + private function formatRelationType(string $type): string + { + return match ($type) { + 'belongsTo' => 'Belongs To', + 'hasOne' => 'Has One', + 'hasMany' => 'Has Many', + 'belongsToMany' => 'Belongs To Many', + default => $type + }; + } + + private function exportRawJson(string $modelName) + { + return response()->json($this->model, 200, [ + 'Content-Disposition' => "attachment; filename=\"{$modelName}.json\"" + ]); + } + // ... outros métodos de exportação (prisma, eloquent, openapi) +} diff --git a/app/Services/QueryService.php b/app/Services/QueryService.php new file mode 100644 index 00000000..6be399cf --- /dev/null +++ b/app/Services/QueryService.php @@ -0,0 +1,133 @@ +first(); + if ($object) { + return true; + } else { + return false; + } + } + + /** + * query + * + * @param mixed $model + * @param mixed $allowedFilters + * @param mixed $allowedIncludes + * @param mixed $allowedSorts + * @param array|string|\Spatie\QueryBuilder\AllowedSort $defaultSorts + * @return Spatie\QueryBuilder\QueryBuilder + */ + public static function query($model, mixed $allowedFilters = null, mixed $allowedIncludes = null, mixed $allowedSorts = null, $defaultSorts = null, $defaultIncludes = []): \Spatie\QueryBuilder\QueryBuilder + { + $query = + QueryBuilder::for($model); + + if ($allowedFilters) { + $query->allowedFilters($allowedFilters); + } + if ($allowedIncludes) { + $query->allowedIncludes($allowedIncludes); + } + if ($allowedSorts) { + $query->allowedSorts($allowedSorts); + } + if ($defaultSorts) { + $query->defaultSorts($defaultSorts); + } + if ($defaultIncludes) { + $query->with($defaultIncludes); + } + + return $query; + } + + public static function getOrFailById($model, string $value, array $allowedIncludes = [], $defaultIncludes = []) + { + return self::findOrFail($model, 'id', $value, $allowedIncludes, $defaultIncludes); + } + + public static function getById($model, string $value, array $allowedIncludes = [], $defaultIncludes = []) + { + return self::find($model, 'id', $value, $allowedIncludes, $defaultIncludes); + } + + + public static function find($model, string $attribute, string $value, array $allowedIncludes = [], array $defaultIncludes = []) + { + $object = QueryBuilder::for($model::where($attribute, $value)); + if ($allowedIncludes) { + $object->allowedIncludes($allowedIncludes); + } + if ($defaultIncludes) { + $object->with($defaultIncludes); + } + return $object->first(); + } + + public static function findOrFail($model, string $attribute, string $value, array $allowedIncludes = [], array $defaultIncludes = []) + { + $object = QueryBuilder::for($model::where($attribute, $value)); + if ($allowedIncludes) { + $object->allowedIncludes($allowedIncludes); + } + if ($defaultIncludes) { + $object->with($defaultIncludes); + } + + return $object->firstOrFail(); + } + + //TRASHED + public static function getOrFailTrashedById($model, string $value, array $allowedIncludes = [], array $defaultIncludes = []) + { + return self::findOrFailTrashed($model, 'id', $value, $allowedIncludes, $defaultIncludes); + } + + public static function getTrashedById($model, string $value, array $allowedIncludes = [], array $defaultIncludes = []) + { + return self::findTrashed($model, 'id', $value, $allowedIncludes, $defaultIncludes); + } + + public static function findTrashed($model, string $attribute, string $value, array $allowedIncludes = [], array $defaultIncludes = []) + { + $object = QueryBuilder::for($model::where($attribute, $value)->onlyTrashed()); + if ($allowedIncludes) { + $object->allowedIncludes($allowedIncludes); + } + if ($defaultIncludes) { + $object->with($defaultIncludes); + } + + return $object->first(); + } + + public static function findOrFailTrashed($model, string $attribute, string $value, array $allowedIncludes = [], array $defaultIncludes = []) + { + $object = QueryBuilder::for($model::where($attribute, $value)->onlyTrashed()); + if ($allowedIncludes) { + $object->allowedIncludes($allowedIncludes); + } + if ($defaultIncludes) { + $object->with($defaultIncludes); + } + + return $object->firstOrFail(); + } +} diff --git a/app/Services/StatusService.php b/app/Services/StatusService.php new file mode 100644 index 00000000..069ad315 --- /dev/null +++ b/app/Services/StatusService.php @@ -0,0 +1,206 @@ +update([ + 'is_active' => 1, + ]); + $model->activeMotives()->create([ + 'is_active' => 1, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + public static function deactive($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + + $model->update([ + 'is_active' => 0, + ]); + $model->activeMotives()->create([ + 'is_active' => 0, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + + public static function toggleApprovedStatus($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + $model->update([ + 'approved_status' => $model::APPROVED_STATUS_APPROVED, + 'is_active' => true, + + ]); + $model->approvedMotives()->create([ + 'approved_status' => $model::APPROVED_STATUS_APPROVED, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + + public static function approve($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + $model->update([ + 'approved_status' => $model::APPROVED_STATUS_APPROVED, + 'is_active' => true, + + ]); + $model->approvedMotives()->create([ + 'approved_status' => $model::APPROVED_STATUS_APPROVED, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + public static function unapprove($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + $model->update([ + 'approved_status' => $model::APPROVED_STATUS_UNAPPROVED, + + ]); + $model->approvedMotives()->create([ + 'approved_status' => $model::APPROVED_STATUS_UNAPPROVED, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + public static function analisys($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + $model->update([ + 'approved_status' => $model::APPROVED_STATUS_ANALISYS, + + ]); + $model->approvedMotives()->create([ + 'approved_status' => $model::APPROVED_STATUS_ANALISYS, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + public static function block($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + $model->update([ + 'approved_status' => $model::APPROVED_STATUS_BLOCKED, + + ]); + $model->approvedMotives()->create([ + 'approved_status' => $model::APPROVED_STATUS_BLOCKED, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } + + public static function cancel($model, string $motive, int $createdBy, bool $sendEmail = false) + { + $motives = []; + $translateds = TranslatorGoogle::translate($motive); + $motives = $translateds['translations']; + + try { + $model->update([ + 'approved_status' => $model::APPROVED_STATUS_CANCELED, + + ]); + $model->approvedMotives()->create([ + 'approved_status' => $model::APPROVED_STATUS_CANCELED, + 'causer_type' => Auth::user()::class, // Tipo do usuário que ativou + 'causer_id' => Auth::user()->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + } catch (\Throwable $th) { + throw $th; + } + return true; + } +} diff --git a/app/Services/TranslatorGoogle.php b/app/Services/TranslatorGoogle.php new file mode 100644 index 00000000..b9a78994 --- /dev/null +++ b/app/Services/TranslatorGoogle.php @@ -0,0 +1,226 @@ +setTarget($language); + // $translations[$language] = $tr->preserveParameters('/<[^>]+>/') + // ->translate($text); + $translations[$language] = $tr->translate($text); + usleep(500000); + } + if ($detectSource) { + $sourceLanguage = $tr->getLastDetectedSource(); + } else { + $sourceLanguage = null; + } + if ($sourceLanguage == 'pt') { + $sourceLanguage = 'pt_BR'; + } + $result = [ + 'original_text' => $text, + 'translations' => $translations, + 'source_language' => $sourceLanguage, + ]; + + return $result; + } + + + public static function translate($text, $detectSource = true) + { + $tr = new GoogleTranslate(); + $locales = config('app.supported_locales', ['pt_BR']); + $translations = []; + $placeholders = []; + + // Passo 1: Substituir tags HTML por placeholders codificados em Base64 + $parts = preg_split('/(<[^>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + try { + foreach ($locales as $language) { + $tr->setTarget($language); + $translatedHtml = ''; + foreach ($parts as $part) { + if (preg_match('/^<[^>]+>$/', $part)) { + // Preservar tags HTML intactas + $translatedHtml .= $part; + } else { + // Passo 2: Capturar espaços antes/depois do texto + preg_match('/^(\s*)(.*?)(\s*)$/u', $part, $matches); + $leadingSpace = $matches[1]; + $content = $matches[2]; + $trailingSpace = $matches[3]; + + // Traduzir apenas o conteúdo (sem espaços) + $translatedContent = $tr->translate($content); + + // Reconstruir com espaços originais + $translatedHtml .= $leadingSpace . $translatedContent . $trailingSpace; + } + } + + $translations[$language] = $translatedHtml; + usleep(500000); // Pausa de 1 segundo + + } + } catch (\Exception $e) { + Log::error("Erro ao traduzir: " . $e->getMessage()); + return [ + 'error' => true, + 'message' => "Erro ao traduzir: " . $e->getMessage(), + ]; + } + + if ($detectSource) { + $sourceLanguage = $tr->getLastDetectedSource(); + } else { + $sourceLanguage = null; + } + if ($sourceLanguage == 'pt') { + $sourceLanguage = 'pt_BR'; + } + $result = [ + 'original_text' => $text, + 'translations' => $translations, + 'source_language' => $sourceLanguage, + ]; + + return $result; + if ($sourceLanguage === 'pt') { + $sourceLanguage = 'pt_BR'; + } + + return [ + 'original_text' => str_replace(array_keys($placeholders), array_values($placeholders), $text), + 'translations' => $translations, + 'source_language' => $sourceLanguage ?? null, + ]; + } + + public static function translateWithHtml($text, $detectSource = true) + { + $tr = new GoogleTranslate(); + $locales = config('app.supported_locales', ['pt_BR']); + $translations = []; + $placeholders = []; + + // Passo 1: Substituir tags HTML por placeholders codificados em Base64 + $parts = preg_split('/(<[^>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + try { + foreach ($locales as $language) { + $tr->setTarget($language); + $translatedHtml = ''; + foreach ($parts as $part) { + if (preg_match('/^<[^>]+>$/', $part)) { + // Preservar tags HTML intactas + $translatedHtml .= $part; + } else { + // Passo 2: Capturar espaços antes/depois do texto + preg_match('/^(\s*)(.*?)(\s*)$/u', $part, $matches); + $leadingSpace = $matches[1]; + $content = $matches[2]; + $trailingSpace = $matches[3]; + + // Traduzir apenas o conteúdo (sem espaços) + $translatedContent = $tr->translate($content); + + // Reconstruir com espaços originais + $translatedHtml .= $leadingSpace . $translatedContent . $trailingSpace; + } + } + + $translations[$language] = $translatedHtml; + usleep(500000); // Pausa de 1 segundo + } + } catch (\Exception $e) { + Log::error("Erro ao traduzir: " . $e->getMessage()); + return [ + 'error' => true, + 'message' => "Erro ao traduzir: " . $e->getMessage(), + ]; + } + + if ($detectSource) { + $sourceLanguage = $tr->getLastDetectedSource(); + } else { + $sourceLanguage = null; + } + if ($sourceLanguage == 'pt') { + $sourceLanguage = 'pt_BR'; + } + $result = [ + 'original_text' => $text, + 'translations' => $translations, + 'source_language' => $sourceLanguage, + ]; + + return $result; + if ($sourceLanguage === 'pt') { + $sourceLanguage = 'pt_BR'; + } + + return [ + 'original_text' => str_replace(array_keys($placeholders), array_values($placeholders), $text), + 'translations' => $translations, + 'source_language' => $sourceLanguage ?? null, + ]; + } + + /** + * Traduzir a string para o idioma escolhido, opcionalmente, detectar a língua de origem. + * + * @param string $text + * @param string $target [pt_BR] + * @param bool $detectSource + * @return array + */ + public static function translateToTarget($text, $target = null, $detectSource = true) + { + if (!$target) { + $target = 'pt_BR'; + } + $tr = new GoogleTranslate(); + $sourceLanguage = null; + $translation = ''; + $tr->setTarget($target); + $translation = $tr->translate($text); + if ($detectSource) { + $sourceLanguage = $tr->getLastDetectedSource(); + } else { + $sourceLanguage = null; + } + if ($sourceLanguage == 'pt') { + $sourceLanguage = 'pt_BR'; + } + $result = [ + 'original_text' => $text, + 'translation' => $translation, + 'source_language' => $sourceLanguage, + 'target_language' => $target, + ]; + + return $result; + } +} diff --git a/app/Services/UploadService.php b/app/Services/UploadService.php new file mode 100644 index 00000000..54522900 --- /dev/null +++ b/app/Services/UploadService.php @@ -0,0 +1,109 @@ +getClientOriginalExtension(); + + // Gera um nome único para o arquivo + $fileName = self::generateFileName($extension); + + if (!$originalName) { + $originalName = $fileData->getClientOriginalName(); + } + // Verifica se o arquivo é base64 e converte para arquivo se necessário + if (self::isBase64($fileData)) { + $isSave = self::base64ToFile($fileData, $storagePath, $fileName); + return [ + 'original_name' => $originalName, + 'saved_name' => $fileName, + 'size' => $fileData->getSize(), + 'extension' => $extension, + ]; + } + if (self::validateType($extension) === 'file') { + $contents = file_get_contents($fileData->getRealPath()); + $isSave = Storage::put($storagePath . DIRECTORY_SEPARATOR . $fileName, $contents, $storageDisk); + } else { + if (strtolower($extension) === 'svg') { + // $sanitizer = new Sanitizer(); + $svgContent = file_get_contents($fileData->getPathname()); + + // Limpa o SVG para remover código perigoso + $cleanSvg = $svgContent; //$sanitizer->sanitize($svgContent); + + // Salva o arquivo limpo + $isSave = Storage::put($storagePath . DIRECTORY_SEPARATOR . $fileName, $cleanSvg, $storageDisk); + } else { + $isSave = Storage::putFileAs($storagePath, $fileData, $fileName, $storageDisk); + } + } + return [ + 'original_name' => $originalName, + 'saved_name' => $fileName, + 'size' => $fileData->getSize(), + 'extension' => $extension, + ]; + } + + protected static function isBase64($fileData): bool + { + return preg_match('/^data:image\/(\w+);base64,/', $fileData) || preg_match('/^data:application\/(\w+);base64,/', $fileData); + } + + protected static function base64ToFile($base64String, $storagePath, $fileName) + { + Log::debug("Estou no base64"); + $replace = substr($base64String, 0, strpos($base64String, ',') + 1); + + // find substring fro replace here eg: data:image/png;base64, + $image = str_replace($replace, '', $base64String); + $image = str_replace(' ', '+', $image); + $decoded = base64_decode($image); + Storage::put($storagePath . DIRECTORY_SEPARATOR . $fileName, $decoded, 'public'); + return true; + } + + protected static function validateType($extension) + { + $allowedImageTypes = config('image-file.supported_images', ['jpg', 'jpeg', 'png', 'svg', 'ifc', 'dwg', 'dxf']); + $allowedFileTypes = config('image-file.supported_files', ['txt', 'xls', 'pdf', 'doc', 'docx', 'xlsx', 'jpg', 'jpeg', 'png', 'ifc', 'dwg', 'dxf', 'pptx', 'odt', 'ods', 'odp']); + $allowedTypes = array_merge($allowedImageTypes, $allowedFileTypes); + if (in_array(strtolower($extension), $allowedImageTypes)) { + return 'image'; + } + if (in_array(strtolower($extension), $allowedFileTypes)) { + return 'file'; + } + } + + protected static function generateFileName($extension): string + { + $date = Carbon::now()->format('Y-m-d'); + return $date . '_' . Str::uuid() . '.' . $extension; // Gera um nome único para o arquivo + } +} diff --git a/app/Services/UtilityService.php b/app/Services/UtilityService.php new file mode 100644 index 00000000..910cacb1 --- /dev/null +++ b/app/Services/UtilityService.php @@ -0,0 +1,53 @@ +json([ + 'status' => $code, + // 'error' => false, + 'message' => $message, + 'data' => [], + ], $code); + } + + protected function sendResponse($data, string $message = null, int $code = JsonResponse::HTTP_OK) + { + if (!$message) { + $message = __('The action was executed successfully.'); + } + return response()->json([ + 'status' => $code, + // 'error' => false, + 'message' => $message, + 'data' => $data, + ], $code); + } + + protected function sendNoContent($message = null, $code = JsonResponse::HTTP_NO_CONTENT) + { + if (!$message) { + $message = __('Not Found'); + } + return response()->json([ + 'status' => $code, + // 'error' => false, + 'message' => $message, + 'data' => [], + ], $code); + } + + protected function sendNoPermission($message = null, $code = JsonResponse::HTTP_FORBIDDEN) + { + if (!$message) { + $message = __('Sorry! You are not authorized to perform this action.'); + } + return response()->json([ + 'status' => $code, + 'error' => true, + 'message' => $message, + 'data' => [], + ], $code); + } + + protected function sendError($message = null, string $code = JsonResponse::HTTP_NOT_FOUND, $data = []) + { + if (!$message) { + $message = __('There was a problem executing the action.'); + } + return response()->json([ + 'status' => $code, + 'error' => true, + 'message' => $message, + 'data' => $data, + ], $code); + } + + protected function sendErrorUnprocessable($data = [], $message = null, $code = JsonResponse::HTTP_UNPROCESSABLE_ENTITY) + { + if (!$message) { + $message = __('There was a problem submitting the form.'); + } + return response()->json([ + 'status' => $code, + 'error' => true, + 'message' => $message, + 'errors' => $data, + ], $code); + } +} diff --git a/app/Traits/CascadeSoftDeletes.php b/app/Traits/CascadeSoftDeletes.php new file mode 100644 index 00000000..99ca574b --- /dev/null +++ b/app/Traits/CascadeSoftDeletes.php @@ -0,0 +1,214 @@ +validateCascadingSoftDelete(); + $model->backupDeletedRecord(); + $model->runCascadingDeletes(); + }); + + static::restoring(function ($model) { + $model->validateCascadingSoftDelete(); + $model->deleteBackupRecord(); + $model->runCascadingRestores(); + }); + } + + /** + * Validate that the calling model is correctly setup for cascading soft deletes. + * + * @throws \App\Exceptions\API\CascadeSoftDeleteException + */ + protected function validateCascadingSoftDelete() + { + if (!$this->implementsSoftDeletes()) { + throw CascadeSoftDeleteException::softDeleteNotImplemented(get_called_class()); + } + + if ($invalidCascadingRelationships = $this->hasInvalidCascadingRelationships()) { + throw CascadeSoftDeleteException::invalidRelationships($invalidCascadingRelationships); + } + } + + /** + * Run the cascading soft delete for this model. + * + * @return void + */ + protected function runCascadingDeletes() + { + $relations = []; + + foreach ($this->getActiveCascadingDeletes() as $relationship) { + $this->cascadeSoftDeletes($relationship); + } + } + + /** + * Cascade delete the given relationship on the given model. + * + * @param string $relationship + * @return void + */ + protected function cascadeSoftDeletes($relationship) + { + $delete = $this->forceDeleting ? 'forceDelete' : 'delete'; + + foreach ($this->{$relationship}()->get() as $model) { + + + + if (Schema::hasColumn($model->getTable(), 'deleted_by_parent')) { + $model->pivot ? $model->pivot->update(['deleted_by_parent' => true]) : $model->update(['deleted_by_parent' => true]); + } + // if ($delete === 'forceDelete') { + // $model->backupDeletedRecord(); + // } + + $model->pivot ? $model->pivot->{$delete}() : $model->{$delete}(); + } + } + + /** + * Run the cascading restore for this model. + * + * @return void + */ + protected function runCascadingRestores() + { + + foreach ($this->getDeletedCascadingDeletes() as $relationship) { + $this->cascadeRestore($relationship); + } + } + + /** + * Cascade restore the given relationship on the given model. + * + * @param string $relationship + * @return void + */ + protected function cascadeRestore($relationship) + { + foreach ($this->{$relationship}()->withTrashed()->get() as $model) { + if (Schema::hasColumn($model->getTable(), 'deleted_by_parent')) { + if ($model->deleted_by_parent) { + $model->restore(); + + $model->update(['deleted_by_parent' => false]); + } + } + + // if ($model->deleted_by_parent) { + // $model->restore(); + + // $model->update(['deleted_by_parent' => false]); + // } + } + } + + /** + * Determine if the current model implements soft deletes. + * + * @return bool + */ + protected function implementsSoftDeletes() + { + return method_exists($this, 'runSoftDelete'); + } + + /** + * Determine if the current model has any invalid cascading relationships defined. + * + * A relationship is considered invalid when the method does not exist, or the relationship + * method does not return an instance of Illuminate\Database\Eloquent\Relations\Relation. + * + * @return array + */ + protected function hasInvalidCascadingRelationships() + { + return array_filter($this->getCascadingDeletes(), function ($relationship) { + return !method_exists($this, $relationship) || !$this->{$relationship}() instanceof Relation; + }); + } + + /** + * Fetch the defined cascading soft deletes for this model. + * + * @return array + */ + protected function getCascadingDeletes() + { + return isset($this->cascadeDeletes) ? (array) $this->cascadeDeletes : []; + } + + /** + * For the cascading deletes defined on the model, return only those that are not null. + * + * @return array + */ + protected function getActiveCascadingDeletes() + { + return array_filter($this->getCascadingDeletes(), function ($relationship) { + return !is_null($this->{$relationship}); + }); + } + + /** + * For the cascading deletes defined on the model, return only those that are not null. + * + * @return array + */ + protected function getDeletedCascadingDeletes() + { + return array_filter($this->getCascadingDeletes(), function ($relationship) { + return !is_null($this->{$relationship}()->withTrashed()); + }); + } + + protected function backupDeletedRecord() + { + // Verifica se a configuração 'keep_deleted_backup' está definida como true + if (config('app.keep_deleted_backup')) { + $user = Auth::user(); + + DB::table('deleted_records')->insert([ + 'subject_type' => get_class($this), + 'subject_id' => $this->id, + 'subject_data' => json_encode($this->attributesToArray()), + 'deleted_at' => now(), + 'causer_id' => $user ? $user->id : null, + 'causer_type' => $user ? get_class($user) : null, + ]); + } + } + + protected function deleteBackupRecord() + { + DB::table('deleted_records') + ->where('subject_type', get_class($this)) + ->where('subject_id', $this->id) + ->delete(); + } +} diff --git a/app/Traits/ClearsResponseCache.php b/app/Traits/ClearsResponseCache.php new file mode 100644 index 00000000..6db865aa --- /dev/null +++ b/app/Traits/ClearsResponseCache.php @@ -0,0 +1,23 @@ +dateFields) || !is_array($this->dateFields)) { + $this->dateFields = ['created_at', 'updated_at']; + } + } + + protected function applyDateScope(Builder $builder, $field, $method, ...$params) + { + if (in_array($field, $this->dateFields)) { + return $this->{"scope{$method}"}($builder, $field, ...$params); + } + return $builder; + } + + protected function scopeAt(Builder $builder, $field, $date) + { + $parsedDate = DateService::parseDate($date); + return $builder->whereDate($field, $parsedDate->format('Y-m-d') ? $parsedDate->format('Y-m-d') : '1912-01-01'); + } + + protected function scopeAtBefore(Builder $builder, $field, $date) + { + $parsedDate = DateService::parseDate($date); + return $builder->whereDate($field, '<=', $parsedDate ? $parsedDate->format('Y-m-d') : '1912-01-01'); + } + + protected function scopeAtAfter(Builder $builder, $field, $date) + { + $parsedDate = DateService::parseDate($date); + return $builder->whereDate($field, '>=', $parsedDate ? $parsedDate->format('Y-m-d') : '1912-01-01'); + } + + protected function scopeAtBetween(Builder $builder, $field, $startDate, $endDate) + { + $parsedStartDate = DateService::parseDate($startDate); + $parsedEndDate = DateService::parseDate($endDate); + return $builder->whereBetween($field, [ + $parsedStartDate ? $parsedStartDate->startOfDay() : '1912-01-01', + $parsedEndDate ? $parsedEndDate->endOfDay() : '1912-01-01' + ]); + } + + protected function scopeAtCurrentDay(Builder $builder, $field) + { + return $builder->whereDate($field, DateService::today()->format('Y-m-d')); + } + + protected function scopeAtCurrentWeek(Builder $builder, $field) + { + return $builder->whereBetween($field, [ + DateService::currentStartOfWeek()->format('Y-m-d 00:00:00'), + DateService::currentEndOfWeek()->format('Y-m-d 23:59:59') + ]); + } + + protected function scopeAtCurrentMonth(Builder $builder, $field) + { + return $builder->whereMonth($field, DateService::currentMonth()) + ->whereYear($field, DateService::currentYear()); + } + + protected function scopeAtLastDays(Builder $builder, $field, int $days) + { + return $builder->whereBetween($field, [ + DateService::currentLastDays($days)->format('Y-m-d 00:00:00'), + DateService::today()->format('Y-m-d 23:59:59') + ]); + } + + protected function scopeAtNextDays(Builder $builder, $field, int $days) + { + return $builder->whereBetween($field, [ + DateService::today()->format('Y-m-d 00:00:00'), + DateService::currentNextDays($days)->format('Y-m-d 23:59:59') + ]); + } +} diff --git a/app/Traits/LogsScheduledCommands.php b/app/Traits/LogsScheduledCommands.php new file mode 100644 index 00000000..6b0b8f50 --- /dev/null +++ b/app/Traits/LogsScheduledCommands.php @@ -0,0 +1,18 @@ + $this->signature, // Assinatura do comando + 'output' => $output, + 'status' => $status, + 'executed_at' => now(), + ]); + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index 134581ab..37ebaa54 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -9,8 +9,10 @@ return Application::configure(basePath: dirname(__DIR__)) ->withRouting( - web: __DIR__.'/../routes/web.php', - commands: __DIR__.'/../routes/console.php', + web: __DIR__ . '/../routes/web.php', + api: __DIR__ . '/../routes/api.php', + commands: __DIR__ . '/../routes/console.php', + channels: __DIR__ . '/../routes/channels.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { @@ -21,6 +23,13 @@ HandleInertiaRequests::class, AddLinkHeadersForPreloadedAssets::class, ]); + $middleware->alias([ + 'set_locale' => \App\Http\Middleware\SetLocale::class, + + 'role' => \Spatie\Permission\Middleware\RoleMiddleware::class, + 'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class, + 'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class, + ]); }) ->withExceptions(function (Exceptions $exceptions) { // diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore old mode 100644 new mode 100755 diff --git a/components.json b/components.json index 5e3012e5..0bf315c6 100644 --- a/components.json +++ b/components.json @@ -1,20 +1,20 @@ { - "$schema": "https://shadcn-vue.com/schema.json", - "style": "default", - "typescript": true, - "tailwind": { - "config": "tailwind.config.js", - "css": "resources/css/app.css", - "baseColor": "neutral", - "cssVariables": true, - "prefix": "" - }, - "aliases": { - "components": "@/components", - "composables": "@/composables", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib" - }, - "iconLibrary": "lucide" -} + "$schema": "https://shadcn-vue.com/schema.json", + "style": "new-york", + "typescript": true, + "tailwind": { + "config": "", + "css": "resources/css/app.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "composables": "@/composables", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/composer.json b/composer.json index ec56e03c..092d4737 100644 --- a/composer.json +++ b/composer.json @@ -10,13 +10,29 @@ "license": "MIT", "require": { "php": "^8.2", + "barryvdh/laravel-dompdf": "^3.1", + "doctrine/dbal": "^4.2", "inertiajs/inertia-laravel": "^2.0", + "intervention/image": "^3.11", + "knuckleswtf/scribe": "^5.2", + "laravel-lang/common": "^6.7", "laravel/framework": "^12.0", + "laravel/reverb": "^1.0", + "laravel/sanctum": "^4.0", "laravel/tinker": "^2.10.1", + "maatwebsite/excel": "^3.1", + "predis/predis": "^3.0", + "reefki/laravel-device-detector": "^1.0", + "spatie/laravel-activitylog": "^4.10", + "spatie/laravel-json-api-paginate": "^1.16", + "spatie/laravel-permission": "^6.19", + "spatie/laravel-query-builder": "^6.3", + "stichoza/google-translate-php": "^5.3", "tightenco/ziggy": "^2.4" }, "require-dev": { "fakerphp/faker": "^1.23", + "laravel-lang/publisher": "^16.6", "laravel/pail": "^1.2.2", "laravel/pint": "^1.18", "laravel/sail": "^1.41", diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..776ff7bc --- /dev/null +++ b/composer.lock @@ -0,0 +1,13378 @@ +{ + "_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": "07265d9873667b6a4e9fccfa5c30de8e", + "packages": [ + { + "name": "archtechx/enums", + "version": "v1.1.2", + "source": { + "type": "git", + "url": "https://github.com/archtechx/enums.git", + "reference": "81375b71c176f680880a95e7448d84258cfb5c72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/archtechx/enums/zipball/81375b71c176f680880a95e7448d84258cfb5c72", + "reference": "81375b71c176f680880a95e7448d84258cfb5c72", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "larastan/larastan": "^2.4", + "orchestra/testbench": "^8.0 || ^9.0", + "pestphp/pest": "^2.0", + "pestphp/pest-plugin-laravel": "^2.0" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "ArchTech\\Enums\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Samuel Štancl", + "email": "samuel@archte.ch" + } + ], + "description": "Helpers for making PHP enums more lovable.", + "support": { + "issues": "https://github.com/archtechx/enums/issues", + "source": "https://github.com/archtechx/enums/tree/v1.1.2" + }, + "time": "2025-06-06T23:15:09+00:00" + }, + { + "name": "barryvdh/laravel-dompdf", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-dompdf.git", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "shasum": "" + }, + "require": { + "dompdf/dompdf": "^3.0", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1" + }, + "require-dev": { + "larastan/larastan": "^2.7|^3.0", + "orchestra/testbench": "^7|^8|^9|^10", + "phpro/grumphp": "^2.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf", + "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf" + }, + "providers": [ + "Barryvdh\\DomPDF\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\DomPDF\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "A DOMPDF Wrapper for Laravel", + "keywords": [ + "dompdf", + "laravel", + "pdf" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-dompdf/issues", + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-02-13T15:07:54+00:00" + }, + { + "name": "brick/math", + "version": "0.13.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.13.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-03-29T13:50:30+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/dbal": "<4.0.0 || >=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" + }, + { + "name": "clue/redis-protocol", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/clue/redis-protocol.git", + "reference": "6f565332f5531b7722d1e9c445314b91862f6d6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/redis-protocol/zipball/6f565332f5531b7722d1e9c445314b91862f6d6c", + "reference": "6f565332f5531b7722d1e9c445314b91862f6d6c", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\Redis\\Protocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@lueck.tv" + } + ], + "description": "A streaming Redis protocol (RESP) parser and serializer written in pure PHP.", + "homepage": "https://github.com/clue/redis-protocol", + "keywords": [ + "parser", + "protocol", + "redis", + "resp", + "serializer", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/redis-protocol/issues", + "source": "https://github.com/clue/redis-protocol/tree/v0.3.2" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2024-08-07T11:06:28+00:00" + }, + { + "name": "clue/redis-react", + "version": "v2.8.0", + "source": { + "type": "git", + "url": "https://github.com/clue/reactphp-redis.git", + "reference": "84569198dfd5564977d2ae6a32de4beb5a24bdca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/reactphp-redis/zipball/84569198dfd5564977d2ae6a32de4beb5a24bdca", + "reference": "84569198dfd5564977d2ae6a32de4beb5a24bdca", + "shasum": "" + }, + "require": { + "clue/redis-protocol": "^0.3.2", + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.0 || ^1.1", + "react/promise-timer": "^1.11", + "react/socket": "^1.16" + }, + "require-dev": { + "clue/block-react": "^1.5", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\Redis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Async Redis client implementation, built on top of ReactPHP.", + "homepage": "https://github.com/clue/reactphp-redis", + "keywords": [ + "async", + "client", + "database", + "reactphp", + "redis" + ], + "support": { + "issues": "https://github.com/clue/reactphp-redis/issues", + "source": "https://github.com/clue/reactphp-redis/tree/v2.8.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2025-01-03T16:18:33+00:00" + }, + { + "name": "composer/class-map-generator", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/composer/class-map-generator.git", + "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/class-map-generator/zipball/134b705ddb0025d397d8318a75825fe3c9d1da34", + "reference": "134b705ddb0025d397d8318a75825fe3c9d1da34", + "shasum": "" + }, + "require": { + "composer/pcre": "^2.1 || ^3.1", + "php": "^7.2 || ^8.0", + "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", + "phpunit/phpunit": "^8", + "symfony/filesystem": "^5.4 || ^6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\ClassMapGenerator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Utilities to scan PHP code and generate class maps.", + "keywords": [ + "classmap" + ], + "support": { + "issues": "https://github.com/composer/class-map-generator/issues", + "source": "https://github.com/composer/class-map-generator/tree/1.6.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2025-03-24T13:50:44+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, + { + "name": "doctrine/dbal", + "version": "4.2.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/33d2d7fe1269b2301640c44cf2896ea607b30e3e", + "reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^0.5.3|^1", + "php": "^8.1", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "12.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.2", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "10.5.39", + "slevomat/coding-standard": "8.13.1", + "squizlabs/php_codesniffer": "3.10.2", + "symfony/cache": "^6.3.8|^7.0", + "symfony/console": "^5.4|^6.3|^7.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/4.2.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2025-03-07T18:29:05+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "dompdf/dompdf", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "a51bd7a063a65499446919286fb18b518177155a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a", + "reference": "a51bd7a063a65499446919286fb18b518177155a", + "shasum": "" + }, + "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-gd": "*", + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v3.1.0" + }, + "time": "2025-01-15T14:09:04+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" + }, + "time": "2024-12-02T14:37:59+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" + }, + "time": "2024-04-29T13:26:35+00:00" + }, + { + "name": "dragon-code/contracts", + "version": "2.24.0", + "source": { + "type": "git", + "url": "https://github.com/TheDragonCode/contracts.git", + "reference": "c21ea4fc0a399bd803a2805a7f2c989749083896" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/TheDragonCode/contracts/zipball/c21ea4fc0a399bd803a2805a7f2c989749083896", + "reference": "c21ea4fc0a399bd803a2805a7f2c989749083896", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-message": "^1.0.1 || ^2.0", + "symfony/http-kernel": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/polyfill-php80": "^1.23" + }, + "conflict": { + "andrey-helldar/contracts": "*" + }, + "require-dev": { + "illuminate/database": "^10.0 || ^11.0 || ^12.0", + "phpdocumentor/reflection-docblock": "^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "DragonCode\\Contracts\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + } + ], + "description": "A set of contracts for any project", + "keywords": [ + "contracts", + "interfaces" + ], + "support": { + "source": "https://github.com/TheDragonCode/contracts" + }, + "funding": [ + { + "url": "https://boosty.to/dragon-code", + "type": "boosty" + }, + { + "url": "https://yoomoney.ru/to/410012608840929", + "type": "yoomoney" + } + ], + "time": "2025-02-23T23:11:50+00:00" + }, + { + "name": "dragon-code/pretty-array", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/TheDragonCode/pretty-array.git", + "reference": "b94034d92172a5d14a578822d68b2a8f8b5388e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/TheDragonCode/pretty-array/zipball/b94034d92172a5d14a578822d68b2a8f8b5388e0", + "reference": "b94034d92172a5d14a578822d68b2a8f8b5388e0", + "shasum": "" + }, + "require": { + "dragon-code/contracts": "^2.20", + "dragon-code/support": "^6.11.2", + "ext-dom": "*", + "ext-mbstring": "*", + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^10.0 || ^11.0 || ^12.0" + }, + "suggest": { + "symfony/thanks": "Give thanks (in the form of a GitHub) to your fellow PHP package maintainers" + }, + "type": "library", + "autoload": { + "psr-4": { + "DragonCode\\PrettyArray\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + } + ], + "description": "Simple conversion of an array to a pretty view", + "keywords": [ + "andrey helldar", + "array", + "dragon", + "dragon code", + "pretty", + "pretty array" + ], + "support": { + "issues": "https://github.com/TheDragonCode/pretty-array/issues", + "source": "https://github.com/TheDragonCode/pretty-array" + }, + "funding": [ + { + "url": "https://boosty.to/dragon-code", + "type": "boosty" + }, + { + "url": "https://yoomoney.ru/to/410012608840929", + "type": "yoomoney" + } + ], + "time": "2025-02-24T15:35:24+00:00" + }, + { + "name": "dragon-code/support", + "version": "6.16.0", + "source": { + "type": "git", + "url": "https://github.com/TheDragonCode/support.git", + "reference": "ab9b657a307e75f6ba5b2b39e1e45207dc1a065a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/TheDragonCode/support/zipball/ab9b657a307e75f6ba5b2b39e1e45207dc1a065a", + "reference": "ab9b657a307e75f6ba5b2b39e1e45207dc1a065a", + "shasum": "" + }, + "require": { + "dragon-code/contracts": "^2.22.0", + "ext-bcmath": "*", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.1", + "psr/http-message": "^1.0.1 || ^2.0", + "symfony/polyfill-php81": "^1.25", + "voku/portable-ascii": "^1.4.8 || ^2.0.1" + }, + "conflict": { + "andrey-helldar/support": "*" + }, + "require-dev": { + "illuminate/contracts": "^9.0 || ^10.0 || ^11.0 || ^12.0", + "phpunit/phpunit": "^9.6 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.0 || ^7.0" + }, + "suggest": { + "dragon-code/laravel-support": "Various helper files for the Laravel and Lumen frameworks", + "symfony/thanks": "Give thanks (in the form of a GitHub) to your fellow PHP package maintainers" + }, + "type": "library", + "extra": { + "dragon-code": { + "docs-generator": { + "preview": { + "brand": "php", + "vendor": "The Dragon Code" + } + } + } + }, + "autoload": { + "psr-4": { + "DragonCode\\Support\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + } + ], + "description": "Support package is a collection of helpers and tools for any project.", + "keywords": [ + "dragon", + "dragon-code", + "framework", + "helper", + "helpers", + "laravel", + "php", + "support", + "symfony", + "yii", + "yii2" + ], + "support": { + "issues": "https://github.com/TheDragonCode/support/issues", + "source": "https://github.com/TheDragonCode/support" + }, + "funding": [ + { + "url": "https://boosty.to/dragon-code", + "type": "boosty" + }, + { + "url": "https://yoomoney.ru/to/410012608840929", + "type": "yoomoney" + } + ], + "time": "2025-02-24T14:01:52+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" + }, + { + "name": "erusev/parsedown", + "version": "1.7.4", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, + "time": "2019-12-30T22:54:17+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": "ezyang/htmlpurifier", + "version": "v4.18.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b", + "shasum": "" + }, + "require": { + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "cerdic/css-tidy": "^1.7 || ^2.0", + "simpletest/simpletest": "dev-master" + }, + "suggest": { + "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", + "ext-bcmath": "Used for unit conversion and imagecrash protection", + "ext-iconv": "Converts text to and from non-UTF-8 encodings", + "ext-tidy": "Used for pretty-printing HTML" + }, + "type": "library", + "autoload": { + "files": [ + "library/HTMLPurifier.composer.php" + ], + "psr-0": { + "HTMLPurifier": "library/" + }, + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" + }, + "time": "2024-11-01T03:51:45+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "filp/whoops", + "version": "2.18.1", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26", + "reference": "8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.18.1" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2025-06-03T18:56:14+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:30:47+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "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" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-02-03T10:55:03+00:00" + }, + { + "name": "inertiajs/inertia-laravel", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/inertiajs/inertia-laravel.git", + "reference": "248e815cf8d41307cbfb735efaa514c118e2f3b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/248e815cf8d41307cbfb735efaa514c118e2f3b4", + "reference": "248e815cf8d41307cbfb735efaa514c118e2f3b4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": "^10.0|^11.0|^12.0", + "php": "^8.1.0", + "symfony/console": "^6.2|^7.0" + }, + "require-dev": { + "laravel/pint": "^1.16", + "mockery/mockery": "^1.3.3", + "orchestra/testbench": "^8.0|^9.2|^10.0", + "phpunit/phpunit": "^10.4|^11.5", + "roave/security-advisories": "dev-master" + }, + "suggest": { + "ext-pcntl": "Recommended when running the Inertia SSR server via the `inertia:start-ssr` artisan command." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Inertia\\ServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "./helpers.php" + ], + "psr-4": { + "Inertia\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Reinink", + "email": "jonathan@reinink.ca", + "homepage": "https://reinink.ca" + } + ], + "description": "The Laravel adapter for Inertia.js.", + "keywords": [ + "inertia", + "laravel" + ], + "support": { + "issues": "https://github.com/inertiajs/inertia-laravel/issues", + "source": "https://github.com/inertiajs/inertia-laravel/tree/v2.0.2" + }, + "time": "2025-04-10T15:08:36+00:00" + }, + { + "name": "intervention/gif", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/Intervention/gif.git", + "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/gif/zipball/5999eac6a39aa760fb803bc809e8909ee67b451a", + "reference": "5999eac6a39aa760fb803bc809e8909ee67b451a", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Gif\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "Native PHP GIF Encoder/Decoder", + "homepage": "https://github.com/intervention/gif", + "keywords": [ + "animation", + "gd", + "gif", + "image" + ], + "support": { + "issues": "https://github.com/Intervention/gif/issues", + "source": "https://github.com/Intervention/gif/tree/4.2.2" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + }, + { + "url": "https://ko-fi.com/interventionphp", + "type": "ko_fi" + } + ], + "time": "2025-03-29T07:46:21+00:00" + }, + { + "name": "intervention/image", + "version": "3.11.3", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "d0f097b8a3fa8fb758efc9440b513aa3833cda17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/d0f097b8a3fa8fb758efc9440b513aa3833cda17", + "reference": "d0f097b8a3fa8fb758efc9440b513aa3833cda17", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "intervention/gif": "^4.2", + "php": "^8.1" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "slevomat/coding-standard": "~8.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "suggest": { + "ext-exif": "Recommended to be able to read EXIF data properly." + }, + "type": "library", + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@intervention.io", + "homepage": "https://intervention.io/" + } + ], + "description": "PHP image manipulation", + "homepage": "https://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "resize", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/3.11.3" + }, + "funding": [ + { + "url": "https://paypal.me/interventionio", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + }, + { + "url": "https://ko-fi.com/interventionphp", + "type": "ko_fi" + } + ], + "time": "2025-05-22T17:26:23+00:00" + }, + { + "name": "knuckleswtf/scribe", + "version": "5.2.1", + "source": { + "type": "git", + "url": "https://github.com/knuckleswtf/scribe.git", + "reference": "7d1866bfccc96559b753466afdc1f70ed6c6125e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/knuckleswtf/scribe/zipball/7d1866bfccc96559b753466afdc1f70ed6c6125e", + "reference": "7d1866bfccc96559b753466afdc1f70ed6c6125e", + "shasum": "" + }, + "require": { + "erusev/parsedown": "1.7.4", + "ext-fileinfo": "*", + "ext-json": "*", + "ext-pdo": "*", + "fakerphp/faker": "^1.23.1", + "laravel/framework": "^9.0|^10.0|^11.0|^12.0", + "league/flysystem": "^3.0", + "mpociot/reflection-docblock": "^1.0.1", + "nikic/php-parser": "^5.0", + "nunomaduro/collision": "^6.0|^7.0|^8.0", + "php": ">=8.1", + "ramsey/uuid": "^4.2.2", + "shalvah/clara": "^3.1.0", + "shalvah/upgrader": ">=0.6.0", + "spatie/data-transfer-object": "^2.6|^3.0", + "symfony/var-exporter": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "replace": { + "mpociot/laravel-apidoc-generator": "*" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^v0.5.0", + "laravel/legacy-factories": "^1.3.0", + "league/fractal": "^0.20", + "nikic/fast-route": "^1.3", + "orchestra/testbench": "^7.0|^8.0|^v9.10.0|^10.0", + "pestphp/pest": "^1.21|^2.0|^3.0", + "phpstan/phpstan": "^2.1.5", + "phpunit/phpunit": "^9.0|^10.0|^11.0", + "spatie/ray": "^1.41", + "symfony/css-selector": "^6.0|^7.0", + "symfony/dom-crawler": "^6.0|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Knuckles\\Scribe\\ScribeServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Config/helpers.php" + ], + "psr-4": { + "Knuckles\\Camel\\": "camel/", + "Knuckles\\Scribe\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shalvah" + } + ], + "description": "Generate API documentation for humans from your Laravel codebase.✍", + "homepage": "http://github.com/knuckleswtf/scribe", + "keywords": [ + "api", + "documentation", + "laravel" + ], + "support": { + "issues": "https://github.com/knuckleswtf/scribe/issues", + "source": "https://github.com/knuckleswtf/scribe/tree/5.2.1" + }, + "funding": [ + { + "url": "https://patreon.com/shalvah", + "type": "patreon" + } + ], + "time": "2025-05-01T01:14:54+00:00" + }, + { + "name": "laravel-lang/actions", + "version": "1.10.1", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/actions.git", + "reference": "61ccf44b51382bf198a4178446062c2ede1322c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/actions/zipball/61ccf44b51382bf198a4178446062c2ede1322c6", + "reference": "61ccf44b51382bf198a4178446062c2ede1322c6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel-lang/publisher": "^14.0 || ^15.0 || ^16.0", + "php": "^8.1" + }, + "require-dev": { + "laravel-lang/status-generator": "^2.3.1", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.3 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Actions\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Actions\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + }, + { + "name": "Laravel Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "Translation of buttons and other action elements", + "keywords": [ + "actions", + "buttons", + "lang", + "languages", + "laravel", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/actions/issues", + "source": "https://github.com/Laravel-Lang/actions/tree/1.10.1" + }, + "time": "2025-03-10T17:07:52+00:00" + }, + { + "name": "laravel-lang/attributes", + "version": "2.13.4", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/attributes.git", + "reference": "c3671787b92fb83da1f5a4f9b6dcc9f4e3edfafe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/attributes/zipball/c3671787b92fb83da1f5a4f9b6dcc9f4e3edfafe", + "reference": "c3671787b92fb83da1f5a4f9b6dcc9f4e3edfafe", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel-lang/publisher": "^14.0 || ^15.0 || ^16.0", + "php": "^8.1" + }, + "require-dev": { + "laravel-lang/status-generator": "^1.19 || ^2.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Attributes\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Attributes\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://github.com/Laravel-Lang" + } + ], + "description": "List of 126 languages for form field names", + "keywords": [ + "attributes", + "fields", + "form", + "lang", + "languages", + "laravel", + "messages", + "translations", + "validation" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/attributes/issues", + "source": "https://github.com/Laravel-Lang/attributes/tree/2.13.4" + }, + "time": "2025-03-14T10:43:34+00:00" + }, + { + "name": "laravel-lang/common", + "version": "6.7.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/common.git", + "reference": "098bb5e900c5381d326f3cfd953fee40045e299f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/common/zipball/098bb5e900c5381d326f3cfd953fee40045e299f", + "reference": "098bb5e900c5381d326f3cfd953fee40045e299f", + "shasum": "" + }, + "require": { + "laravel-lang/actions": "^1.9", + "laravel-lang/attributes": "^2.12", + "laravel-lang/http-statuses": "^3.8", + "laravel-lang/json-fallback": "^2.2", + "laravel-lang/lang": "^13.12 || ^14.0 || ^15.5.1", + "laravel-lang/locales": "^2.10", + "laravel-lang/models": "^1.3", + "laravel-lang/moonshine": "^1.2", + "laravel-lang/publisher": "^16.5", + "laravel-lang/routes": "^1.7", + "laravel-lang/starter-kits": "^1.0", + "php": "^8.1" + }, + "require-dev": { + "dragon-code/support": "^6.13", + "orchestra/testbench": "^8.17 || ^9.1.2 || ^10.0", + "phpunit/phpunit": "^10.5.20 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.4 || ^7.1.1" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laravel-Lang Team", + "homepage": "https://github.com/Laravel-Lang" + }, + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + } + ], + "description": "Easily connect the necessary language packs to the application", + "keywords": [ + "Laravel-lang", + "actions", + "attribute", + "attributes", + "breeze", + "buttons", + "cashier", + "fortify", + "framework", + "http", + "http-status", + "http-status-code", + "i18n", + "jetstream", + "lang", + "language", + "languages", + "laravel", + "locale", + "locales", + "localization", + "localizations", + "moonshine", + "nova", + "publisher", + "spark", + "translation", + "translations", + "ui" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/common/issues", + "source": "https://github.com/Laravel-Lang/common" + }, + "time": "2025-03-04T07:34:14+00:00" + }, + { + "name": "laravel-lang/config", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/config.git", + "reference": "0f6a41a1d5f4bde6ff59fbfd9e349ac64b737c69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/config/zipball/0f6a41a1d5f4bde6ff59fbfd9e349ac64b737c69", + "reference": "0f6a41a1d5f4bde6ff59fbfd9e349ac64b737c69", + "shasum": "" + }, + "require": { + "archtechx/enums": "^1.0", + "illuminate/config": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/locale-list": "^1.5", + "php": "^8.1" + }, + "require-dev": { + "orchestra/testbench": "^8.23 || ^9.1 || ^10.0", + "pestphp/pest": "^2.34 || ^3.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Config\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Config\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "The Laravel-Lang config package", + "keywords": [ + "Laravel-lang", + "Settings", + "config", + "lang", + "languages", + "laravel", + "locale", + "locales", + "localization", + "localizations", + "translation", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/config/issues", + "source": "https://github.com/Laravel-Lang/config/tree/1.14.0" + }, + "time": "2025-04-11T07:31:54+00:00" + }, + { + "name": "laravel-lang/http-statuses", + "version": "3.10.3", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/http-statuses.git", + "reference": "32f9c3e9a93179ea6769844eaddfe8ae4cf3df63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/http-statuses/zipball/32f9c3e9a93179ea6769844eaddfe8ae4cf3df63", + "reference": "32f9c3e9a93179ea6769844eaddfe8ae4cf3df63", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel-lang/publisher": "^14.1 || ^15.0 || ^16.0", + "php": "^8.1" + }, + "require-dev": { + "laravel-lang/status-generator": "^1.19 || ^2.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\HttpStatuses\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\HttpStatuses\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://github.com/Laravel-Lang" + } + ], + "description": "List of 127 languages for HTTP statuses", + "keywords": [ + "http", + "lang", + "languages", + "laravel", + "messages", + "status", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/http-statuses/issues", + "source": "https://github.com/Laravel-Lang/http-statuses/tree/3.10.3" + }, + "time": "2025-03-11T20:03:32+00:00" + }, + { + "name": "laravel-lang/json-fallback", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/json-fallback.git", + "reference": "4d59cacd6a092d76fab4884be559312118ba0b12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/json-fallback/zipball/4d59cacd6a092d76fab4884be559312118ba0b12", + "reference": "4d59cacd6a092d76fab4884be559312118ba0b12", + "shasum": "" + }, + "require": { + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "illuminate/translation": "^10.0 || ^11.0 || ^12.0", + "php": "^8.1" + }, + "require-dev": { + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "LaravelLang\\JsonFallback\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://github.com/andrey-helldar" + }, + { + "name": "Felipe Dsdev", + "homepage": "https://github.com/felipe-dsdev" + } + ], + "description": "Adds support for fallback JSON string translation", + "support": { + "issues": "https://github.com/Laravel-Lang/json-fallback/issues", + "source": "https://github.com/Laravel-Lang/json-fallback/tree/2.2.0" + }, + "time": "2025-02-24T18:12:08+00:00" + }, + { + "name": "laravel-lang/lang", + "version": "15.21.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/lang.git", + "reference": "09206b3aedef0ecab295b130fdade626b17fde29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/09206b3aedef0ecab295b130fdade626b17fde29", + "reference": "09206b3aedef0ecab295b130fdade626b17fde29", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel-lang/publisher": "^16.0", + "php": "^8.2" + }, + "conflict": { + "laravel/framework": "<11.0.7" + }, + "require-dev": { + "laravel-lang/status-generator": "^2.11", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "symfony/var-dumper": "^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Lang\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Lang\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laravel-Lang Team", + "homepage": "https://github.com/Laravel-Lang" + } + ], + "description": "List of 126 languages for Laravel Framework, Laravel Jetstream, Laravel Fortify, Laravel Breeze, Laravel Cashier, Laravel Nova, Laravel Spark and Laravel UI", + "keywords": [ + "lang", + "languages", + "laravel", + "lpm" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/lang/issues", + "source": "https://github.com/Laravel-Lang/lang" + }, + "time": "2025-06-01T10:37:35+00:00" + }, + { + "name": "laravel-lang/locale-list", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/locale-list.git", + "reference": "a214a3d49b1bcd1d5111cc1bb9653f0280f223d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/locale-list/zipball/a214a3d49b1bcd1d5111cc1bb9653f0280f223d3", + "reference": "a214a3d49b1bcd1d5111cc1bb9653f0280f223d3", + "shasum": "" + }, + "require": { + "archtechx/enums": "^0.3.2 || ^1.0", + "php": "^8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "LaravelLang\\LocaleList\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "List of localizations available in Laravel Lang projects", + "keywords": [ + "Laravel-lang", + "lang", + "languages", + "laravel", + "locale", + "locales", + "localization", + "translation", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/locale-list/issues", + "source": "https://github.com/Laravel-Lang/locale-list" + }, + "time": "2025-02-24T19:11:00+00:00" + }, + { + "name": "laravel-lang/locales", + "version": "2.10.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/locales.git", + "reference": "8c1d2383ced70a919b3c2f430589be6c81663087" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/locales/zipball/8c1d2383ced70a919b3c2f430589be6c81663087", + "reference": "8c1d2383ced70a919b3c2f430589be6c81663087", + "shasum": "" + }, + "require": { + "archtechx/enums": "^0.3.2 || ^1.0", + "dragon-code/support": "^6.11.3", + "ext-json": "*", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/config": "^1.12", + "laravel-lang/locale-list": "^1.5", + "laravel-lang/native-country-names": "^1.5", + "laravel-lang/native-currency-names": "^1.6", + "laravel-lang/native-locale-names": "^2.5", + "php": "^8.1" + }, + "require-dev": { + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^2.24.1 || ^3.0", + "symfony/var-dumper": "^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Locales\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Locales\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "Basic functionality for working with localizations", + "keywords": [ + "laravel", + "locale", + "locales", + "localization", + "translation", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/locales/issues", + "source": "https://github.com/Laravel-Lang/locales" + }, + "time": "2025-02-24T20:38:10+00:00" + }, + { + "name": "laravel-lang/models", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/models.git", + "reference": "d983a8a821aceddf9a30e2baaf20e8e82a30c5d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/models/zipball/d983a8a821aceddf9a30e2baaf20e8e82a30c5d9", + "reference": "d983a8a821aceddf9a30e2baaf20e8e82a30c5d9", + "shasum": "" + }, + "require": { + "composer/class-map-generator": "^1.3", + "dragon-code/support": "^6.13", + "illuminate/database": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/config": "^1.12", + "laravel-lang/locales": "^2.10.0", + "laravel/prompts": ">=0.1", + "php": "^8.1" + }, + "require-dev": { + "orchestra/testbench": "^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^2.34 || ^3.0", + "pestphp/pest-plugin-laravel": "^2.4 || ^3.0", + "symfony/var-dumper": "^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Models\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Models\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro", + "role": "Maintainer" + }, + { + "name": "Andrey Sokolov", + "email": "walfireru@gmail.com", + "homepage": "https://github.com/Quiss", + "role": "Usability consultant" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://github.com/Laravel-Lang" + } + ], + "description": "Easy and fast way to localize models", + "keywords": [ + "database", + "l18n", + "languages", + "laravel", + "locales", + "localization", + "models", + "translate", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/models/issues", + "source": "https://github.com/Laravel-Lang/models" + }, + "time": "2025-02-24T21:01:53+00:00" + }, + { + "name": "laravel-lang/moonshine", + "version": "1.3.7", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/moonshine.git", + "reference": "d0d52b9932b48feb765f1a3394f12a8a8a78eefe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/moonshine/zipball/d0d52b9932b48feb765f1a3394f12a8a8a78eefe", + "reference": "d0d52b9932b48feb765f1a3394f12a8a8a78eefe", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel-lang/publisher": "^15.0 || ^16.4.1", + "php": "^8.1" + }, + "require-dev": { + "dragon-code/support": "^6.15.2", + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/lang": "^14.8 || ^15.14", + "laravel-lang/status-generator": "^2.12", + "phpunit/phpunit": "^10.0 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.3 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\MoonShine\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\MoonShine\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "Translation for MoonShine admin panel", + "keywords": [ + "lang", + "languages", + "laravel", + "moonshine", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/moonshine/issues", + "source": "https://github.com/Laravel-Lang/moonshine/tree/1.3.7" + }, + "time": "2025-05-01T05:27:46+00:00" + }, + { + "name": "laravel-lang/native-country-names", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/native-country-names.git", + "reference": "bb88d4bc54c309cb52d1de04bbdc0b2db651247c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/native-country-names/zipball/bb88d4bc54c309cb52d1de04bbdc0b2db651247c", + "reference": "bb88d4bc54c309cb52d1de04bbdc0b2db651247c", + "shasum": "" + }, + "require": { + "dragon-code/support": "^6.11", + "ext-json": "*", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/locale-list": "^1.5", + "pestphp/pest": "^2.24.3 || ^3.0", + "punic/punic": "^3.8", + "symfony/console": "^6.3 || ^7.0", + "symfony/process": "^6.3 || ^7.0", + "symfony/var-dumper": "^6.3 || ^7.0", + "vlucas/phpdotenv": "^5.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "LaravelLang\\NativeCountryNames\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "The project contains native translations of country names", + "keywords": [ + "Laravel-lang", + "countries", + "country", + "lang", + "languages", + "laravel", + "locale", + "locales", + "localization", + "territories", + "territory", + "translation", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/native-country-names/issues", + "source": "https://github.com/Laravel-Lang/native-country-names" + }, + "time": "2025-02-24T19:27:45+00:00" + }, + { + "name": "laravel-lang/native-currency-names", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/native-currency-names.git", + "reference": "c63dea01b3ce58f709ae20bf5521b41ffca194c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/native-currency-names/zipball/c63dea01b3ce58f709ae20bf5521b41ffca194c9", + "reference": "c63dea01b3ce58f709ae20bf5521b41ffca194c9", + "shasum": "" + }, + "require": { + "dragon-code/support": "^6.11", + "ext-json": "*", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/locale-list": "^1.2", + "pestphp/pest": "^2.24.3 || ^3.0", + "punic/punic": "^3.8", + "symfony/console": "^6.3 || ^7.0", + "symfony/process": "^6.3 || ^7.0", + "symfony/var-dumper": "^6.3 || ^7.0", + "vlucas/phpdotenv": "^5.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "LaravelLang\\NativeCurrencyNames\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "The project contains native translations of currency names", + "keywords": [ + "Laravel-lang", + "currency", + "lang", + "languages", + "laravel", + "locale", + "locales", + "localization", + "translation", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/native-currency-names/issues", + "source": "https://github.com/Laravel-Lang/native-currency-names" + }, + "time": "2025-02-24T19:57:57+00:00" + }, + { + "name": "laravel-lang/native-locale-names", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/native-locale-names.git", + "reference": "9e08ad7c0e088618c67e94a321e62dc93eddfea5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/native-locale-names/zipball/9e08ad7c0e088618c67e94a321e62dc93eddfea5", + "reference": "9e08ad7c0e088618c67e94a321e62dc93eddfea5", + "shasum": "" + }, + "require": { + "dragon-code/support": "^6.11", + "ext-json": "*", + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.31 || ^11.0 || ^12.0", + "laravel-lang/locale-list": "^1.2", + "pestphp/pest": "^2.24.3", + "punic/punic": "^3.8", + "symfony/console": "^6.3 || ^7.0", + "symfony/process": "^6.3 || ^7.0", + "symfony/var-dumper": "^6.3 || ^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "LaravelLang\\NativeLocaleNames\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "The project contains native translations of locale names", + "keywords": [ + "Laravel-lang", + "lang", + "languages", + "laravel", + "locale", + "locales", + "localization", + "translation", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/native-locale-names/issues", + "source": "https://github.com/Laravel-Lang/native-locale-names" + }, + "time": "2025-02-24T20:00:58+00:00" + }, + { + "name": "laravel-lang/publisher", + "version": "16.6.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/publisher.git", + "reference": "ab4f5364444065f95ca78c85c319f7786f67d7ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/publisher/zipball/ab4f5364444065f95ca78c85c319f7786f67d7ac", + "reference": "ab4f5364444065f95ca78c85c319f7786f67d7ac", + "shasum": "" + }, + "require": { + "composer/semver": "^3.4", + "dragon-code/pretty-array": "^4.1", + "dragon-code/support": "^6.11.3", + "ext-json": "*", + "illuminate/collections": "^10.0 || ^11.0 || ^12.0", + "illuminate/console": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/config": "^1.12", + "laravel-lang/locales": "^2.10", + "league/commonmark": "^2.4.1", + "league/config": "^1.2", + "php": "^8.1" + }, + "conflict": { + "laravel-lang/attributes": "<2.0", + "laravel-lang/http-statuses": "<3.0", + "laravel-lang/lang": "<11.0" + }, + "require-dev": { + "laravel-lang/json-fallback": "^2.2", + "orchestra/testbench": "^8.14 || ^9.0 || ^10.0", + "phpunit/phpunit": "^10.4.2 || ^11.0 || ^12.0", + "symfony/var-dumper": "^6.3.6 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Publisher\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\Publisher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "Localization publisher for your Laravel application", + "keywords": [ + "Laravel-lang", + "breeze", + "cashier", + "fortify", + "framework", + "i18n", + "jetstream", + "lang", + "languages", + "laravel", + "locale", + "locales", + "localization", + "localizations", + "lpm", + "lumen", + "nova", + "publisher", + "spark", + "trans", + "translation", + "translations", + "validations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/publisher/issues", + "source": "https://github.com/Laravel-Lang/publisher" + }, + "time": "2025-03-03T10:29:09+00:00" + }, + { + "name": "laravel-lang/routes", + "version": "1.9.0", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/routes.git", + "reference": "d9265ff5ec572828a3f141cc07d30f8c4f3d0f75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/routes/zipball/d9265ff5ec572828a3f141cc07d30f8c4f3d0f75", + "reference": "d9265ff5ec572828a3f141cc07d30f8c4f3d0f75", + "shasum": "" + }, + "require": { + "dragon-code/support": "^6.13", + "illuminate/config": "^10.0 || ^11.0 || ^12.0", + "illuminate/http": "^10.0 || ^11.0 || ^12.0", + "illuminate/routing": "^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^10.0 || ^11.0 || ^12.0", + "laravel-lang/config": "^1.13", + "laravel-lang/locales": "^2.10", + "php": "^8.1" + }, + "require-dev": { + "orchestra/testbench": "^8.23 || ^9.1 || ^10.0", + "pestphp/pest": "^2.34 || ^3.0", + "pestphp/pest-plugin-laravel": "^2.4 || ^3.0", + "symfony/var-dumper": "^6.0 || ^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\Routes\\ServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "helpers/functions.php" + ], + "psr-4": { + "LaravelLang\\Routes\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro", + "homepage": "https://dragon-code.pro" + }, + { + "name": "Laravel-Lang Team", + "homepage": "https://github.com/Laravel-Lang" + } + ], + "description": "Easy and fast way to localize routes", + "keywords": [ + "l18n", + "languages", + "laravel", + "localization", + "routes", + "translate", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/routes/issues", + "source": "https://github.com/Laravel-Lang/routes" + }, + "time": "2025-04-14T14:11:58+00:00" + }, + { + "name": "laravel-lang/starter-kits", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/Laravel-Lang/starter-kits.git", + "reference": "37884af8f9bdaf3cbc40716ddbe1b9e543bef615" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Lang/starter-kits/zipball/37884af8f9bdaf3cbc40716ddbe1b9e543bef615", + "reference": "37884af8f9bdaf3cbc40716ddbe1b9e543bef615", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel-lang/publisher": "^16.6", + "php": "^8.1" + }, + "require-dev": { + "laravel-lang/status-generator": "^2.13", + "phpunit/phpunit": "^11.0 || ^12.0", + "symfony/var-dumper": "^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "LaravelLang\\StarterKits\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "LaravelLang\\StarterKits\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrey Helldar", + "email": "helldar@dragon-code.pro" + }, + { + "name": "Laravel Lang Team", + "homepage": "https://laravel-lang.com" + } + ], + "description": "Translations for Laravel Starter Kits", + "keywords": [ + "i18n", + "lang", + "languages", + "laravel", + "starter-kit", + "starter-kits", + "translations" + ], + "support": { + "issues": "https://github.com/Laravel-Lang/starter-kits/issues", + "source": "https://github.com/Laravel-Lang/starter-kits/tree/1.3.8" + }, + "time": "2025-05-11T00:05:02+00:00" + }, + { + "name": "laravel/framework", + "version": "v12.17.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "8729d084510480fdeec9b6ad198180147d4a7f06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/8729d084510480fdeec9b6ad198180147d4a7f06", + "reference": "8729d084510480fdeec9b6ad198180147d4a7f06", + "shasum": "" + }, + "require": { + "brick/math": "^0.11|^0.12|^0.13", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^3.8.4", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.0.0", + "pda/pheanstalk": "^5.0.6|^7.0.0", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "12.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-06-03T14:04:18+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.3.5", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.5" + }, + "time": "2025-02-11T13:34:40+00:00" + }, + { + "name": "laravel/reverb", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/reverb.git", + "reference": "bf84766ad35d9174fb508147f956e8bcf2e46e91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/reverb/zipball/bf84766ad35d9174fb508147f956e8bcf2e46e91", + "reference": "bf84766ad35d9174fb508147f956e8bcf2e46e91", + "shasum": "" + }, + "require": { + "clue/redis-react": "^2.6", + "guzzlehttp/psr7": "^2.6", + "illuminate/console": "^10.47|^11.0|^12.0", + "illuminate/contracts": "^10.47|^11.0|^12.0", + "illuminate/http": "^10.47|^11.0|^12.0", + "illuminate/support": "^10.47|^11.0|^12.0", + "laravel/prompts": "^0.1.15|^0.2.0|^0.3.0", + "php": "^8.2", + "pusher/pusher-php-server": "^7.2", + "ratchet/rfc6455": "^0.4", + "react/promise-timer": "^1.10", + "react/socket": "^1.14", + "symfony/console": "^6.0|^7.0", + "symfony/http-foundation": "^6.3|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^8.0|^9.0|^10.0", + "pestphp/pest": "^2.0|^3.0", + "phpstan/phpstan": "^1.10", + "ratchet/pawl": "^0.4.1", + "react/async": "^4.2", + "react/http": "^1.9" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Output": "Laravel\\Reverb\\Output" + }, + "providers": [ + "Laravel\\Reverb\\ApplicationManagerServiceProvider", + "Laravel\\Reverb\\ReverbServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Reverb\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Joe Dixon", + "email": "joe@laravel.com" + } + ], + "description": "Laravel Reverb provides a real-time WebSocket communication backend for Laravel applications.", + "keywords": [ + "WebSockets", + "laravel", + "real-time", + "websocket" + ], + "support": { + "issues": "https://github.com/laravel/reverb/issues", + "source": "https://github.com/laravel/reverb/tree/v1.5.0" + }, + "time": "2025-03-31T14:06:47+00:00" + }, + { + "name": "laravel/sanctum", + "version": "v4.1.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.0|^12.0", + "illuminate/contracts": "^11.0|^12.0", + "illuminate/database": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "php": "^8.2", + "symfony/console": "^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "orchestra/testbench": "^9.0|^10.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2025-04-23T13:03:38+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2025-03-19T13:51:03+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.10.1" + }, + "time": "2025-01-27T14:24:01+00:00" + }, + { + "name": "league/commonmark", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-05-05T12:20:28+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.29.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" + }, + "time": "2024-10-08T08:58:34+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + }, + "time": "2024-08-09T21:24:39+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, + { + "name": "maatwebsite/excel", + "version": "3.1.64", + "source": { + "type": "git", + "url": "https://github.com/SpartnerNL/Laravel-Excel.git", + "reference": "e25d44a2d91da9179cd2d7fec952313548597a79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e25d44a2d91da9179cd2d7fec952313548597a79", + "reference": "e25d44a2d91da9179cd2d7fec952313548597a79", + "shasum": "" + }, + "require": { + "composer/semver": "^3.3", + "ext-json": "*", + "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0", + "php": "^7.0||^8.0", + "phpoffice/phpspreadsheet": "^1.29.9", + "psr/simple-cache": "^1.0||^2.0||^3.0" + }, + "require-dev": { + "laravel/scout": "^7.0||^8.0||^9.0||^10.0", + "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0", + "predis/predis": "^1.1" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Excel": "Maatwebsite\\Excel\\Facades\\Excel" + }, + "providers": [ + "Maatwebsite\\Excel\\ExcelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Maatwebsite\\Excel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Patrick Brouwers", + "email": "patrick@spartner.nl" + } + ], + "description": "Supercharged Excel exports and imports in Laravel", + "keywords": [ + "PHPExcel", + "batch", + "csv", + "excel", + "export", + "import", + "laravel", + "php", + "phpspreadsheet" + ], + "support": { + "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.64" + }, + "funding": [ + { + "url": "https://laravel-excel.com/commercial-support", + "type": "custom" + }, + { + "url": "https://github.com/patrickbrouwers", + "type": "github" + } + ], + "time": "2025-02-24T11:12:50+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-zlib": "*", + "php-64bit": "^8.2" + }, + "require-dev": { + "brianium/paratest": "^7.7", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.16", + "guzzlehttp/guzzle": "^7.5", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.5", + "phpunit/phpunit": "^11.0", + "vimeo/psalm": "^6.0" + }, + "suggest": { + "guzzlehttp/psr7": "^2.4", + "psr/http-message": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" + }, + "funding": [ + { + "url": "https://github.com/maennchen", + "type": "github" + } + ], + "time": "2025-01-27T12:07:53+00:00" + }, + { + "name": "markbaker/complex", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "^9.3", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPComplex/issues", + "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2" + }, + "time": "2022-12-06T16:21:08+00:00" + }, + { + "name": "markbaker/matrix", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "728434227fe21be27ff6d86621a1b13107a2562c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c", + "reference": "728434227fe21be27ff6d86621a1b13107a2562c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "^9.3", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "^4.0", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "sebastian/phpcpd": "^4.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matrix\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@demon-angel.eu" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPMatrix/issues", + "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1" + }, + "time": "2022-12-02T22:17:43+00:00" + }, + { + "name": "masterminds/html5", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" + }, + "time": "2024-03-31T07:05:07+00:00" + }, + { + "name": "matomo/device-detector", + "version": "6.4.6", + "source": { + "type": "git", + "url": "https://github.com/matomo-org/device-detector.git", + "reference": "6f07f615199851548db47a900815d2ea2cdcde08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/6f07f615199851548db47a900815d2ea2cdcde08", + "reference": "6f07f615199851548db47a900815d2ea2cdcde08", + "shasum": "" + }, + "require": { + "mustangostang/spyc": "*", + "php": "^7.2|^8.0" + }, + "replace": { + "piwik/device-detector": "self.version" + }, + "require-dev": { + "matthiasmullie/scrapbook": "^1.4.7", + "mayflower/mo4-coding-standard": "^v9.0.0", + "phpstan/phpstan": "^1.10.44", + "phpunit/phpunit": "^8.5.8", + "psr/cache": "^1.0.1", + "psr/simple-cache": "^1.0.1", + "slevomat/coding-standard": "<8.16.0", + "symfony/yaml": "^5.1.7" + }, + "suggest": { + "doctrine/cache": "Can directly be used for caching purpose", + "ext-yaml": "Necessary for using the Pecl YAML parser" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeviceDetector\\": "" + }, + "exclude-from-classmap": [ + "Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The Matomo Team", + "email": "hello@matomo.org", + "homepage": "https://matomo.org/team/" + } + ], + "description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, media players, mobile apps, feed readers, libraries, etc), operating systems, devices, brands and models.", + "homepage": "https://matomo.org", + "keywords": [ + "devicedetection", + "parser", + "useragent" + ], + "support": { + "forum": "https://forum.matomo.org/", + "issues": "https://github.com/matomo-org/device-detector/issues", + "source": "https://github.com/matomo-org/matomo", + "wiki": "https://dev.matomo.org/" + }, + "time": "2025-06-10T10:00:59+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.9.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2025-03-24T10:02:05+00:00" + }, + { + "name": "mpociot/reflection-docblock", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/mpociot/reflection-docblock.git", + "reference": "c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mpociot/reflection-docblock/zipball/c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587", + "reference": "c8b2e2b1f5cebbb06e2b5ccbf2958f2198867587", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mpociot": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "support": { + "issues": "https://github.com/mpociot/reflection-docblock/issues", + "source": "https://github.com/mpociot/reflection-docblock/tree/master" + }, + "time": "2016-06-20T20:53:12+00:00" + }, + { + "name": "mustangostang/spyc", + "version": "0.6.3", + "source": { + "type": "git", + "url": "https://github.com/mustangostang/spyc.git", + "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0", + "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "4.3.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.5.x-dev" + } + }, + "autoload": { + "files": [ + "Spyc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "mustangostang", + "email": "vlad.andersen@gmail.com" + } + ], + "description": "A simple YAML loader/dumper class for PHP", + "homepage": "https://github.com/mustangostang/spyc/", + "keywords": [ + "spyc", + "yaml", + "yml" + ], + "support": { + "issues": "https://github.com/mustangostang/spyc/issues", + "source": "https://github.com/mustangostang/spyc/tree/0.6.3" + }, + "time": "2019-09-10T13:16:29+00:00" + }, + { + "name": "nesbot/carbon", + "version": "3.9.1", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "ced71f79398ece168e24f7f7710462f462310d4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", + "reference": "ced71f79398ece168e24f7f7710462f462310d4d", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.57.2", + "kylekatarnls/multi-tester": "^2.5.3", + "ondrejmirtes/better-reflection": "^6.25.0.4", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.11.2", + "phpunit/phpunit": "^10.5.20", + "squizlabs/php_codesniffer": "^3.9.0" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2025-05-01T19:51:51+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.4" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.2" + }, + "time": "2024-10-06T23:10:23+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.7", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.4" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.5", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.7" + }, + "time": "2025-06-03T04:55:08+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.5.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", + "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.5.0" + }, + "time": "2025-05-31T08:24:38+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.8.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.0", + "nunomaduro/termwind": "^2.3.0", + "php": "^8.2.0", + "symfony/console": "^7.2.5" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.2", + "laravel/framework": "^11.44.2 || ^12.6", + "laravel/pint": "^1.21.2", + "laravel/sail": "^1.41.0", + "laravel/sanctum": "^4.0.8", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.1", + "pestphp/pest": "^3.8.0", + "sebastian/environment": "^7.2.0 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-04-03T14:33:09+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.2.6" + }, + "require-dev": { + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2025-05-08T08:14:37+00:00" + }, + { + "name": "paragonie/sodium_compat", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/sodium_compat.git", + "reference": "a673d5f310477027cead2e2f2b6db5d8368157cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/a673d5f310477027cead2e2f2b6db5d8368157cb", + "reference": "a673d5f310477027cead2e2f2b6db5d8368157cb", + "shasum": "" + }, + "require": { + "php": "^8.1", + "php-64bit": "*" + }, + "require-dev": { + "phpunit/phpunit": "^7|^8|^9", + "vimeo/psalm": "^4|^5" + }, + "suggest": { + "ext-sodium": "Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "files": [ + "autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com" + }, + { + "name": "Frank Denis", + "email": "jedisct1@pureftpd.org" + } + ], + "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", + "keywords": [ + "Authentication", + "BLAKE2b", + "ChaCha20", + "ChaCha20-Poly1305", + "Chapoly", + "Curve25519", + "Ed25519", + "EdDSA", + "Edwards-curve Digital Signature Algorithm", + "Elliptic Curve Diffie-Hellman", + "Poly1305", + "Pure-PHP cryptography", + "RFC 7748", + "RFC 8032", + "Salpoly", + "Salsa20", + "X25519", + "XChaCha20-Poly1305", + "XSalsa20-Poly1305", + "Xchacha20", + "Xsalsa20", + "aead", + "cryptography", + "ecdh", + "elliptic curve", + "elliptic curve cryptography", + "encryption", + "libsodium", + "php", + "public-key cryptography", + "secret-key cryptography", + "side-channel resistant" + ], + "support": { + "issues": "https://github.com/paragonie/sodium_compat/issues", + "source": "https://github.com/paragonie/sodium_compat/tree/v2.1.0" + }, + "time": "2024-09-04T12:51:01+00:00" + }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.29.10", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "c80041b1628c4f18030407134fe88303661d4e4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/c80041b1628c4f18030407134fe88303661d4e4e", + "reference": "c80041b1628c4f18030407134fe88303661d4e4e", + "shasum": "" + }, + "require": { + "composer/pcre": "^1||^2||^3", + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "ezyang/htmlpurifier": "^4.15", + "maennchen/zipstream-php": "^2.1 || ^3.0", + "markbaker/complex": "^3.0", + "markbaker/matrix": "^3.0", + "php": "^7.4 || ^8.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-main", + "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.2", + "mitoteam/jpgraph": "^10.3", + "mpdf/mpdf": "^8.1.1", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.7", + "tecnickcom/tcpdf": "^6.5" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer", + "ext-intl": "PHP Internationalization Functions", + "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.10" + }, + "time": "2025-02-08T02:56:14+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:41:07+00:00" + }, + { + "name": "predis/predis", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "34fb0a7da0330df1bab4280fcac4afdeeccc3edf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/34fb0a7da0330df1bab4280fcac4afdeeccc3edf", + "reference": "34fb0a7da0330df1bab4280fcac4afdeeccc3edf", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "psr/http-message": "^1.0|^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.3", + "phpstan/phpstan": "^1.9", + "phpunit/phpcov": "^6.0 || ^8.0", + "phpunit/phpunit": "^8.0 || ~9.4.4" + }, + "suggest": { + "ext-relay": "Faster connection with in-memory caching (>=0.6.2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "A flexible and feature-complete Redis/Valkey client for PHP.", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "time": "2025-05-16T18:30:32+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/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": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.8", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/85057ceedee50c49d4f6ecaff73ee96adb3b3625", + "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.8" + }, + "time": "2025-03-16T03:05:19+00:00" + }, + { + "name": "pusher/pusher-php-server", + "version": "7.2.7", + "source": { + "type": "git", + "url": "https://github.com/pusher/pusher-http-php.git", + "reference": "148b0b5100d000ed57195acdf548a2b1b38ee3f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pusher/pusher-http-php/zipball/148b0b5100d000ed57195acdf548a2b1b38ee3f7", + "reference": "148b0b5100d000ed57195acdf548a2b1b38ee3f7", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.2", + "paragonie/sodium_compat": "^1.6|^2.0", + "php": "^7.3|^8.0", + "psr/log": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "overtrue/phplint": "^2.3", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Pusher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Library for interacting with the Pusher REST API", + "keywords": [ + "events", + "messaging", + "php-pusher-server", + "publish", + "push", + "pusher", + "real time", + "real-time", + "realtime", + "rest", + "trigger" + ], + "support": { + "issues": "https://github.com/pusher/pusher-http-php/issues", + "source": "https://github.com/pusher/pusher-http-php/tree/7.2.7" + }, + "time": "2025-01-06T10:56:20+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": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.8.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.8.1" + }, + "time": "2025-06-01T06:28:46+00:00" + }, + { + "name": "ratchet/rfc6455", + "version": "v0.4.0", + "source": { + "type": "git", + "url": "https://github.com/ratchetphp/RFC6455.git", + "reference": "859d95f85dda0912c6d5b936d036d044e3af47ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/859d95f85dda0912c6d5b936d036d044e3af47ef", + "reference": "859d95f85dda0912c6d5b936d036d044e3af47ef", + "shasum": "" + }, + "require": { + "php": ">=7.4", + "psr/http-factory-implementation": "^1.0", + "symfony/polyfill-php80": "^1.15" + }, + "require-dev": { + "guzzlehttp/psr7": "^2.7", + "phpunit/phpunit": "^9.5", + "react/socket": "^1.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ratchet\\RFC6455\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "role": "Developer" + }, + { + "name": "Matt Bonneau", + "role": "Developer" + } + ], + "description": "RFC6455 WebSocket protocol handler", + "homepage": "http://socketo.me", + "keywords": [ + "WebSockets", + "rfc6455", + "websocket" + ], + "support": { + "chat": "https://gitter.im/reactphp/reactphp", + "issues": "https://github.com/ratchetphp/RFC6455/issues", + "source": "https://github.com/ratchetphp/RFC6455/tree/v0.4.0" + }, + "time": "2025-02-24T01:18:22+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/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/promise-timer", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-timer.git", + "reference": "4f70306ed66b8b44768941ca7f142092600fafc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/4f70306ed66b8b44768941ca7f142092600fafc1", + "reference": "4f70306ed66b8b44768941ca7f142092600fafc1", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7.0 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\Timer\\": "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": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", + "homepage": "https://github.com/reactphp/promise-timer", + "keywords": [ + "async", + "event-loop", + "promise", + "reactphp", + "timeout", + "timer" + ], + "support": { + "issues": "https://github.com/reactphp/promise-timer/issues", + "source": "https://github.com/reactphp/promise-timer/tree/v1.11.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-04T14:27:45+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": "reefki/laravel-device-detector", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/reefki/laravel-device-detector.git", + "reference": "2cbe6577a0aa4dd9b51a9536e81619e4c08bdeb2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reefki/laravel-device-detector/zipball/2cbe6577a0aa4dd9b51a9536e81619e4c08bdeb2", + "reference": "2cbe6577a0aa4dd9b51a9536e81619e4c08bdeb2", + "shasum": "" + }, + "require": { + "laravel/framework": "^9.0|^10.0|^11.0|^12.0", + "matomo/device-detector": "^6.0" + }, + "require-dev": { + "laravel/pint": "^1.13", + "orchestra/testbench": "^7.0|^8.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Device": "Reefki\\DeviceDetector\\Device" + }, + "providers": [ + "Reefki\\DeviceDetector\\DeviceDetectorServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Reefki\\DeviceDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rifki Aria Gumelar", + "email": "rifki@rifki.net" + } + ], + "description": "Laravel wrapper for Matomo's Universal Device Detection library.", + "support": { + "issues": "https://github.com/reefki/laravel-device-detector/issues", + "source": "https://github.com/reefki/laravel-device-detector/tree/v1.0.2" + }, + "time": "2025-03-02T02:50:30+00:00" + }, + { + "name": "sabberworm/php-css-parser", + "version": "v8.8.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "3de493bdddfd1f051249af725c7e0d2c38fed740" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/3de493bdddfd1f051249af725c7e0d2c38fed740", + "reference": "3de493bdddfd1f051249af725c7e0d2c38fed740", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.8.0" + }, + "time": "2025-03-23T17:59:05+00:00" + }, + { + "name": "shalvah/clara", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/shalvah/clara.git", + "reference": "cdbb5737cbdd101756d97dd2279a979a1af7710b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shalvah/clara/zipball/cdbb5737cbdd101756d97dd2279a979a1af7710b", + "reference": "cdbb5737cbdd101756d97dd2279a979a1af7710b", + "shasum": "" + }, + "require": { + "php": ">=7.4", + "symfony/console": "^4.0|^5.0|^6.0|^7.0" + }, + "require-dev": { + "eloquent/phony-phpunit": "^7.0", + "phpunit/phpunit": "^9.1" + }, + "type": "library", + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Shalvah\\Clara\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "🔊 Simple, pretty, testable console output for CLI apps.", + "keywords": [ + "cli", + "log", + "logging" + ], + "support": { + "issues": "https://github.com/shalvah/clara/issues", + "source": "https://github.com/shalvah/clara/tree/3.2.0" + }, + "time": "2024-02-27T20:30:59+00:00" + }, + { + "name": "shalvah/upgrader", + "version": "0.6.0", + "source": { + "type": "git", + "url": "https://github.com/shalvah/upgrader.git", + "reference": "d95ed17fe9f5e1ee7d47ad835595f1af080a867f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shalvah/upgrader/zipball/d95ed17fe9f5e1ee7d47ad835595f1af080a867f", + "reference": "d95ed17fe9f5e1ee7d47ad835595f1af080a867f", + "shasum": "" + }, + "require": { + "illuminate/support": ">=8.0", + "nikic/php-parser": "^5.0", + "php": ">=8.0" + }, + "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.2.0", + "pestphp/pest": "^1.21", + "phpstan/phpstan": "^1.0", + "spatie/ray": "^1.33" + }, + "type": "library", + "autoload": { + "psr-4": { + "Shalvah\\Upgrader\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shalvah", + "email": "hello@shalvah.me" + } + ], + "description": "Create automatic upgrades for your package.", + "homepage": "http://github.com/shalvah/upgrader", + "keywords": [ + "upgrade" + ], + "support": { + "issues": "https://github.com/shalvah/upgrader/issues", + "source": "https://github.com/shalvah/upgrader/tree/0.6.0" + }, + "funding": [ + { + "url": "https://patreon.com/shalvah", + "type": "patreon" + } + ], + "time": "2024-02-20T11:51:46+00:00" + }, + { + "name": "spatie/data-transfer-object", + "version": "3.9.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/data-transfer-object.git", + "reference": "1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/data-transfer-object/zipball/1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8", + "reference": "1df0906c4e9e3aebd6c0506fd82c8b7d5548c1c8", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "illuminate/collections": "^8.36", + "jetbrains/phpstorm-attributes": "^1.0", + "larapack/dd": "^1.1", + "phpunit/phpunit": "^9.5.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\DataTransferObject\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brent Roose", + "email": "brent@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Data transfer objects with batteries included", + "homepage": "https://github.com/spatie/data-transfer-object", + "keywords": [ + "data-transfer-object", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/data-transfer-object/issues", + "source": "https://github.com/spatie/data-transfer-object/tree/3.9.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "abandoned": "spatie/laravel-data", + "time": "2022-09-16T13:34:38+00:00" + }, + { + "name": "spatie/laravel-activitylog", + "version": "4.10.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-activitylog.git", + "reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/466f30f7245fe3a6e328ad5e6812bd43b4bddea5", + "reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5", + "shasum": "" + }, + "require": { + "illuminate/config": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "illuminate/database": "^8.69 || ^9.27 || ^10.0 || ^11.0 || ^12.0", + "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.6.3" + }, + "require-dev": { + "ext-json": "*", + "orchestra/testbench": "^6.23 || ^7.0 || ^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^1.20 || ^2.0 || ^3.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Activitylog\\ActivitylogServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\Activitylog\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Sebastian De Deyne", + "email": "sebastian@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Tom Witkowski", + "email": "dev.gummibeer@gmail.com", + "homepage": "https://gummibeer.de", + "role": "Developer" + } + ], + "description": "A very simple activity logger to monitor the users of your website or application", + "homepage": "https://github.com/spatie/activitylog", + "keywords": [ + "activity", + "laravel", + "log", + "spatie", + "user" + ], + "support": { + "issues": "https://github.com/spatie/laravel-activitylog/issues", + "source": "https://github.com/spatie/laravel-activitylog/tree/4.10.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-02-10T15:38:25+00:00" + }, + { + "name": "spatie/laravel-json-api-paginate", + "version": "1.16.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-json-api-paginate.git", + "reference": "2acf8b754e088285f1a29fdd5b2295769aee76f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-json-api-paginate/zipball/2acf8b754e088285f1a29fdd5b2295769aee76f4", + "reference": "2acf8b754e088285f1a29fdd5b2295769aee76f4", + "shasum": "" + }, + "require": { + "illuminate/support": "^10.0|^11.0|^12.0", + "php": "^8.0" + }, + "require-dev": { + "orchestra/testbench": "^8.21.1|^9.0|^10.0", + "pestphp/pest": "^2.34|^3.7", + "phpunit/phpunit": "^9.0|^10.5.10|^11.5.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\JsonApiPaginate\\JsonApiPaginateServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\JsonApiPaginate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A paginator that plays nice with the JSON API spec", + "homepage": "https://github.com/spatie/laravel-json-api-paginate", + "keywords": [ + "laravel-json-api-paginate", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/laravel-json-api-paginate/tree/1.16.3" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2025-02-25T20:27:30+00:00" + }, + { + "name": "spatie/laravel-package-tools", + "version": "1.92.4", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-package-tools.git", + "reference": "d20b1969f836d210459b78683d85c9cd5c5f508c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/d20b1969f836d210459b78683d85c9cd5c5f508c", + "reference": "d20b1969f836d210459b78683d85c9cd5c5f508c", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^9.28|^10.0|^11.0|^12.0", + "php": "^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.5", + "orchestra/testbench": "^7.7|^8.0|^9.0|^10.0", + "pestphp/pest": "^1.23|^2.1|^3.1", + "phpunit/php-code-coverage": "^9.0|^10.0|^11.0", + "phpunit/phpunit": "^9.5.24|^10.5|^11.5", + "spatie/pest-plugin-test-time": "^1.1|^2.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\LaravelPackageTools\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Tools for creating Laravel packages", + "homepage": "https://github.com/spatie/laravel-package-tools", + "keywords": [ + "laravel-package-tools", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-package-tools/issues", + "source": "https://github.com/spatie/laravel-package-tools/tree/1.92.4" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-04-11T15:27:14+00:00" + }, + { + "name": "spatie/laravel-permission", + "version": "6.19.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-permission.git", + "reference": "0cd412dcad066d75caf0b977716809be7e7642fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/0cd412dcad066d75caf0b977716809be7e7642fd", + "reference": "0cd412dcad066d75caf0b977716809be7e7642fd", + "shasum": "" + }, + "require": { + "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0", + "php": "^8.0" + }, + "require-dev": { + "laravel/passport": "^11.0|^12.0", + "laravel/pint": "^1.0", + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", + "phpunit/phpunit": "^9.4|^10.1|^11.5" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Permission\\PermissionServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "6.x-dev", + "dev-master": "6.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\Permission\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Permission handling for Laravel 8.0 and up", + "homepage": "https://github.com/spatie/laravel-permission", + "keywords": [ + "acl", + "laravel", + "permission", + "permissions", + "rbac", + "roles", + "security", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-permission/issues", + "source": "https://github.com/spatie/laravel-permission/tree/6.19.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-05-31T00:50:27+00:00" + }, + { + "name": "spatie/laravel-query-builder", + "version": "6.3.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-query-builder.git", + "reference": "3675f7bace346dc5243f58fa7c531e36471200f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/3675f7bace346dc5243f58fa7c531e36471200f4", + "reference": "3675f7bace346dc5243f58fa7c531e36471200f4", + "shasum": "" + }, + "require": { + "illuminate/database": "^10.0|^11.0|^12.0", + "illuminate/http": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "php": "^8.2", + "spatie/laravel-package-tools": "^1.11" + }, + "require-dev": { + "ext-json": "*", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^7.0|^8.0|^10.0", + "pestphp/pest": "^2.0|^3.7", + "phpunit/phpunit": "^10.0|^11.5.3", + "spatie/invade": "^2.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\QueryBuilder\\QueryBuilderServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\QueryBuilder\\": "src", + "Spatie\\QueryBuilder\\Database\\Factories\\": "database/factories" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily build Eloquent queries from API requests", + "homepage": "https://github.com/spatie/laravel-query-builder", + "keywords": [ + "laravel-query-builder", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-query-builder/issues", + "source": "https://github.com/spatie/laravel-query-builder" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2025-04-16T07:30:03+00:00" + }, + { + "name": "stichoza/google-translate-php", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/Stichoza/google-translate-php.git", + "reference": "2891310296cc115786d7c135a47a4ed53cd38df1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Stichoza/google-translate-php/zipball/2891310296cc115786d7c135a47a4ed53cd38df1", + "reference": "2891310296cc115786d7c135a47a4ed53cd38df1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "guzzlehttp/guzzle": "^7.0", + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Stichoza\\GoogleTranslate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Levan Velijanashvili", + "email": "me@stichoza.com" + } + ], + "description": "Free Google Translate API PHP Package", + "homepage": "https://github.com/Stichoza/google-translate-php", + "keywords": [ + "google", + "php", + "translate", + "translating", + "translator" + ], + "support": { + "issues": "https://github.com/Stichoza/google-translate-php/issues", + "source": "https://github.com/Stichoza/google-translate-php/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://btc.com/bc1qc25j4x7yahghm8nnn6lypnw59nptylsw32nkfl", + "type": "custom" + }, + { + "url": "https://www.paypal.me/stichoza", + "type": "custom" + }, + { + "url": "https://ko-fi.com/stichoza", + "type": "ko_fi" + }, + { + "url": "https://liberapay.com/stichoza", + "type": "liberapay" + }, + { + "url": "https://opencollective.com/stichoza", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/stichoza", + "type": "patreon" + } + ], + "time": "2025-05-20T08:38:25+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "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.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T10:34:04+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf68d225bc43629de4ff54778029aee6dc191b83", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-29T07:19:49+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "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.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-22T09:11:45+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", + "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.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-30T19:00:26+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "4236baf01609667d53b20371486228231eb135fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4236baf01609667d53b20371486228231eb135fd", + "reference": "4236baf01609667d53b20371486228231eb135fd", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "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": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-12T14:48:23+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "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 structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-29T07:47:32+00:00" + }, + { + "name": "symfony/mailer", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/0f375bbbde96ae8c78e4aa3e63aabd486e33364c", + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "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": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T09:51:09+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "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": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-19T08:51:26+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "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.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-17T09:11:12+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "8e213820c5fea844ecea29203d2a308019007c15" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", + "reference": "8e213820c5fea844ecea29203d2a308019007c15", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "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": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T20:43:28+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "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": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "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.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", + "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.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-20T20:19:01+00:00" + }, + { + "name": "symfony/translation", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/4aba29076a29a3aa667e09b791e5f868973a8667", + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-29T07:19:49+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.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-27T08:32:26+00:00" + }, + { + "name": "symfony/uid", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/7beeb2b885cd584cd01e126c5777206ae4c3c6a3", + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T14:28:13+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/548f6760c54197b1084e1e5c71f6d9d523f2f78e", + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-27T18:39:23+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c9a1168891b5aaadfd6332ef44393330b3498c4c", + "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "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": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-15T09:04:05+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "cea40a48279d58dc3efee8112634cb90141156c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/cea40a48279d58dc3efee8112634cb90141156c2", + "reference": "cea40a48279d58dc3efee8112634cb90141156c2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "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.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T10:10:33+00:00" + }, + { + "name": "tightenco/ziggy", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/tighten/ziggy.git", + "reference": "0b3b521d2c55fbdb04b6721532f7f5f49d32f52b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tighten/ziggy/zipball/0b3b521d2c55fbdb04b6721532f7f5f49d32f52b", + "reference": "0b3b521d2c55fbdb04b6721532f7f5f49d32f52b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": ">=9.0", + "php": ">=8.1" + }, + "require-dev": { + "laravel/folio": "^1.1", + "orchestra/testbench": "^7.0 || ^8.0 || ^9.0 || ^10.0", + "pestphp/pest": "^2.26|^3.0", + "pestphp/pest-plugin-laravel": "^2.4|^3.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Tighten\\Ziggy\\ZiggyServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Tighten\\Ziggy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Coulbourne", + "email": "daniel@tighten.co" + }, + { + "name": "Jake Bathman", + "email": "jake@tighten.co" + }, + { + "name": "Jacob Baker-Kretzmar", + "email": "jacob@tighten.co" + } + ], + "description": "Use your Laravel named routes in JavaScript.", + "homepage": "https://github.com/tighten/ziggy", + "keywords": [ + "Ziggy", + "javascript", + "laravel", + "routes" + ], + "support": { + "issues": "https://github.com/tighten/ziggy/issues", + "source": "https://github.com/tighten/ziggy/tree/v2.5.3" + }, + "time": "2025-05-17T18:15:19+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + }, + "time": "2024-12-21T16:25:41+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.2", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-04-30T23:37:27+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/pint": "^1.13", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", + "phpstan/phpstan": "^1.12.27", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "dev", + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2025-06-05T13:55:57+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "941d1927c5ca420c22710e98420287169c7bcaf7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/941d1927c5ca420c22710e98420287169c7bcaf7", + "reference": "941d1927c5ca420c22710e98420287169c7bcaf7", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.75.0", + "illuminate/view": "^11.44.7", + "larastan/larastan": "^3.4.0", + "laravel-zero/framework": "^11.36.1", + "mockery/mockery": "^1.6.12", + "nunomaduro/termwind": "^2.3.1", + "pestphp/pest": "^2.36.0" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2025-05-08T08:38:12+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.43.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/3e7d899232a8c5e3ea4fc6dee7525ad583887e72", + "reference": "3e7d899232a8c5e3ea4fc6dee7525ad583887e72", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2025-05-19T13:19:21+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-04-29T12:36:36+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": "phpunit/php-code-coverage", + "version": "11.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7", + "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "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.5.2" + }, + "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.9" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-25T13:26:39+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.5.22", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "4cd72faaa8f811e4cc63040cba167757660a5538" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4cd72faaa8f811e4cc63040cba167757660a5538", + "reference": "4cd72faaa8f811e4cc63040cba167757660a5538", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.9", + "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.3", + "sebastian/comparator": "^6.3.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.2", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-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.5.22" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-06-06T02:48:05+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.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "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.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+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.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-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.3.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-07T06:57:01+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.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "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.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-05-21T11:55:47+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^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": "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.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-05T09:17:50+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.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "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.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-18T13:35:50+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": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+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": true, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/config/activitylog.php b/config/activitylog.php new file mode 100644 index 00000000..f1262f54 --- /dev/null +++ b/config/activitylog.php @@ -0,0 +1,52 @@ + env('ACTIVITY_LOGGER_ENABLED', true), + + /* + * When the clean-command is executed, all recording activities older than + * the number of days specified here will be deleted. + */ + 'delete_records_older_than_days' => 365, + + /* + * If no log name is passed to the activity() helper + * we use this default log name. + */ + 'default_log_name' => 'default', + + /* + * You can specify an auth driver here that gets user models. + * If this is null we'll use the current Laravel auth driver. + */ + 'default_auth_driver' => null, + + /* + * If set to true, the subject returns soft deleted models. + */ + 'subject_returns_soft_deleted_models' => false, + + /* + * This model will be used to log activity. + * It should implement the Spatie\Activitylog\Contracts\Activity interface + * and extend Illuminate\Database\Eloquent\Model. + */ + 'activity_model' => \Spatie\Activitylog\Models\Activity::class, + + /* + * This is the name of the table that will be created by the migration and + * used by the Activity model shipped with this package. + */ + 'table_name' => env('ACTIVITY_LOGGER_TABLE_NAME', 'activity_log'), + + /* + * This is the database connection that will be used by the migration and + * the Activity model shipped with this package. In case it's not set + * Laravel's database.default will be used instead. + */ + 'database_connection' => env('ACTIVITY_LOGGER_DB_CONNECTION'), +]; diff --git a/config/app.php b/config/app.php index 324b513a..73934680 100644 --- a/config/app.php +++ b/config/app.php @@ -123,4 +123,66 @@ 'store' => env('APP_MAINTENANCE_STORE', 'database'), ], + /* + |-------------------------------------------------------------------------- + | Supported Locales + |-------------------------------------------------------------------------- + | + | This option controls the supported locales for your application. + | You may add any of the locales that your application should support. + | + */ + + 'supported_locales' => ['en', 'pt_BR', 'es', 'de', 'it', 'fr'], + 'keep_deleted_backup' => env('APP_KEEP_DELETED_BACKUP', false), + + /* + |-------------------------------------------------------------------------- + | Application Configuration + |-------------------------------------------------------------------------- + | + | This option controls the configuration of your application. + | You may add any of the configurations that your application should support. + | + */ + + 'config' => [ + 'image_file' => [ + 'supported_images' => [ + 'jpg', + 'jpeg', + 'png', + 'svg', + 'ifc', + 'dwg', + 'dxf' + ], + 'supported_videos' => [ + 'mp4', + 'mov', + 'avi', + 'wmv', + 'mkv', + 'webm' + ], + 'supported_files' => [ + 'txt', + 'xls', + 'pdf', + 'doc', + 'docx', + 'xlsx', + 'jpg', + 'jpeg', + 'png', + 'ifc', + 'dwg', + 'dxf', + 'pptx', + 'odt', + 'ods', + 'odp' + ], + ], + ], ]; diff --git a/config/broadcasting.php b/config/broadcasting.php new file mode 100644 index 00000000..ebc3fb9c --- /dev/null +++ b/config/broadcasting.php @@ -0,0 +1,82 @@ + env('BROADCAST_CONNECTION', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over WebSockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + + 'reverb' => [ + 'driver' => 'reverb', + 'key' => env('REVERB_APP_KEY'), + 'secret' => env('REVERB_APP_SECRET'), + 'app_id' => env('REVERB_APP_ID'), + 'options' => [ + 'host' => env('REVERB_HOST'), + 'port' => env('REVERB_PORT', 443), + 'scheme' => env('REVERB_SCHEME', 'https'), + 'useTLS' => env('REVERB_SCHEME', 'https') === 'https', + ], + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + ], + + 'pusher' => [ + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'secret' => env('PUSHER_APP_SECRET'), + 'app_id' => env('PUSHER_APP_ID'), + 'options' => [ + 'cluster' => env('PUSHER_APP_CLUSTER'), + 'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com', + 'port' => env('PUSHER_PORT', 443), + 'scheme' => env('PUSHER_SCHEME', 'https'), + 'encrypted' => true, + 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', + ], + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + ], + + 'ably' => [ + 'driver' => 'ably', + 'key' => env('ABLY_KEY'), + ], + + 'log' => [ + 'driver' => 'log', + ], + + 'null' => [ + 'driver' => 'null', + ], + + ], + +]; diff --git a/config/dompdf.php b/config/dompdf.php new file mode 100644 index 00000000..35eef8ff --- /dev/null +++ b/config/dompdf.php @@ -0,0 +1,301 @@ + false, // Throw an Exception on warnings from dompdf + + 'public_path' => null, // Override the public path if needed + + /* + * Dejavu Sans font is missing glyphs for converted entities, turn it off if you need to show € and £. + */ + 'convert_entities' => true, + + 'options' => [ + /** + * The location of the DOMPDF font directory + * + * The location of the directory where DOMPDF will store fonts and font metrics + * Note: This directory must exist and be writable by the webserver process. + * *Please note the trailing slash.* + * + * Notes regarding fonts: + * Additional .afm font metrics can be added by executing load_font.php from command line. + * + * Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must + * be embedded in the pdf file or the PDF may not display correctly. This can significantly + * increase file size unless font subsetting is enabled. Before embedding a font please + * review your rights under the font license. + * + * Any font specification in the source HTML is translated to the closest font available + * in the font directory. + * + * The pdf standard "Base 14 fonts" are: + * Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique, + * Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique, + * Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic, + * Symbol, ZapfDingbats. + */ + 'font_dir' => storage_path('fonts'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782) + + /** + * The location of the DOMPDF font cache directory + * + * This directory contains the cached font metrics for the fonts used by DOMPDF. + * This directory can be the same as DOMPDF_FONT_DIR + * + * Note: This directory must exist and be writable by the webserver process. + */ + 'font_cache' => storage_path('fonts'), + + /** + * The location of a temporary directory. + * + * The directory specified must be writeable by the webserver process. + * The temporary directory is required to download remote images and when + * using the PDFLib back end. + */ + 'temp_dir' => sys_get_temp_dir(), + + /** + * ==== IMPORTANT ==== + * + * dompdf's "chroot": Prevents dompdf from accessing system files or other + * files on the webserver. All local files opened by dompdf must be in a + * subdirectory of this directory. DO NOT set it to '/' since this could + * allow an attacker to use dompdf to read any files on the server. This + * should be an absolute path. + * This is only checked on command line call by dompdf.php, but not by + * direct class use like: + * $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output(); + */ + 'chroot' => realpath(base_path()), + + /** + * Protocol whitelist + * + * Protocols and PHP wrappers allowed in URIs, and the validation rules + * that determine if a resouce may be loaded. Full support is not guaranteed + * for the protocols/wrappers specified + * by this array. + * + * @var array + */ + 'allowed_protocols' => [ + 'data://' => ['rules' => []], + 'file://' => ['rules' => []], + 'http://' => ['rules' => []], + 'https://' => ['rules' => []], + ], + + /** + * Operational artifact (log files, temporary files) path validation + */ + 'artifactPathValidation' => null, + + /** + * @var string + */ + 'log_output_file' => null, + + /** + * Whether to enable font subsetting or not. + */ + 'enable_font_subsetting' => false, + + /** + * The PDF rendering backend to use + * + * Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and + * 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will + * fall back on CPDF. 'GD' renders PDFs to graphic files. + * {@link * Canvas_Factory} ultimately determines which rendering class to + * instantiate based on this setting. + * + * Both PDFLib & CPDF rendering backends provide sufficient rendering + * capabilities for dompdf, however additional features (e.g. object, + * image and font support, etc.) differ between backends. Please see + * {@link PDFLib_Adapter} for more information on the PDFLib backend + * and {@link CPDF_Adapter} and lib/class.pdf.php for more information + * on CPDF. Also see the documentation for each backend at the links + * below. + * + * The GD rendering backend is a little different than PDFLib and + * CPDF. Several features of CPDF and PDFLib are not supported or do + * not make any sense when creating image files. For example, + * multiple pages are not supported, nor are PDF 'objects'. Have a + * look at {@link GD_Adapter} for more information. GD support is + * experimental, so use it at your own risk. + * + * @link http://www.pdflib.com + * @link http://www.ros.co.nz/pdf + * @link http://www.php.net/image + */ + 'pdf_backend' => 'CPDF', + + /** + * html target media view which should be rendered into pdf. + * List of types and parsing rules for future extensions: + * http://www.w3.org/TR/REC-html40/types.html + * screen, tty, tv, projection, handheld, print, braille, aural, all + * Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3. + * Note, even though the generated pdf file is intended for print output, + * the desired content might be different (e.g. screen or projection view of html file). + * Therefore allow specification of content here. + */ + 'default_media_type' => 'screen', + + /** + * The default paper size. + * + * North America standard is "letter"; other countries generally "a4" + * + * @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.) + */ + 'default_paper_size' => 'a4', + + /** + * The default paper orientation. + * + * The orientation of the page (portrait or landscape). + * + * @var string + */ + 'default_paper_orientation' => 'portrait', + + /** + * The default font family + * + * Used if no suitable fonts can be found. This must exist in the font folder. + * + * @var string + */ + 'default_font' => 'serif', + + /** + * Image DPI setting + * + * This setting determines the default DPI setting for images and fonts. The + * DPI may be overridden for inline images by explictly setting the + * image's width & height style attributes (i.e. if the image's native + * width is 600 pixels and you specify the image's width as 72 points, + * the image will have a DPI of 600 in the rendered PDF. The DPI of + * background images can not be overridden and is controlled entirely + * via this parameter. + * + * For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI). + * If a size in html is given as px (or without unit as image size), + * this tells the corresponding size in pt. + * This adjusts the relative sizes to be similar to the rendering of the + * html page in a reference browser. + * + * In pdf, always 1 pt = 1/72 inch + * + * Rendering resolution of various browsers in px per inch: + * Windows Firefox and Internet Explorer: + * SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:? + * Linux Firefox: + * about:config *resolution: Default:96 + * (xorg screen dimension in mm and Desktop font dpi settings are ignored) + * + * Take care about extra font/image zoom factor of browser. + * + * In images, size in pixel attribute, img css style, are overriding + * the real image dimension in px for rendering. + * + * @var int + */ + 'dpi' => 96, + + /** + * Enable embedded PHP + * + * If this setting is set to true then DOMPDF will automatically evaluate embedded PHP contained + * within tags. + * + * ==== IMPORTANT ==== Enabling this for documents you do not trust (e.g. arbitrary remote html pages) + * is a security risk. + * Embedded scripts are run with the same level of system access available to dompdf. + * Set this option to false (recommended) if you wish to process untrusted documents. + * This setting may increase the risk of system exploit. + * Do not change this settings without understanding the consequences. + * Additional documentation is available on the dompdf wiki at: + * https://github.com/dompdf/dompdf/wiki + * + * @var bool + */ + 'enable_php' => false, + + /** + * Rnable inline JavaScript + * + * If this setting is set to true then DOMPDF will automatically insert JavaScript code contained + * within tags as written into the PDF. + * NOTE: This is PDF-based JavaScript to be executed by the PDF viewer, + * not browser-based JavaScript executed by Dompdf. + * + * @var bool + */ + 'enable_javascript' => true, + + /** + * Enable remote file access + * + * If this setting is set to true, DOMPDF will access remote sites for + * images and CSS files as required. + * + * ==== IMPORTANT ==== + * This can be a security risk, in particular in combination with isPhpEnabled and + * allowing remote html code to be passed to $dompdf = new DOMPDF(); $dompdf->load_html(...); + * This allows anonymous users to download legally doubtful internet content which on + * tracing back appears to being downloaded by your server, or allows malicious php code + * in remote html pages to be executed by your server with your account privileges. + * + * This setting may increase the risk of system exploit. Do not change + * this settings without understanding the consequences. Additional + * documentation is available on the dompdf wiki at: + * https://github.com/dompdf/dompdf/wiki + * + * @var bool + */ + 'enable_remote' => false, + + /** + * List of allowed remote hosts + * + * Each value of the array must be a valid hostname. + * + * This will be used to filter which resources can be loaded in combination with + * isRemoteEnabled. If enable_remote is FALSE, then this will have no effect. + * + * Leave to NULL to allow any remote host. + * + * @var array|null + */ + 'allowed_remote_hosts' => null, + + /** + * A ratio applied to the fonts height to be more like browsers' line height + */ + 'font_height_ratio' => 1.1, + + /** + * Use the HTML5 Lib parser + * + * @deprecated This feature is now always on in dompdf 2.x + * + * @var bool + */ + 'enable_html5_parser' => true, + ], + +]; diff --git a/config/excel.php b/config/excel.php new file mode 100644 index 00000000..c1fd34a6 --- /dev/null +++ b/config/excel.php @@ -0,0 +1,380 @@ + [ + + /* + |-------------------------------------------------------------------------- + | Chunk size + |-------------------------------------------------------------------------- + | + | When using FromQuery, the query is automatically chunked. + | Here you can specify how big the chunk should be. + | + */ + 'chunk_size' => 1000, + + /* + |-------------------------------------------------------------------------- + | Pre-calculate formulas during export + |-------------------------------------------------------------------------- + */ + 'pre_calculate_formulas' => false, + + /* + |-------------------------------------------------------------------------- + | Enable strict null comparison + |-------------------------------------------------------------------------- + | + | When enabling strict null comparison empty cells ('') will + | be added to the sheet. + */ + 'strict_null_comparison' => false, + + /* + |-------------------------------------------------------------------------- + | CSV Settings + |-------------------------------------------------------------------------- + | + | Configure e.g. delimiter, enclosure and line ending for CSV exports. + | + */ + 'csv' => [ + 'delimiter' => ',', + 'enclosure' => '"', + 'line_ending' => PHP_EOL, + 'use_bom' => false, + 'include_separator_line' => false, + 'excel_compatibility' => false, + 'output_encoding' => '', + 'test_auto_detect' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Worksheet properties + |-------------------------------------------------------------------------- + | + | Configure e.g. default title, creator, subject,... + | + */ + 'properties' => [ + 'creator' => '', + 'lastModifiedBy' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', + ], + ], + + 'imports' => [ + + /* + |-------------------------------------------------------------------------- + | Read Only + |-------------------------------------------------------------------------- + | + | When dealing with imports, you might only be interested in the + | data that the sheet exists. By default we ignore all styles, + | however if you want to do some logic based on style data + | you can enable it by setting read_only to false. + | + */ + 'read_only' => true, + + /* + |-------------------------------------------------------------------------- + | Ignore Empty + |-------------------------------------------------------------------------- + | + | When dealing with imports, you might be interested in ignoring + | rows that have null values or empty strings. By default rows + | containing empty strings or empty values are not ignored but can be + | ignored by enabling the setting ignore_empty to true. + | + */ + 'ignore_empty' => false, + + /* + |-------------------------------------------------------------------------- + | Heading Row Formatter + |-------------------------------------------------------------------------- + | + | Configure the heading row formatter. + | Available options: none|slug|custom + | + */ + 'heading_row' => [ + 'formatter' => 'slug', + ], + + /* + |-------------------------------------------------------------------------- + | CSV Settings + |-------------------------------------------------------------------------- + | + | Configure e.g. delimiter, enclosure and line ending for CSV imports. + | + */ + 'csv' => [ + 'delimiter' => null, + 'enclosure' => '"', + 'escape_character' => '\\', + 'contiguous' => false, + 'input_encoding' => Csv::GUESS_ENCODING, + ], + + /* + |-------------------------------------------------------------------------- + | Worksheet properties + |-------------------------------------------------------------------------- + | + | Configure e.g. default title, creator, subject,... + | + */ + 'properties' => [ + 'creator' => '', + 'lastModifiedBy' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', + ], + + /* + |-------------------------------------------------------------------------- + | Cell Middleware + |-------------------------------------------------------------------------- + | + | Configure middleware that is executed on getting a cell value + | + */ + 'cells' => [ + 'middleware' => [ + //\Maatwebsite\Excel\Middleware\TrimCellValue::class, + //\Maatwebsite\Excel\Middleware\ConvertEmptyCellValuesToNull::class, + ], + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Extension detector + |-------------------------------------------------------------------------- + | + | Configure here which writer/reader type should be used when the package + | needs to guess the correct type based on the extension alone. + | + */ + 'extension_detector' => [ + 'xlsx' => Excel::XLSX, + 'xlsm' => Excel::XLSX, + 'xltx' => Excel::XLSX, + 'xltm' => Excel::XLSX, + 'xls' => Excel::XLS, + 'xlt' => Excel::XLS, + 'ods' => Excel::ODS, + 'ots' => Excel::ODS, + 'slk' => Excel::SLK, + 'xml' => Excel::XML, + 'gnumeric' => Excel::GNUMERIC, + 'htm' => Excel::HTML, + 'html' => Excel::HTML, + 'csv' => Excel::CSV, + 'tsv' => Excel::TSV, + + /* + |-------------------------------------------------------------------------- + | PDF Extension + |-------------------------------------------------------------------------- + | + | Configure here which Pdf driver should be used by default. + | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF + | + */ + 'pdf' => Excel::DOMPDF, + ], + + /* + |-------------------------------------------------------------------------- + | Value Binder + |-------------------------------------------------------------------------- + | + | PhpSpreadsheet offers a way to hook into the process of a value being + | written to a cell. In there some assumptions are made on how the + | value should be formatted. If you want to change those defaults, + | you can implement your own default value binder. + | + | Possible value binders: + | + | [x] Maatwebsite\Excel\DefaultValueBinder::class + | [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class + | [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class + | + */ + 'value_binder' => [ + 'default' => Maatwebsite\Excel\DefaultValueBinder::class, + ], + + 'cache' => [ + /* + |-------------------------------------------------------------------------- + | Default cell caching driver + |-------------------------------------------------------------------------- + | + | By default PhpSpreadsheet keeps all cell values in memory, however when + | dealing with large files, this might result into memory issues. If you + | want to mitigate that, you can configure a cell caching driver here. + | When using the illuminate driver, it will store each value in the + | cache store. This can slow down the process, because it needs to + | store each value. You can use the "batch" store if you want to + | only persist to the store when the memory limit is reached. + | + | Drivers: memory|illuminate|batch + | + */ + 'driver' => 'memory', + + /* + |-------------------------------------------------------------------------- + | Batch memory caching + |-------------------------------------------------------------------------- + | + | When dealing with the "batch" caching driver, it will only + | persist to the store when the memory limit is reached. + | Here you can tweak the memory limit to your liking. + | + */ + 'batch' => [ + 'memory_limit' => 60000, + ], + + /* + |-------------------------------------------------------------------------- + | Illuminate cache + |-------------------------------------------------------------------------- + | + | When using the "illuminate" caching driver, it will automatically use + | your default cache store. However if you prefer to have the cell + | cache on a separate store, you can configure the store name here. + | You can use any store defined in your cache config. When leaving + | at "null" it will use the default store. + | + */ + 'illuminate' => [ + 'store' => null, + ], + + /* + |-------------------------------------------------------------------------- + | Cache Time-to-live (TTL) + |-------------------------------------------------------------------------- + | + | The TTL of items written to cache. If you want to keep the items cached + | indefinitely, set this to null. Otherwise, set a number of seconds, + | a \DateInterval, or a callable. + | + | Allowable types: callable|\DateInterval|int|null + | + */ + 'default_ttl' => 10800, + ], + + /* + |-------------------------------------------------------------------------- + | Transaction Handler + |-------------------------------------------------------------------------- + | + | By default the import is wrapped in a transaction. This is useful + | for when an import may fail and you want to retry it. With the + | transactions, the previous import gets rolled-back. + | + | You can disable the transaction handler by setting this to null. + | Or you can choose a custom made transaction handler here. + | + | Supported handlers: null|db + | + */ + 'transactions' => [ + 'handler' => 'db', + 'db' => [ + 'connection' => null, + ], + ], + + 'temporary_files' => [ + + /* + |-------------------------------------------------------------------------- + | Local Temporary Path + |-------------------------------------------------------------------------- + | + | When exporting and importing files, we use a temporary file, before + | storing reading or downloading. Here you can customize that path. + | permissions is an array with the permission flags for the directory (dir) + | and the create file (file). + | + */ + 'local_path' => storage_path('framework/cache/laravel-excel'), + + /* + |-------------------------------------------------------------------------- + | Local Temporary Path Permissions + |-------------------------------------------------------------------------- + | + | Permissions is an array with the permission flags for the directory (dir) + | and the create file (file). + | If omitted the default permissions of the filesystem will be used. + | + */ + 'local_permissions' => [ + // 'dir' => 0755, + // 'file' => 0644, + ], + + /* + |-------------------------------------------------------------------------- + | Remote Temporary Disk + |-------------------------------------------------------------------------- + | + | When dealing with a multi server setup with queues in which you + | cannot rely on having a shared local temporary path, you might + | want to store the temporary file on a shared disk. During the + | queue executing, we'll retrieve the temporary file from that + | location instead. When left to null, it will always use + | the local path. This setting only has effect when using + | in conjunction with queued imports and exports. + | + */ + 'remote_disk' => null, + 'remote_prefix' => null, + + /* + |-------------------------------------------------------------------------- + | Force Resync + |-------------------------------------------------------------------------- + | + | When dealing with a multi server setup as above, it's possible + | for the clean up that occurs after entire queue has been run to only + | cleanup the server that the last AfterImportJob runs on. The rest of the server + | would still have the local temporary file stored on it. In this case your + | local storage limits can be exceeded and future imports won't be processed. + | To mitigate this you can set this config value to be true, so that after every + | queued chunk is processed the local temporary file is deleted on the server that + | processed it. + | + */ + 'force_resync_remote' => null, + ], +]; diff --git a/config/image-file.php b/config/image-file.php new file mode 100644 index 00000000..c0afc595 --- /dev/null +++ b/config/image-file.php @@ -0,0 +1,59 @@ + [ + 'jpg', + 'jpeg', + 'png', + 'svg', + 'ifc', + 'dwg', + 'dxf' + ], + 'supported_videos' => [ + 'mp4', + 'mov', + 'avi', + 'wmv', + 'mkv', + 'webm' + ], + /* + |-------------------------------------------------------------------------- + | Supported Files + |-------------------------------------------------------------------------- + | + | This option controls the supported files for your application. + | You may add any of the files that your application should support. + | + */ + + 'supported_files' => [ + 'txt', + 'xls', + 'pdf', + 'doc', + 'docx', + 'xlsx', + 'jpg', + 'jpeg', + 'png', + 'ifc', + 'dwg', + 'dxf', + 'pptx', + 'odt', + 'ods', + 'odp' + ], +]; diff --git a/config/json-api-paginate.php b/config/json-api-paginate.php new file mode 100644 index 00000000..fb8d6566 --- /dev/null +++ b/config/json-api-paginate.php @@ -0,0 +1,64 @@ + 30, + + /* + * The default number of results that will be returned + * when using the JSON API paginator. + */ + 'default_size' => 30, + + /* + * The key of the page[x] query string parameter for page number. + */ + 'number_parameter' => 'number', + + /* + * The key of the page[x] query string parameter for page size. + */ + 'size_parameter' => 'size', + + /* + * The key of the page[x] query string parameter for cursor. + */ + 'cursor_parameter' => 'cursor', + + /* + * The name of the macro that is added to the Eloquent query builder. + */ + 'method_name' => 'jsonPaginate', + + /* + * If you only need to display Next and Previous links, you may use + * simple pagination to perform a more efficient query. + */ + 'use_simple_pagination' => false, + + /* + * If you want to use cursor pagination, set this to true. + * This would override use_simple_pagination. + */ + 'use_cursor_pagination' => false, + + /* + * use simpleFastPaginate() or fastPaginate from https://github.com/aarondfrancis/fast-paginate + * use may installed it via `composer require aaronfrancis/fast-paginate` + */ + 'use_fast_pagination' => false, + + /* + * Here you can override the base url to be used in the link items. + */ + 'base_url' => null, + + /* + * The name of the query parameter used for pagination + */ + 'pagination_parameter' => 'page', +]; diff --git a/config/permission.php b/config/permission.php new file mode 100644 index 00000000..f39f6b5b --- /dev/null +++ b/config/permission.php @@ -0,0 +1,202 @@ + [ + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * Eloquent model should be used to retrieve your permissions. Of course, it + * is often just the "Permission" model but you may use whatever you like. + * + * The model you want to use as a Permission model needs to implement the + * `Spatie\Permission\Contracts\Permission` contract. + */ + + 'permission' => Spatie\Permission\Models\Permission::class, + + /* + * When using the "HasRoles" trait from this package, we need to know which + * Eloquent model should be used to retrieve your roles. Of course, it + * is often just the "Role" model but you may use whatever you like. + * + * The model you want to use as a Role model needs to implement the + * `Spatie\Permission\Contracts\Role` contract. + */ + + 'role' => Spatie\Permission\Models\Role::class, + + ], + + 'table_names' => [ + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your roles. We have chosen a basic + * default value but you may easily change it to any table you like. + */ + + 'roles' => 'roles', + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * table should be used to retrieve your permissions. We have chosen a basic + * default value but you may easily change it to any table you like. + */ + + 'permissions' => 'permissions', + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * table should be used to retrieve your models permissions. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'model_has_permissions' => 'model_has_permissions', + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your models roles. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'model_has_roles' => 'model_has_roles', + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your roles permissions. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'role_has_permissions' => 'role_has_permissions', + ], + + 'column_names' => [ + /* + * Change this if you want to name the related pivots other than defaults + */ + 'role_pivot_key' => null, // default 'role_id', + 'permission_pivot_key' => null, // default 'permission_id', + + /* + * Change this if you want to name the related model primary key other than + * `model_id`. + * + * For example, this would be nice if your primary keys are all UUIDs. In + * that case, name this `model_uuid`. + */ + + 'model_morph_key' => 'model_id', + + /* + * Change this if you want to use the teams feature and your related model's + * foreign key is other than `team_id`. + */ + + 'team_foreign_key' => 'team_id', + ], + + /* + * When set to true, the method for checking permissions will be registered on the gate. + * Set this to false if you want to implement custom logic for checking permissions. + */ + + 'register_permission_check_method' => true, + + /* + * When set to true, Laravel\Octane\Events\OperationTerminated event listener will be registered + * this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated + * NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it. + */ + 'register_octane_reset_listener' => false, + + /* + * Events will fire when a role or permission is assigned/unassigned: + * \Spatie\Permission\Events\RoleAttached + * \Spatie\Permission\Events\RoleDetached + * \Spatie\Permission\Events\PermissionAttached + * \Spatie\Permission\Events\PermissionDetached + * + * To enable, set to true, and then create listeners to watch these events. + */ + 'events_enabled' => false, + + /* + * Teams Feature. + * When set to true the package implements teams using the 'team_foreign_key'. + * If you want the migrations to register the 'team_foreign_key', you must + * set this to true before doing the migration. + * If you already did the migration then you must make a new migration to also + * add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions' + * (view the latest version of this package's migration file) + */ + + 'teams' => false, + + /* + * The class to use to resolve the permissions team id + */ + 'team_resolver' => \Spatie\Permission\DefaultTeamResolver::class, + + /* + * Passport Client Credentials Grant + * When set to true the package will use Passports Client to check permissions + */ + + 'use_passport_client_credentials' => false, + + /* + * When set to true, the required permission names are added to exception messages. + * This could be considered an information leak in some contexts, so the default + * setting is false here for optimum safety. + */ + + 'display_permission_in_exception' => false, + + /* + * When set to true, the required role names are added to exception messages. + * This could be considered an information leak in some contexts, so the default + * setting is false here for optimum safety. + */ + + 'display_role_in_exception' => false, + + /* + * By default wildcard permission lookups are disabled. + * See documentation to understand supported syntax. + */ + + 'enable_wildcard_permission' => false, + + /* + * The class to use for interpreting wildcard permissions. + * If you need to modify delimiters, override the class and specify its name here. + */ + // 'wildcard_permission' => Spatie\Permission\WildcardPermission::class, + + /* Cache-specific settings */ + + 'cache' => [ + + /* + * By default all permissions are cached for 24 hours to speed up performance. + * When permissions or roles are updated the cache is flushed automatically. + */ + + 'expiration_time' => \DateInterval::createFromDateString('24 hours'), + + /* + * The cache key used to store all permissions. + */ + + 'key' => 'spatie.permission.cache', + + /* + * You may optionally indicate a specific cache driver to use for permission and + * role caching using any of the `store` drivers listed in the cache.php config + * file. Using 'default' here means to use the `default` set in cache.php. + */ + + 'store' => 'default', + ], +]; diff --git a/config/query-builder.php b/config/query-builder.php new file mode 100644 index 00000000..94fca196 --- /dev/null +++ b/config/query-builder.php @@ -0,0 +1,82 @@ + [ + 'include' => 'include', + + 'filter' => 'filter', + + 'sort' => 'sort', + + 'fields' => 'fields', + + 'append' => 'append', + ], + + /* + * Related model counts are included using the relationship name suffixed with this string. + * For example: GET /users?include=postsCount + */ + 'count_suffix' => 'Count', + + /* + * Related model exists are included using the relationship name suffixed with this string. + * For example: GET /users?include=postsExists + */ + 'exists_suffix' => 'Exists', + + /* + * By default the package will throw an `InvalidFilterQuery` exception when a filter in the + * URL is not allowed in the `allowedFilters()` method. + */ + 'disable_invalid_filter_query_exception' => false, + + /* + * By default the package will throw an `InvalidSortQuery` exception when a sort in the + * URL is not allowed in the `allowedSorts()` method. + */ + 'disable_invalid_sort_query_exception' => false, + + /* + * By default the package will throw an `InvalidIncludeQuery` exception when an include in the + * URL is not allowed in the `allowedIncludes()` method. + */ + 'disable_invalid_includes_query_exception' => false, + + /* + * By default, the package expects relationship names to be snake case plural when using fields[relationship]. + * For example, fetching the id and name for a userOwner relation would look like this: + * GET /users?fields[user_owner]=id,name + * + * Set this to `false` if you don't want that and keep the requested relationship names as-is and allows you to + * request the fields using a camelCase relationship name: + * GET /users?fields[userOwner]=id,name + */ + 'convert_relation_names_to_snake_case_plural' => true, + + /* + * By default, the package expects relationship names to be snake case plural when using fields[relationship]. + * For example, fetching the id and name for a userOwner relation would look like this: + * GET /users?fields[user_owner]=id,name + * + * Set this to one of `snake_case`, `camelCase` or `none` if you want to enable table name resolution in addition to the relation name resolution + * GET /users?include=topOrders&fields[orders]=id,name + */ + 'convert_relation_table_name_strategy' => false, + + /* + * By default, the package expects the field names to match the database names + * For example, fetching the field named firstName would look like this: + * GET /users?fields=firstName + * + * Set this to `true` if you want to convert the firstName into first_name for the underlying query + */ + 'convert_field_names_to_snake_case' => false, +]; diff --git a/config/reverb.php b/config/reverb.php new file mode 100644 index 00000000..bec46d4c --- /dev/null +++ b/config/reverb.php @@ -0,0 +1,94 @@ + env('REVERB_SERVER', 'reverb'), + + /* + |-------------------------------------------------------------------------- + | Reverb Servers + |-------------------------------------------------------------------------- + | + | Here you may define details for each of the supported Reverb servers. + | Each server has its own configuration options that are defined in + | the array below. You should ensure all the options are present. + | + */ + + 'servers' => [ + + 'reverb' => [ + 'host' => env('REVERB_SERVER_HOST', '0.0.0.0'), + 'port' => env('REVERB_SERVER_PORT', 8080), + 'path' => env('REVERB_SERVER_PATH', ''), + 'hostname' => env('REVERB_HOST'), + 'options' => [ + 'tls' => [], + ], + 'max_request_size' => env('REVERB_MAX_REQUEST_SIZE', 10_000), + 'scaling' => [ + 'enabled' => env('REVERB_SCALING_ENABLED', false), + 'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'), + 'server' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'port' => env('REDIS_PORT', '6379'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'database' => env('REDIS_DB', '0'), + 'timeout' => env('REDIS_TIMEOUT', 60), + ], + ], + 'pulse_ingest_interval' => env('REVERB_PULSE_INGEST_INTERVAL', 15), + 'telescope_ingest_interval' => env('REVERB_TELESCOPE_INGEST_INTERVAL', 15), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Reverb Applications + |-------------------------------------------------------------------------- + | + | Here you may define how Reverb applications are managed. If you choose + | to use the "config" provider, you may define an array of apps which + | your server will support, including their connection credentials. + | + */ + + 'apps' => [ + + 'provider' => 'config', + + 'apps' => [ + [ + 'key' => env('REVERB_APP_KEY'), + 'secret' => env('REVERB_APP_SECRET'), + 'app_id' => env('REVERB_APP_ID'), + 'options' => [ + 'host' => env('REVERB_HOST'), + 'port' => env('REVERB_PORT', 443), + 'scheme' => env('REVERB_SCHEME', 'https'), + 'useTLS' => env('REVERB_SCHEME', 'https') === 'https', + ], + 'allowed_origins' => ['*'], + 'ping_interval' => env('REVERB_APP_PING_INTERVAL', 60), + 'activity_timeout' => env('REVERB_APP_ACTIVITY_TIMEOUT', 30), + 'max_message_size' => env('REVERB_APP_MAX_MESSAGE_SIZE', 10_000), + ], + ], + + ], + +]; diff --git a/config/sanctum.php b/config/sanctum.php new file mode 100644 index 00000000..44527d68 --- /dev/null +++ b/config/sanctum.php @@ -0,0 +1,84 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort(), + // Sanctum::currentRequestHost(), + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. This will override any values set in the token's + | "expires_at" attribute, but first-party sessions are not affected. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Token Prefix + |-------------------------------------------------------------------------- + | + | Sanctum can prefix new tokens in order to take advantage of numerous + | security scanning initiatives maintained by open source platforms + | that notify developers if they commit tokens into repositories. + | + | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning + | + */ + + 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, + 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, + 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, + ], + +]; diff --git a/config/scribe.php b/config/scribe.php new file mode 100644 index 00000000..b7d517ca --- /dev/null +++ b/config/scribe.php @@ -0,0 +1,252 @@ + for the generated documentation. + 'title' => config('app.name').' API Documentation', + + // A short description of your API. Will be included in the docs webpage, Postman collection and OpenAPI spec. + 'description' => '', + + // The base URL displayed in the docs. + // If you're using `laravel` type, you can set this to a dynamic string, like '{{ config("app.tenant_url") }}' to get a dynamic base URL. + 'base_url' => config("app.url"), + + // Routes to include in the docs + 'routes' => [ + [ + 'match' => [ + // Match only routes whose paths match this pattern (use * as a wildcard to match any characters). Example: 'users/*'. + 'prefixes' => ['api/*'], + + // Match only routes whose domains match this pattern (use * as a wildcard to match any characters). Example: 'api.*'. + 'domains' => ['*'], + ], + + // Include these routes even if they did not match the rules above. + 'include' => [ + // 'users.index', 'POST /new', '/auth/*' + ], + + // Exclude these routes even if they matched the rules above. + 'exclude' => [ + // 'GET /health', 'admin.*' + ], + ], + ], + + // The type of documentation output to generate. + // - "static" will generate a static HTMl page in the /public/docs folder, + // - "laravel" will generate the documentation as a Blade view, so you can add routing and authentication. + // - "external_static" and "external_laravel" do the same as above, but pass the OpenAPI spec as a URL to an external UI template + 'type' => 'laravel', + + // See https://scribe.knuckles.wtf/laravel/reference/config#theme for supported options + 'theme' => 'default', + + 'static' => [ + // HTML documentation, assets and Postman collection will be generated to this folder. + // Source Markdown will still be in resources/docs. + 'output_path' => 'public/docs', + ], + + 'laravel' => [ + // Whether to automatically create a docs route for you to view your generated docs. You can still set up routing manually. + 'add_routes' => true, + + // URL path to use for the docs endpoint (if `add_routes` is true). + // By default, `/docs` opens the HTML page, `/docs.postman` opens the Postman collection, and `/docs.openapi` the OpenAPI spec. + 'docs_url' => '/docs', + + // Directory within `public` in which to store CSS and JS assets. + // By default, assets are stored in `public/vendor/scribe`. + // If set, assets will be stored in `public/{{assets_directory}}` + 'assets_directory' => null, + + // Middleware to attach to the docs endpoint (if `add_routes` is true). + 'middleware' => [], + ], + + 'external' => [ + 'html_attributes' => [] + ], + + 'try_it_out' => [ + // Add a Try It Out button to your endpoints so consumers can test endpoints right from their browser. + // Don't forget to enable CORS headers for your endpoints. + 'enabled' => true, + + // The base URL to use in the API tester. Leave as null to be the same as the displayed URL (`scribe.base_url`). + 'base_url' => null, + + // [Laravel Sanctum] Fetch a CSRF token before each request, and add it as an X-XSRF-TOKEN header. + 'use_csrf' => false, + + // The URL to fetch the CSRF token from (if `use_csrf` is true). + 'csrf_url' => '/sanctum/csrf-cookie', + ], + + // How is your API authenticated? This information will be used in the displayed docs, generated examples and response calls. + 'auth' => [ + // Set this to true if ANY endpoints in your API use authentication. + 'enabled' => false, + + // Set this to true if your API should be authenticated by default. If so, you must also set `enabled` (above) to true. + // You can then use @unauthenticated or @authenticated on individual endpoints to change their status from the default. + 'default' => false, + + // Where is the auth value meant to be sent in a request? + 'in' => AuthIn::BEARER->value, + + // The name of the auth parameter (e.g. token, key, apiKey) or header (e.g. Authorization, Api-Key). + 'name' => 'key', + + // The value of the parameter to be used by Scribe to authenticate response calls. + // This will NOT be included in the generated documentation. If empty, Scribe will use a random value. + 'use_value' => env('SCRIBE_AUTH_KEY'), + + // Placeholder your users will see for the auth parameter in the example requests. + // Set this to null if you want Scribe to use a random value as placeholder instead. + 'placeholder' => '{YOUR_AUTH_KEY}', + + // Any extra authentication-related info for your users. Markdown and HTML are supported. + 'extra_info' => 'You can retrieve your token by visiting your dashboard and clicking Generate API token.', + ], + + // Text to place in the "Introduction" section, right after the `description`. Markdown and HTML are supported. + 'intro_text' => <<As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile). + You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile). + INTRO, + + // Example requests for each endpoint will be shown in each of these languages. + // Supported options are: bash, javascript, php, python + // To add a language of your own, see https://scribe.knuckles.wtf/laravel/advanced/example-requests + // Note: does not work for `external` docs types + 'example_languages' => [ + 'bash', + 'javascript', + ], + + // Generate a Postman collection (v2.1.0) in addition to HTML docs. + // For 'static' docs, the collection will be generated to public/docs/collection.json. + // For 'laravel' docs, it will be generated to storage/app/scribe/collection.json. + // Setting `laravel.add_routes` to true (above) will also add a route for the collection. + 'postman' => [ + 'enabled' => true, + + 'overrides' => [ + // 'info.version' => '2.0.0', + ], + ], + + // Generate an OpenAPI spec (v3.0.1) in addition to docs webpage. + // For 'static' docs, the collection will be generated to public/docs/openapi.yaml. + // For 'laravel' docs, it will be generated to storage/app/scribe/openapi.yaml. + // Setting `laravel.add_routes` to true (above) will also add a route for the spec. + 'openapi' => [ + 'enabled' => true, + + 'overrides' => [ + // 'info.version' => '2.0.0', + ], + + // Additional generators to use when generating the OpenAPI spec. + // Should extend `Knuckles\Scribe\Writing\OpenApiSpecGenerators\OpenApiGenerator`. + 'generators' => [], + ], + + 'groups' => [ + // Endpoints which don't have a @group will be placed in this default group. + 'default' => 'Endpoints', + + // By default, Scribe will sort groups alphabetically, and endpoints in the order their routes are defined. + // You can override this by listing the groups, subgroups and endpoints here in the order you want them. + // See https://scribe.knuckles.wtf/blog/laravel-v4#easier-sorting and https://scribe.knuckles.wtf/laravel/reference/config#order for details + // Note: does not work for `external` docs types + 'order' => [], + ], + + // Custom logo path. This will be used as the value of the src attribute for the tag, + // so make sure it points to an accessible URL or path. Set to false to not use a logo. + // For example, if your logo is in public/img: + // - 'logo' => '../img/logo.png' // for `static` type (output folder is public/docs) + // - 'logo' => 'img/logo.png' // for `laravel` type + 'logo' => false, + + // Customize the "Last updated" value displayed in the docs by specifying tokens and formats. + // Examples: + // - {date:F j Y} => March 28, 2022 + // - {git:short} => Short hash of the last Git commit + // Available tokens are `{date:}` and `{git:}`. + // The format you pass to `date` will be passed to PHP's `date()` function. + // The format you pass to `git` can be either "short" or "long". + // Note: does not work for `external` docs types + 'last_updated' => 'Last updated: {date:F j, Y}', + + 'examples' => [ + // Set this to any number to generate the same example values for parameters on each run, + 'faker_seed' => 1234, + + // With API resources and transformers, Scribe tries to generate example models to use in your API responses. + // By default, Scribe will try the model's factory, and if that fails, try fetching the first from the database. + // You can reorder or remove strategies here. + 'models_source' => ['factoryCreate', 'factoryMake', 'databaseFirst'], + ], + + // The strategies Scribe will use to extract information about your routes at each stage. + // Use configureStrategy() to specify settings for a strategy in the list. + // Use removeStrategies() to remove an included strategy. + 'strategies' => [ + 'metadata' => [ + ...Defaults::METADATA_STRATEGIES, + ], + 'headers' => [ + ...Defaults::HEADERS_STRATEGIES, + Strategies\StaticData::withSettings(data: [ + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]), + ], + 'urlParameters' => [ + ...Defaults::URL_PARAMETERS_STRATEGIES, + ], + 'queryParameters' => [ + ...Defaults::QUERY_PARAMETERS_STRATEGIES, + ], + 'bodyParameters' => [ + ...Defaults::BODY_PARAMETERS_STRATEGIES, + ], + 'responses' => configureStrategy( + Defaults::RESPONSES_STRATEGIES, + Strategies\Responses\ResponseCalls::withSettings( + only: ['GET *'], + // Recommended: disable debug mode in response calls to avoid error stack traces in responses + config: [ + 'app.debug' => false, + ] + ) + ), + 'responseFields' => [ + ...Defaults::RESPONSE_FIELDS_STRATEGIES, + ] + ], + + // For response calls, API resource responses and transformer responses, + // Scribe will try to start database transactions, so no changes are persisted to your database. + // Tell Scribe which connections should be transacted here. If you only use one db connection, you can leave this as is. + 'database_connections_to_transact' => [config('database.default')], + + 'fractal' => [ + // If you are using a custom serializer with league/fractal, you can specify it here. + 'serializer' => null, + ], +]; diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 584104c9..ba9e2f93 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -2,43 +2,28 @@ namespace Database\Factories; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; -/** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User> - */ class UserFactory extends Factory { - /** - * The current password being used by the factory. - */ - protected static ?string $password; + protected $model = User::class; - /** - * Define the model's default state. - * - * @return array - */ public function definition(): array { return [ - 'name' => fake()->name(), - 'email' => fake()->unique()->safeEmail(), + 'name' => $this->faker->name(), + 'email' => $this->faker->unique()->safeEmail(), 'email_verified_at' => now(), - 'password' => static::$password ??= Hash::make('password'), + 'password' => Hash::make('password'), 'remember_token' => Str::random(10), + 'avatar' => 'default.svg', // Ou implemente lógica para gerar avatares aleatórios + 'is_active' => false, + 'approved_status' => '1', // 2 = aprovado + 'created_at' => now(), + 'updated_at' => now(), ]; } - - /** - * Indicate that the model's email address should be unverified. - */ - public function unverified(): static - { - return $this->state(fn (array $attributes) => [ - 'email_verified_at' => null, - ]); - } } diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 05fb5d9e..4de03b25 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -13,12 +13,23 @@ public function up(): void { Schema::create('users', function (Blueprint $table) { $table->id(); - $table->string('name'); + $table->string('name')->nullable(); + $table->string('username')->nullable(); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); + $table->integer('pin_code')->nullable(); + $table->string('locale')->nullable()->default('pt_BR'); + $table->string('avatar')->nullable(); + $table->string('original_file_name')->nullable(); + $table->boolean('is_active')->nullable()->default(0); + $table->string('approved_status')->nullable()->default('1'); + $table->string('nickname')->nullable(); + $table->rememberToken(); $table->timestamps(); + $table->softDeletes(); + $table->unsignedBigInteger('registered_by')->nullable(); }); Schema::create('password_reset_tokens', function (Blueprint $table) { diff --git a/database/migrations/0001_01_01_000012_create_command_logs_table.php b/database/migrations/0001_01_01_000012_create_command_logs_table.php new file mode 100644 index 00000000..521ab431 --- /dev/null +++ b/database/migrations/0001_01_01_000012_create_command_logs_table.php @@ -0,0 +1,28 @@ +id(); + $table->string('command'); // Nome do comando + $table->text('output')->nullable(); // Saída do comando + $table->boolean('status')->default(false); // Status de execução: sucesso ou falha + $table->timestamp('executed_at')->useCurrent(); // Data de execução + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('command_logs'); + } +}; diff --git a/database/migrations/0001_01_01_000021_create_deleted_records_table.php b/database/migrations/0001_01_01_000021_create_deleted_records_table.php new file mode 100644 index 00000000..195dcfde --- /dev/null +++ b/database/migrations/0001_01_01_000021_create_deleted_records_table.php @@ -0,0 +1,27 @@ +id(); + $table->nullableMorphs('subject'); + $table->nullableMorphs('causer'); + $table->json('subject_data'); // Dados do model excluído + $table->timestamp('deleted_at'); + }); + } + + public function down() + { + Schema::dropIfExists('deleted_records'); + } +}; diff --git a/database/migrations/2023_11_16_193832_create_approve_historics_table.php b/database/migrations/2023_11_16_193832_create_approve_historics_table.php new file mode 100644 index 00000000..17cfe2b7 --- /dev/null +++ b/database/migrations/2023_11_16_193832_create_approve_historics_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('approved_status')->nullable(); + $table->nullableMorphs('subject'); + $table->nullableMorphs('causer'); + $table->text('motive')->nullable(); + $table->timestamps(); + $table->boolean('deleted_by_parent')->default(0); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('approve_historics'); + } +}; diff --git a/database/migrations/2023_11_16_193833_create_approve_historic_translations_table.php b/database/migrations/2023_11_16_193833_create_approve_historic_translations_table.php new file mode 100644 index 00000000..dd1b3acd --- /dev/null +++ b/database/migrations/2023_11_16_193833_create_approve_historic_translations_table.php @@ -0,0 +1,32 @@ +id(); + + $table->foreignIdFor(ApproveHistoric::class, 'item_id') + ->constrained('approve_historics') + ->cascadeOnDelete(); + + $table->string('locale'); + + $table->string('motive')->nullable(); + + $table->unique(['item_id', 'locale']); + }); + } + + public function down(): void + { + Schema::dropIfExists('approve_historic_translations'); + } +}; diff --git a/database/migrations/2023_11_16_193854_create_active_historics_table.php b/database/migrations/2023_11_16_193854_create_active_historics_table.php new file mode 100644 index 00000000..890eac1a --- /dev/null +++ b/database/migrations/2023_11_16_193854_create_active_historics_table.php @@ -0,0 +1,32 @@ +id(); + $table->boolean('is_active')->nullable(); + $table->nullableMorphs('subject'); + $table->nullableMorphs('causer'); + $table->text('motive')->nullable(); + $table->timestamps(); + $table->boolean('deleted_by_parent')->default(0); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('active_historics'); + } +}; diff --git a/database/migrations/2023_11_16_193855_create_active_historic_translations_table.php b/database/migrations/2023_11_16_193855_create_active_historic_translations_table.php new file mode 100644 index 00000000..49ac7392 --- /dev/null +++ b/database/migrations/2023_11_16_193855_create_active_historic_translations_table.php @@ -0,0 +1,29 @@ +id(); + + $table->foreignIdFor(ActiveHistoric::class, 'item_id') + ->constrained('active_historics') + ->cascadeOnDelete(); + $table->string('locale'); + $table->string('motive')->nullable(); + $table->unique(['item_id', 'locale']); + }); + } + + public function down(): void + { + Schema::dropIfExists('active_historic_translations'); + } +}; diff --git a/database/migrations/2024_09_26_173718_create_log_subject_types_table.php b/database/migrations/2024_09_26_173718_create_log_subject_types_table.php new file mode 100644 index 00000000..9df2abae --- /dev/null +++ b/database/migrations/2024_09_26_173718_create_log_subject_types_table.php @@ -0,0 +1,35 @@ +id(); + $table->string('type')->unique(); // Ex: 'App\Models\User' + $table->string('alias'); // Ex: 'User' + $table->string('what_subject_name')->nullable(); + $table->longText('description')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('log_subject_types'); + } +}; diff --git a/database/migrations/2025_02_24_014055_create_user_logins_table.php b/database/migrations/2025_02_24_014055_create_user_logins_table.php new file mode 100644 index 00000000..8fc0e9e0 --- /dev/null +++ b/database/migrations/2025_02_24_014055_create_user_logins_table.php @@ -0,0 +1,39 @@ +id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('token_id'); + $table->string('ip_address'); + $table->string('browser'); + $table->string('browser_version'); + $table->string('platform'); + $table->string('device_type'); + $table->boolean('is_mobile'); + $table->boolean('is_tablet'); + $table->boolean('is_desktop'); + $table->timestamp('logout_at')->nullable(); + $table->integer('session_duration')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_logins'); + } +}; diff --git a/database/migrations/2025_02_24_014115_create_login_logs_table.php b/database/migrations/2025_02_24_014115_create_login_logs_table.php new file mode 100644 index 00000000..0855f5b9 --- /dev/null +++ b/database/migrations/2025_02_24_014115_create_login_logs_table.php @@ -0,0 +1,33 @@ +id(); + $table->unsignedBigInteger('user_id')->nullable(); + $table->string('identifier'); + $table->string('ip_address'); + $table->text('user_agent'); + $table->string('status'); + $table->text('error_message')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('login_logs'); + } +}; diff --git a/database/migrations/2025_06_09_130214_create_personal_access_tokens_table.php b/database/migrations/2025_06_09_130214_create_personal_access_tokens_table.php new file mode 100644 index 00000000..e828ad81 --- /dev/null +++ b/database/migrations/2025_06_09_130214_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('tokenable'); + $table->string('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/database/migrations/2025_06_09_130733_create_notifications_table.php b/database/migrations/2025_06_09_130733_create_notifications_table.php new file mode 100644 index 00000000..d7380322 --- /dev/null +++ b/database/migrations/2025_06_09_130733_create_notifications_table.php @@ -0,0 +1,31 @@ +uuid('id')->primary(); + $table->string('type'); + $table->morphs('notifiable'); + $table->text('data'); + $table->timestamp('read_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('notifications'); + } +}; diff --git a/database/migrations/2025_06_09_181048_create_activity_log_table.php b/database/migrations/2025_06_09_181048_create_activity_log_table.php new file mode 100644 index 00000000..7c05bc89 --- /dev/null +++ b/database/migrations/2025_06_09_181048_create_activity_log_table.php @@ -0,0 +1,27 @@ +create(config('activitylog.table_name'), function (Blueprint $table) { + $table->bigIncrements('id'); + $table->string('log_name')->nullable(); + $table->text('description'); + $table->nullableMorphs('subject', 'subject'); + $table->nullableMorphs('causer', 'causer'); + $table->json('properties')->nullable(); + $table->timestamps(); + $table->index('log_name'); + }); + } + + public function down() + { + Schema::connection(config('activitylog.database_connection'))->dropIfExists(config('activitylog.table_name')); + } +} diff --git a/database/migrations/2025_06_09_181049_add_event_column_to_activity_log_table.php b/database/migrations/2025_06_09_181049_add_event_column_to_activity_log_table.php new file mode 100644 index 00000000..7b797fd5 --- /dev/null +++ b/database/migrations/2025_06_09_181049_add_event_column_to_activity_log_table.php @@ -0,0 +1,22 @@ +table(config('activitylog.table_name'), function (Blueprint $table) { + $table->string('event')->nullable()->after('subject_type'); + }); + } + + public function down() + { + Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) { + $table->dropColumn('event'); + }); + } +} diff --git a/database/migrations/2025_06_09_181050_add_batch_uuid_column_to_activity_log_table.php b/database/migrations/2025_06_09_181050_add_batch_uuid_column_to_activity_log_table.php new file mode 100644 index 00000000..8f7db665 --- /dev/null +++ b/database/migrations/2025_06_09_181050_add_batch_uuid_column_to_activity_log_table.php @@ -0,0 +1,22 @@ +table(config('activitylog.table_name'), function (Blueprint $table) { + $table->uuid('batch_uuid')->nullable()->after('properties'); + }); + } + + public function down() + { + Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) { + $table->dropColumn('batch_uuid'); + }); + } +} diff --git a/database/migrations/2025_06_09_181106_create_permission_tables.php b/database/migrations/2025_06_09_181106_create_permission_tables.php new file mode 100644 index 00000000..ce4d9d2d --- /dev/null +++ b/database/migrations/2025_06_09_181106_create_permission_tables.php @@ -0,0 +1,136 @@ +engine('InnoDB'); + $table->bigIncrements('id'); // permission id + $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format) + $table->string('guard_name'); // For MyISAM use string('guard_name', 25); + $table->timestamps(); + + $table->unique(['name', 'guard_name']); + }); + + Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) { + // $table->engine('InnoDB'); + $table->bigIncrements('id'); // role id + if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing + $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable(); + $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index'); + } + $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format) + $table->string('guard_name'); // For MyISAM use string('guard_name', 25); + $table->timestamps(); + if ($teams || config('permission.testing')) { + $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']); + } else { + $table->unique(['name', 'guard_name']); + } + }); + + Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) { + $table->unsignedBigInteger($pivotPermission); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); + + $table->foreign($pivotPermission) + ->references('id') // permission id + ->on($tableNames['permissions']) + ->onDelete('cascade'); + if ($teams) { + $table->unsignedBigInteger($columnNames['team_foreign_key']); + $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index'); + + $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + } else { + $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + } + + }); + + Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) { + $table->unsignedBigInteger($pivotRole); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); + + $table->foreign($pivotRole) + ->references('id') // role id + ->on($tableNames['roles']) + ->onDelete('cascade'); + if ($teams) { + $table->unsignedBigInteger($columnNames['team_foreign_key']); + $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index'); + + $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + } else { + $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + } + }); + + Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) { + $table->unsignedBigInteger($pivotPermission); + $table->unsignedBigInteger($pivotRole); + + $table->foreign($pivotPermission) + ->references('id') // permission id + ->on($tableNames['permissions']) + ->onDelete('cascade'); + + $table->foreign($pivotRole) + ->references('id') // role id + ->on($tableNames['roles']) + ->onDelete('cascade'); + + $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary'); + }); + + app('cache') + ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null) + ->forget(config('permission.cache.key')); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + $tableNames = config('permission.table_names'); + + if (empty($tableNames)) { + throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.'); + } + + Schema::drop($tableNames['role_has_permissions']); + Schema::drop($tableNames['model_has_roles']); + Schema::drop($tableNames['model_has_permissions']); + Schema::drop($tableNames['roles']); + Schema::drop($tableNames['permissions']); + } +}; diff --git a/database/migrations/2025_06_27_123156_create_genders_table.php b/database/migrations/2025_06_27_123156_create_genders_table.php new file mode 100644 index 00000000..02d611a0 --- /dev/null +++ b/database/migrations/2025_06_27_123156_create_genders_table.php @@ -0,0 +1,61 @@ +id(); + + $table->string('name', 255)->nullable()->unique(); + $table->string('name_translated', 255)->nullable(); + $table->string('icon')->nullable(); + $table->string('icon_file_name')->nullable(); + $table->string('icon_file_extension')->nullable(); + $table->integer('icon_file_size')->nullable(); + $table->string('original_locale')->nullable(); + + $table->boolean('is_active')->nullable()->default(0); + + + $table->boolean('deleted_by_parent')->default(0); + $table->softDeletes(); + $table->timestamps(); + }); + + Schema::create('gender_translations', function (Blueprint $table) { + $table->id(); + + $table->foreignIdFor(Gender::class, 'item_id') + ->constrained('genders') + ->cascadeOnDelete(); + + $table->string('locale'); + + $table->string('name_translated', 255)->nullable(); + + $table->unique(['item_id', 'locale']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('gender_translations'); + Schema::dropIfExists('genders'); + } +}; \ No newline at end of file diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d01a0ef2..9039d0ae 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -13,11 +13,10 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); - - User::factory()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', + $this->call([ + PermissionSeeder::class, + UserSeeder::class, + // Outros seeders... ]); } } diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php new file mode 100644 index 00000000..c238b64f --- /dev/null +++ b/database/seeders/PermissionSeeder.php @@ -0,0 +1,116 @@ +command->info("==>> Iniciando Seeder de permissions e roles"); + // Reset cached roles and permissions + app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions(); + // Permissões para gerenciar desenvolvimento + Permission::create(['name' => 'system.models.list']); + Permission::create(['name' => 'system.models.create']); + Permission::create(['name' => 'system.models.edit']); + Permission::create(['name' => 'system.models.show']); + Permission::create(['name' => 'system.models.delete']); + Permission::create(['name' => 'system.models.trashed.show']); + Permission::create(['name' => 'system.models.trashed.delete']); + Permission::create(['name' => 'system.models.trashed.restore']); + Permission::create(['name' => 'system.models.toggle.is.active']); + Permission::create(['name' => 'system.models.toggle.approve.status']); + Permission::create(['name' => 'system.models.activate']); + Permission::create(['name' => 'system.models.deactivate']); + $this->command->info("====>> Permissions para system adicionadas"); + // Permissões para gerenciar log activities + Permission::create(['name' => 'activityLogs.list']); + Permission::create(['name' => 'activityLogs.create']); + Permission::create(['name' => 'activityLogs.edit']); + Permission::create(['name' => 'activityLogs.show']); + Permission::create(['name' => 'activityLogs.delete']); + Permission::create(['name' => 'activityLogs.trashed.show']); + Permission::create(['name' => 'activityLogs.trashed.delete']); + Permission::create(['name' => 'activityLogs.trashed.restore']); + Permission::create(['name' => 'activityLogs.toggle.is.active']); + Permission::create(['name' => 'activityLogs.toggle.approve.status']); + Permission::create(['name' => 'activityLogs.activate']); + Permission::create(['name' => 'activityLogs.deactivate']); + $this->command->info("====>> Permissions para activity logs adicionadas"); + // Permissões para gerenciar generos + Permission::create(['name' => 'genders.list']); + Permission::create(['name' => 'genders.create']); + Permission::create(['name' => 'genders.edit']); + Permission::create(['name' => 'genders.show']); + Permission::create(['name' => 'genders.delete']); + Permission::create(['name' => 'genders.trashed.show']); + Permission::create(['name' => 'genders.trashed.delete']); + Permission::create(['name' => 'genders.trashed.restore']); + Permission::create(['name' => 'genders.toggle.is.active']); + Permission::create(['name' => 'genders.toggle.approve.status']); + Permission::create(['name' => 'genders.activate']); + Permission::create(['name' => 'genders.deactivate']); + $this->command->info("====>> Permissions para genders adicionadas"); + // Permissões para gerenciar usuários + Permission::create(['name' => 'users.list']); + Permission::create(['name' => 'users.create']); + Permission::create(['name' => 'users.edit']); + Permission::create(['name' => 'users.show']); + Permission::create(['name' => 'users.delete']); + Permission::create(['name' => 'users.trashed.show']); + Permission::create(['name' => 'users.trashed.delete']); + Permission::create(['name' => 'users.trashed.restore']); + Permission::create(['name' => 'users.toggle.is.active']); + Permission::create(['name' => 'users.toggle.approve.status']); + Permission::create(['name' => 'users.activate']); + Permission::create(['name' => 'users.deactivate']); + $this->command->info("====>> Permissions para users adicionadas"); + $systemNames = Permission::where('name', 'like', 'system.%') + ->pluck('name') + ->toArray(); + $usersPermissionNames = Permission::where('name', 'like', 'users.%') + ->pluck('name') + ->toArray(); + $gendersPermissionNames = Permission::where('name', 'like', 'genders.%') + ->pluck('name') + ->toArray(); + $activityLogsNames = Permission::where('name', 'like', 'activityLogs.%') + ->pluck('name') + ->toArray(); + + $system = Role::create(['name' => 'system-admin']); + $system->givePermissionTo($systemNames); + $system->givePermissionTo($activityLogsNames); + $this->command->info("====>> Role para system-admin adicionada"); + $admin = Role::create(['name' => 'super-admin']); + $admin->givePermissionTo($usersPermissionNames); + $admin->givePermissionTo($gendersPermissionNames); + $admin->givePermissionTo($activityLogsNames); + $this->command->info("====>> Role para super-admin adicionada"); + $manager = Role::create(['name' => 'users-manager']); + $manager->givePermissionTo([ + 'genders.list', + 'genders.show', + 'users.list', + 'users.show', + 'users.toggle.is.active' + ]); + $manager->givePermissionTo($activityLogsNames); + $this->command->info("====>> Role para users-manager adicionada"); + + $guest = Role::create(['name' => 'guests']); + $guest->givePermissionTo([ + 'users.list', + 'users.show', + ]); + $this->command->info("====>> Role para guests adicionada"); + $this->command->info("==>> Encerrado Seeder de permissions e roles"); + } +} diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php new file mode 100644 index 00000000..7a97f21d --- /dev/null +++ b/database/seeders/UserSeeder.php @@ -0,0 +1,295 @@ +command->info("==>> Iniciado Seeder de users"); + $motives = []; + $this->command->info("====>> Iniciado translator de motivos"); + + $translateds = TranslatorGoogle::translate('Cadastro inicial'); + $motives = $translateds['translations']; + $this->command->info("====>> Encerrado translator de motivos"); + + // Limpa a pasta de avatares (opcional) + Storage::deleteDirectory('image/user_avatar'); + Storage::makeDirectory('image/user_avatar'); + $systemRole = Role::firstOrCreate(['name' => 'system-admin']); + // Usuário system padrão + $status = '2'; // 2 = aprovado + $isActive = true; // Ativo + $userSystem = User::create([ + 'name' => 'Admin System', + 'email' => 'adminsystem@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Admin'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => $isActive, + 'approved_status' => $status + ])->assignRole([ + $systemRole, + ]); + + $userSystem->approvedMotives()->create([ + 'approved_status' => $status, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $userSystem->activeMotives()->create([ + 'is_active' => $isActive, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $this->command->info("====>> Atribuída role 'system-admin' para {$userSystem->email}"); + + // Usuário super admin padrão + $adminRole = Role::firstOrCreate(['name' => 'super-admin']); + $user = User::create([ + 'name' => 'Super Administrador', + 'email' => 'superadmin@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Super'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => true, + 'approved_status' => '2', // 2 = aprovado + ])->assignRole([ + $adminRole, + ]); + $user->approvedMotives()->create([ + 'approved_status' => $status, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $user->activeMotives()->create([ + 'is_active' => $isActive, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $this->command->info("====>> Atribuída role 'admin' para {$user->email}"); + + + $managerRole = Role::firstOrCreate(['name' => 'users-manager']); + // Usuário users manager padrão + $user = User::create([ + 'name' => 'Users Manager', + 'email' => 'usersmanager@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Users'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => true, + 'approved_status' => '2', // 2 = aprovado + ])->assignRole([ + $managerRole, + ]); + $user->approvedMotives()->create([ + 'approved_status' => $status, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $user->activeMotives()->create([ + 'is_active' => $isActive, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $this->command->info("====>> Atribuída role 'manager Role' para {$user->email}"); + + // Usuário guest padrão + $guestRole = Role::firstOrCreate(['name' => 'guests']); + + + // Usuários de exemplo + $usersExample = [ + [ + 'name' => 'João Silva', + 'email' => 'joao@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Joao'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => true, + 'approved_status' => '2', // 2 = aprovado + + ], + [ + 'name' => 'Maria Souza', + 'email' => 'maria@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Maria'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => true, + 'approved_status' => '2', // 2 = aprovado + + ], + [ + 'name' => 'Carlos Oliveira', + 'email' => 'carlos@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Carlos'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => true, + 'approved_status' => '2', // 2 = aprovado + + ], + [ + 'name' => 'Ana Santos', + 'email' => 'ana@example.com', + 'password' => Hash::make('password'), + 'avatar' => $this->storeAvatar('Ana'), + 'email_verified_at' => now(), + 'created_at' => now(), + 'updated_at' => now(), + 'remember_token' => Str::random(10), + 'is_active' => true, + 'approved_status' => '2', // 2 = aprovado + + ], + ]; + foreach ($usersExample as $userData) { + $user = User::create($userData); + $user->assignRole($managerRole); + $user->approvedMotives()->create([ + 'approved_status' => $status, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $user->activeMotives()->create([ + 'is_active' => $isActive, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $this->command->info("====>> Atribuída role 'manager' para {$user->email}"); + } + + $this->command->info("====>> Iniciado Seeder de 200 usuários 'guests' "); + + $this->storeDefaultAvatar('Guests'); + // 200 usuários fictícios (opcional) + $user = User::factory()->count(200)->create(); + $this->command->info("====>> Encerrado Seeder de 200 usuários 'guests' "); + $this->command->info("====>> Atribuir 'guests' para usuários sem roles"); + + $usersWithoutRoles = User::whereDoesntHave('roles')->get(); + if ($usersWithoutRoles->isEmpty()) { + $this->command->info('======>> Não há usuários sem roles para atribuir.'); + return; + } + foreach ($usersWithoutRoles as $user) { + + $user->assignRole($guestRole); + $user->approvedMotives()->create([ + 'approved_status' => $status, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $user->activeMotives()->create([ + 'is_active' => $isActive, + 'causer_type' => User::class, // Tipo do usuário que ativou + 'causer_id' => $userSystem->id, // ID do usuário que ativou + 'motive' => $motives, + // 'motive' => $motive, + ]); + $this->command->info("======>> Atribuída role 'guests' para {$user->email}"); + } + + $this->command->info("====>> Iniciado Seeder de ajuste de activity logs causer"); + + $activities = ActivityLog::whereNull('causer_type')->get(); + // Usuário system padrão + $causer_type = User::class; + $causer_id = $userSystem->id; + + foreach ($activities as $activity) { + $activity->update(['causer_type' => $causer_type, 'causer_id' => $causer_id]); + $this->command->info("======>> Atribuído causer para {$activity->id}"); + } + $this->command->info("====>> Encerrado Seeder de ajuste de activity logs causer"); + $this->command->info("==>> Encerrado Seeder de users"); + } + + + + /** + * Gera um avatar fictício usando a API DiceBear + */ + private function storeAvatar(string $seed): string + { + $url = "https://api.dicebear.com/7.x/initials/svg?seed={$seed}&scale=80"; + $contents = file_get_contents($url); + // $path = "avatars/{$seed}-" . time() . ".svg"; // Nome único + $storageAvatar = User::AVATAR_STORAGE; + $savedNameAvatar = ''; + $originalFileName = ''; + $fileSize = 0; + $fileExtension = ''; + $uploadData = []; + $storageDisk = 'public'; + $fileName = $seed . '-' . time() . '.svg'; // Nome único com timestamp + + Storage::put($storageAvatar . DIRECTORY_SEPARATOR . $fileName, $contents, $storageDisk); + return $fileName; // Retorna o caminho relativo + } + + + /** + * Gera um avatar fictício usando a API DiceBear + */ + private function storeDefaultAvatar(string $seed): string + { + $url = "https://api.dicebear.com/7.x/initials/svg?seed={$seed}&scale=80"; + $contents = file_get_contents($url); + // $path = "avatars/{$seed}-" . time() . ".svg"; // Nome único + $storageAvatar = User::AVATAR_STORAGE; + $storageDisk = 'public'; + $fileName = 'default.svg'; // Nome único com timestamp + + Storage::put($storageAvatar . DIRECTORY_SEPARATOR . $fileName, $contents, $storageDisk); + return $fileName; // Retorna o caminho relativo + } +} diff --git a/documentation/commands.md b/documentation/commands.md new file mode 100644 index 00000000..2f1eb7b7 --- /dev/null +++ b/documentation/commands.md @@ -0,0 +1,19 @@ +composer install && +php artisan migrate && +chmod -R 755 storage bootstrap/cache && +php artisan seed:log-subject-types && +php artisan config:clear && +php artisan cache:clear && +php artisan route:clear && +php artisan view:clear && +composer dump-autoload && +php artisan queue:work + + +composer install && +php artisan migrate:fresh && +chmod -R 755 storage bootstrap/cache && +php artisan seed:log-subject-types +php artisan db:seed --class=PermissionSeeder +php artisan db:seed --class=PermissionActivityLogSeeder +php artisan db:seed --class=UserSeeder diff --git a/documentation/models/json/Gender.json b/documentation/models/json/Gender.json new file mode 100644 index 00000000..30e58580 --- /dev/null +++ b/documentation/models/json/Gender.json @@ -0,0 +1,65 @@ +{ + "name": "Gender", + "version": "V1", + "softDeletes": true, + "timestamps": true, + "useIsActive": true, + "useApprovedStatus": false, + "useScribe": true, + "authorize": false, + "logsActivity": true, + "clearsResponseCache": true, + "attributes": [ + { + "name": "name", + "type": "string", + "length": 255, + "precision": 0, + "scale": 0, + "max": 255, + "min": 0, + "validate": true, + "required": true, + "nullable": true, + "unique": true, + "translated": true, + "sortAble": true, + "filterAble": true, + "exactFilter": false, + "searchAble": true, + "description": "Determina o g\u00eanero", + "example": "male" + }, + { + "name": "icon", + "type": "image", + "length": 255, + "precision": 0, + "scale": 0, + "max": 255, + "min": 0, + "validate": true, + "required": false, + "nullable": true, + "unique": false, + "translated": false, + "sortAble": false, + "filterAble": false, + "exactFilter": false, + "searchAble": false, + "description": "icon to represent", + "example": null + } + ], + "relations": [ + { + "name": "users", + "type": "hasMany", + "default": true, + "related": "User", + "description": null + } + ], + "created_at": "2025-06-27 12:30:07", + "updated_at": "2025-06-27 12:30:53" +} \ No newline at end of file diff --git a/lang/de.json b/lang/de.json new file mode 100644 index 00000000..a002c8a5 --- /dev/null +++ b/lang/de.json @@ -0,0 +1,1013 @@ +{ + "(and :count more error)": "(und :count weiterer Fehler)", + "(and :count more errors)": "(und :count weiterer Fehler)|(und :count weitere Fehler)|(und :count weitere Fehler)", + "30 Days": "30 Tage", + "60 Days": "60 Tage", + "90 Days": "90 Tage", + ":amount selected": ":Amount ausgewählt", + ":amount Total": ":Amount Gesamt", + ":days day trial": ":Days Tage Testversion", + ":resource Details": ":Resource Einzelheiten", + ":resource Details: :title": ":resource Einzelheiten: :title", + "A decryption key is required.": "Ein Entschlüsselungsschlüssel ist nötig.", + "A fresh verification link has been sent to your email address.": "Ein neuer Bestätigungslink wurde an Ihre E-Mail-Adresse gesendet.", + "A new verification link has been sent to the email address you provided during registration.": "Ein neuer Bestätigungslink wurde an die E-Mail-Adresse gesendet, die Sie bei der Registrierung angegeben haben.", + "A new verification link has been sent to the email address you provided in your profile settings.": "Ein neuer Bestätigungslink wurde an die E-Mail-Adresse, die in Ihrem Profil hinterlegt ist, gesendet.", + "A new verification link has been sent to your email address.": "Ein neuer Bestätigungslink wurde an Ihre E-Mail-Adresse versendet.", + "Accept Invitation": "Einladung annehmen", + "Action": "Aktion", + "Action Event": "Aktion Ereignis", + "Action Events": "Aktion Ereignisse", + "Action Happened At": "Aktion geschah am", + "Action Initiated By": "Aktion initiiert durch", + "Action Name": "Name", + "Action Status": "Status", + "Action Target": "Ziel", + "Actions": "Aktionen", + "Add": "Hinzufügen", + "Add :resource": "Füge :Resource hinzu", + "Add a new team member to your team, allowing them to collaborate with you.": "Fügen Sie ein neues Teammitglied zu Ihrem Team hinzu und erlauben Sie ihm mit Ihnen zusammenzuarbeiten.", + "Add additional security to your account using two factor authentication.": "Fügen Sie Ihrem Konto zusätzliche Sicherheit hinzu, indem Sie die Zwei-Faktor-Authentifizierung verwenden.", + "Add Payment Method": "Zahlungsmethode hinzufügen", + "Add row": "Zeile hinzufügen", + "Add Team Member": "Teammitglied hinzufügen", + "Add VAT Number": "Umsatzsteuer-Identifikationsnummer hinzufügen", + "Added.": "Hinzugefügt.", + "Additional billing information updated successfully.": "Zusätzliche Rechnungsinformationen erfolgreich aktualisiert.", + "Address": "Adresse", + "Address Line 2": "Adresse Zeile 2", + "Administrator": "Administrator", + "Administrator users can perform any action.": "Administratoren können jede Aktion durchführen.", + "Afghanistan": "Afghanistan", + "Aland Islands": "Åland", + "Albania": "Albanien", + "Algeria": "Algerien", + "All of the people that are part of this team.": "Alle Personen, die Teil dieses Teams sind.", + "All resources loaded.": "Alle Ressourcen geladen.", + "All rights reserved.": "Alle Rechte vorbehalten.", + "Already registered?": "Bereits registriert?", + "American Samoa": "Amerikanisch-Samoa", + "An error occurred while uploading the file.": "Beim Hochladen der Datei ist ein Fehler aufgetreten.", + "An error occurred while uploading the file: :error": "Beim Hochladen der Datei ist ein Fehler aufgetreten: :error", + "An unexpected error occurred and we have notified our support team. Please try again later.": "Es ist ein unerwarteter Fehler aufgetreten und wir haben unser Support-Team benachrichtigt. Bitte versuchen Sie es später noch einmal.", + "Andorra": "Andorra", + "Angola": "Angola", + "Anguilla": "Anguilla", + "Another user has updated this resource since this page was loaded. Please refresh the page and try again.": "Ein anderer Benutzer hat diese Ressource aktualisiert, seit diese Seite geladen wurde. Bitte aktualisieren Sie die Seite und versuchen Sie es erneut.", + "Antarctica": "Antarktis", + "Antigua And Barbuda": "Antigua und Barbuda", + "Antigua and Barbuda": "Antigua und Barbuda", + "API Token": "API-Token", + "API Token Permissions": "API-Token-Berechtigungen", + "API Tokens": "API-Token", + "API tokens allow third-party services to authenticate with our application on your behalf.": "Mit API-Token können sich Dienste von Drittanbietern in Ihrem Namen bei unserer Anwendung authentifizieren.", + "Apply": "Anwenden", + "Apply Coupon": "Gutschein anwenden", + "April": "April", + "Are you sure you want to attempt to pay :amount?": "Möchten Sie wirklich versuchen, :amount zu zahlen?", + "Are you sure you want to cancel your subscription?": "Möchten Sie Ihr Abonnement wirklich kündigen?", + "Are you sure you want to delete all the notifications?": "Sind Sie sicher, dass Sie alle Benachrichtigungen löschen möchten?", + "Are you sure you want to delete the selected resources?": "Sind Sie sicher, dass Sie die ausgewählten Ressourcen löschen möchten?", + "Are you sure you want to delete this file?": "Sind Sie sicher, dass Sie diese Datei löschen wollen?", + "Are you sure you want to delete this notification?": "Sind Sie sicher, dass Sie diese Benachrichtigung löschen möchten?", + "Are you sure you want to delete this payment method?": "Möchten Sie diese Zahlungsmethode wirklich löschen?", + "Are you sure you want to delete this resource?": "Sind Sie sicher, dass Sie diese Ressource löschen wollen?", + "Are you sure you want to delete this team? Once a team is deleted, all of its resources and data will be permanently deleted.": "Möchten Sie dieses Team wirklich löschen? Sobald ein Team gelöscht wird, werden alle Ressourcen und Daten dauerhaft gelöscht.", + "Are you sure you want to delete your account?": "Möchten Sie Ihr Konto wirklich löschen?", + "Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Möchten Sie Ihr Konto wirklich löschen? Sobald Ihr Konto gelöscht wurde, werden alle Ressourcen und Daten dauerhaft gelöscht. Bitte geben Sie Ihr Passwort ein, um zu bestätigen, dass Sie Ihr Konto dauerhaft löschen möchten.", + "Are you sure you want to detach the selected resources?": "Sind Sie sicher, dass Sie die ausgewählten Ressourcen abtrennen wollen?", + "Are you sure you want to detach this resource?": "Sind Sie sicher, dass Sie diese Ressource abtrennen wollen?", + "Are you sure you want to force delete the selected resources?": "Sind Sie sicher, dass Sie das Löschen der ausgewählten Ressourcen erzwingen wollen?", + "Are you sure you want to force delete this resource?": "Sind Sie sicher, dass Sie die Löschung dieser Ressource erzwingen wollen?", + "Are you sure you want to log out?": "Sind Sie sicher, dass Sie sich abmelden möchten?", + "Are you sure you want to mark all notifications as read?": "Sind Sie sicher, dass Sie alle Benachrichtigungen als gelesen markieren möchten?", + "Are you sure you want to remove this item?": "Möchten Sie dieses Element wirklich entfernen?", + "Are you sure you want to restore the selected resources?": "Sind Sie sicher, dass Sie die ausgewählten Ressourcen wiederherstellen wollen?", + "Are you sure you want to restore this resource?": "Sind Sie sicher, dass Sie diese Ressource wiederherstellen wollen?", + "Are you sure you want to resume your subscription?": "Möchten Sie Ihr Abonnement wirklich fortsetzen?", + "Are you sure you want to run this action?": "Sind Sie sicher, dass Sie diese Aktion ausführen wollen?", + "Are you sure you want to set this payment method as your default?": "Möchten Sie diese Zahlungsmethode wirklich als Standard festlegen?", + "Are you sure you want to stop impersonating?": "Sind Sie sicher, dass Sie das Imitieren stoppen wollen?", + "Are you sure you would like to delete this API token?": "Möchten Sie dieses API-Token wirklich löschen?", + "Are you sure you would like to leave this team?": "Sind Sie sicher, dass Sie dieses Team verlassen möchten?", + "Are you sure you would like to remove this person from the team?": "Sind Sie sicher, dass Sie diese Person aus dem Team entfernen möchten?", + "Are you sure you would like to switch billing plans?": "Sind Sie sicher, dass Sie den Tarif wechseln möchten?", + "Argentina": "Argentinien", + "Armenia": "Armenien", + "Aruba": "Aruba", + "Attach": "Anhängen", + "Attach & Attach Another": "Anhang und weiterer Anhang", + "Attach :resource": ":Resource Anhängen", + "Attach files by dragging & dropping, selecting or pasting them.": "Hängen Sie Dateien an, indem Sie sie ziehen und ablegen, auswählen oder probieren.", + "August": "August", + "Australia": "Australien", + "Austria": "Österreich", + "Azerbaijan": "Aserbaidschan", + "Bahamas": "Bahamas", + "Bahrain": "Bahrain", + "Bangladesh": "Bangladesch", + "Barbados": "Barbados", + "Before continuing, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.": "Bitte bestätigen Sie Ihre E-Mail-Adresse mit dem zugesandten Link, bevor Sie fortfahren. Sollten Sie keine E-Mail erhalten haben, senden wir Ihnen diese gerne erneut.", + "Before proceeding, please check your email for a verification link.": "Bevor Sie fortfahren, überprüfen Sie bitte Ihre E-Mail auf einen Bestätigungslink.", + "Belarus": "Belarus", + "Belgium": "Belgien", + "Belize": "Belize", + "Benin": "Benin", + "Bermuda": "Bermuda", + "Bhutan": "Bhutan", + "Billing Information": "Informationen zur Abrechnung", + "Billing Management": "Abrechnungsmanagement", + "Bolivia": "Bolivien", + "Bolivia, Plurinational State of": "Bolivien", + "Bonaire, Sint Eustatius and Saba": "Karibische Niederlande", + "Bosnia And Herzegovina": "Bosnien und Herzegowina", + "Bosnia and Herzegovina": "Bosnien und Herzegowina", + "Botswana": "Botswana", + "Bouvet Island": "Bouvetinsel", + "Brazil": "Brasilien", + "British Indian Ocean Territory": "Britisches Territorium im Indischen Ozean", + "Browser Sessions": "Browsersitzungen", + "Brunei Darussalam": "Brunei", + "Bulgaria": "Bulgarien", + "Burkina Faso": "Burkina Faso", + "Burundi": "Burundi", + "Cambodia": "Kambodscha", + "Cameroon": "Kamerun", + "Canada": "Kanada", + "Cancel": "Abbrechen", + "Cancel Subscription": "Abonnement kündigen", + "Cape Verde": "Kap Verde", + "Card": "Karte", + "Cayman Islands": "Caymaninseln", + "Central African Republic": "Zentralafrikanische Republik", + "Chad": "Tschad", + "Change Subscription Plan": "Abonnementplan ändern", + "Change the current payment method attached to your subscription": "Mit dem Abonnementplan verknüpfte Zahlungsmethode ändern", + "Changes": "Änderungen", + "Checkout": "Kasse", + "Chile": "Chile", + "China": "China", + "Choose": "Wählen Sie", + "Choose :field": "Wählen Sie :field", + "Choose :resource": "Wählen Sie :resource", + "Choose an option": "Wählen Sie eine Option", + "Choose date": "Datum wählen", + "Choose File": "Datei wählen", + "Choose Files": "Dateien wählen", + "Choose Type": "Typ wählen", + "Christmas Island": "Weihnachtsinsel", + "City": "Stadt", + "Click here to re-send the verification email.": "Klicke hier, um eine neue Verifizierungs-E-Mail zu erhalten.", + "click here to request another": "Klicken Sie hier, um eine weitere Anfrage zu starten", + "Click to choose": "Klicken Sie zum Auswählen", + "Close": "Schließen", + "Cocos (Keeling) Islands": "Kokosinseln", + "Code": "Code", + "Colombia": "Kolumbien", + "Comoros": "Komoren", + "Confirm": "Bestätigen", + "Confirm Billing Action": "Abrechnungsaktion bestätigen", + "Confirm Password": "Passwort bestätigen", + "Confirm Payment": "Zahlung bestätigen", + "Confirm your :amount payment": "Bestätigen Sie Ihre :amount Zahlung", + "Congo": "Kongo", + "Congo, Democratic Republic": "Demokratische Republik Kongo", + "Congo, the Democratic Republic of the": "Demokratische Republik Kongo", + "Constant": "Konstant", + "Continue To Payment": "Weiter zur Zahlung", + "Cook Islands": "Cookinseln", + "Copy to clipboard": "In die Zwischenablage kopieren", + "Costa Rica": "Costa Rica", + "Cote D'Ivoire": "Elfenbeinküste", + "Country": "Land", + "Coupon": "Gutschein", + "Coupon applied successfully.": "Gutschein erfolgreich angewendet.", + "Create": "Erstellen", + "Create & Add Another": "Erstellen & ein weiteres hinzufügen", + "Create :resource": ":Resource erstellen", + "Create a new team to collaborate with others on projects.": "Erstellen Sie ein neues Team, um mit anderen an Projekten zusammenzuarbeiten.", + "Create Account": "Neues Konto registrieren", + "Create API Token": "API-Token erstellen", + "Create New Team": "Neues Team erstellen", + "Create Team": "Team erstellen", + "Created.": "Erstellt.", + "Croatia": "Kroatien", + "CSV (.csv)": "CSV (.csv)", + "Cuba": "Kuba", + "Curaçao": "Curaçao", + "Current Password": "Derzeitiges Passwort", + "Current Subscription Plan": "Aktueller Abonnementplan", + "Currently Subscribed": "Aktuell abonniert", + "Customer Balance": "Kundenguthaben", + "Customize": "Anpassen", + "Cyprus": "Zypern", + "Czech Republic": "Tschechische Republik", + "Côte d'Ivoire": "Elfenbeinküste", + "Dark": "Dunkel", + "Dashboard": "Dashboard", + "December": "Dezember", + "Decrease": "Verringern", + "Default": "Standard", + "Delete": "Löschen", + "Delete :resource": "Löschen :resource", + "Delete Account": "Account löschen", + "Delete all notifications": "Alle Benachrichtigungen löschen", + "Delete API Token": "API-Token löschen", + "Delete File": "Datei löschen", + "Delete Notification": "Benachrichtigung löschen", + "Delete Resource": "Ressource löschen", + "Delete Selected": "Ausgewählte löschen", + "Delete Team": "Team löschen", + "Denmark": "Dänemark", + "Detach": "Trennen", + "Detach Resource": "Ressource abtrennen", + "Detach Selected": "Ausgewählte abtrennen", + "Details": "Details", + "Disable": "Deaktivieren", + "Djibouti": "Dschibuti", + "Do you really want to leave? You have unsaved changes.": "Wollen Sie wirklich gehen? Sie haben nicht gespeicherte Änderungen.", + "Dominica": "Dominica", + "Dominican Republic": "Dominikanische Republik", + "Done.": "Erledigt.", + "Download": "Herunterladen", + "Download Invoice": "Rechnung herunterladen", + "Drop file or click to choose": "Legen Sie eine Datei ab oder klicken Sie zum Wählen", + "Drop files or click to choose": "Legen Sie Dateien ab oder klicken Sie zum Wählen", + "Ecuador": "Ecuador", + "Edit": "Bearbeiten", + "Edit :resource": ":Resource bearbeiten", + "Edit Attached": "Anhang bearbeiten", + "Edit Profile": "Profil bearbeiten", + "Editor": "Editor", + "Editor users have the ability to read, create, and update.": "Editor-Benutzer haben die Möglichkeit, zu lesen, zu erstellen und zu aktualisieren.", + "Egypt": "Ägypten", + "El Salvador": "El Salvador", + "Email": "E-Mail", + "email": "e-mail", + "Email Address": "E-Mail-Adresse", + "Email Addresses": "E-Mail-Adressen", + "Email Password Reset Link": "Link zum Zurücksetzen des Passwortes zusenden", + "Email Verification": "E-Mail-Bestätigung", + "Enable": "Aktivieren", + "Encrypted environment file already exists.": "Verschlüsselte Umgebungsdatei ist bereits vorhanden.", + "Encrypted environment file not found.": "Verschlüsselte Umgebungsdatei nicht gefunden.", + "Ensure your account is using a long, random password to stay secure.": "Stellen Sie sicher, dass Ihr Konto ein langes, zufälliges Passwort verwendet, um die Sicherheit zu gewährleisten.", + "Environment file already exists.": "Umgebungsdatei ist bereits vorhanden.", + "Environment file not found.": "Umgebungsdatei nicht gefunden.", + "Equatorial Guinea": "Äquatorialguinea", + "Eritrea": "Eritrea", + "Error": "Fehler", + "errors": "Fehler", + "Estonia": "Estland", + "Ethiopia": "Äthiopien", + "ex VAT": "ohne Umsatzsteuer", + "Excel (.xlsx)": "Excel (.xlsx)", + "Expires :expiration": "Läuft ab :expiration", + "Export As CSV": "Als CSV exportieren", + "Extra Billing Information": "Zusätzliche Informationen zur Rechnungsstellung", + "Extra confirmation is needed to process your payment. Please continue to the payment page by clicking on the button below.": "Eine zusätzliche Bestätigung ist erforderlich, um Ihre Zahlung zu bearbeiten. Bitte fahren Sie mit der Zahlungsseite fort, indem Sie auf die Schaltfläche unten klicken.", + "Failed Subscription Payment": "Abonnementzahlung fehlgeschlagen", + "Failed to load :resource!": ":Resource konnte nicht geladen werden!", + "Falkland Islands (Malvinas)": "Falklandinseln", + "Faroe Islands": "Färöer", + "February": "Februar", + "Fiji": "Fidschi", + "Filename": "Dateiname", + "Finish enabling two factor authentication.": "Aktivierung der Zwei-Faktor-Authentifizierung abschließen.", + "Finland": "Finnland", + "For your security, please confirm your password to continue.": "Um fortzufahren, bestätigen Sie zu Ihrer Sicherheit bitte Ihr Passwort.", + "Forbidden": "Verboten", + "Force Delete": "Löschen erzwingen", + "Force Delete :resource": "Löschen erzwingen :resource", + "Force Delete Resource": "Löschen der Ressource erzwingen", + "Force Delete Selected": "Auswahl Löschen erzwingen", + "Forgot Password": "Passwort vergessen", + "Forgot your password?": "Passwort vergessen?", + "Forgot Your Password?": "Passwort vergessen?", + "Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.": "Haben Sie Ihr Passwort vergessen? Kein Problem. Teilen Sie uns einfach Ihre E-Mail-Adresse mit und wir senden Ihnen per E-Mail einen Link zum Zurücksetzen des Passworts, über den Sie ein Neues auswählen können.", + "France": "Frankreich", + "French Guiana": "Französisch-Guayana", + "French Polynesia": "Französisch-Polynesien", + "French Southern Territories": "Französische Süd- und Antarktisgebiete", + "From": "Von", + "Gabon": "Gabun", + "Gambia": "Gambia", + "Georgia": "Georgien", + "Germany": "Deutschland", + "Ghana": "Ghana", + "Gibraltar": "Gibraltar", + "Go Home": "Zur Startseite", + "Go to page :page": "Gehe zur Seite :page", + "Great! You have accepted the invitation to join the :team team.": "Großartig! Sie haben die Einladung zur Teilnahme am :team angenommen.", + "Greece": "Griechenland", + "Greenland": "Grönland", + "Grenada": "Grenada", + "Guadeloupe": "Guadeloupe", + "Guam": "Guam", + "Guatemala": "Guatemala", + "Guernsey": "Guernsey", + "Guinea": "Guinea", + "Guinea-Bissau": "Guinea-Bissau", + "Guyana": "Guyana", + "Haiti": "Haiti", + "Having second thoughts about cancelling your subscription? You can instantly reactivate your subscription at any time until the end of your current billing cycle. After your current billing cycle ends, you may choose an entirely new subscription plan.": "Haben Sie Bedenken, Ihr Abonnement zu kündigen? Sie können Ihr Abonnement jederzeit bis zum Ende Ihres aktuellen Abrechnungszeitraums sofort reaktivieren. Nach dem Ende Ihres aktuellen Abrechnungszeitraums können Sie einen völlig neuen Aboplan wählen.", + "Having second thoughts about cancelling your subscription? You can instantly reactive your subscription at any time until the end of your current billing cycle. After your current billing cycle ends, you may choose an entirely new subscription plan.": "Haben Sie Bedenken, Ihr Abonnement zu kündigen? Sie können Ihr Abonnement jederzeit bis zum Ende Ihres aktuellen Abrechnungszeitraums sofort reaktivieren. Nach dem Ende Ihres aktuellen Abrechnungszeitraums können Sie einen völlig neuen Aboplan wählen.", + "Heard Island & Mcdonald Islands": "Heard und McDonaldinseln", + "Heard Island and McDonald Islands": "Heard und McDonaldinseln", + "Hello!": "Hallo!", + "Hide Content": "Inhalt ausblenden", + "Hold Up!": "Moment mal!", + "Holy See (Vatican City State)": "Vatikanstadt", + "Honduras": "Honduras", + "Hong Kong": "Hongkong", + "Hungary": "Ungarn", + "I agree to the :terms_of_service and :privacy_policy": "Ich akzeptiere die :terms_of_service und die :privacy_policy", + "Iceland": "Island", + "ID": "ID", + "If necessary, you may log out of all of your other browser sessions across all of your devices. Some of your recent sessions are listed below; however, this list may not be exhaustive. If you feel your account has been compromised, you should also update your password.": "Bei Bedarf können Sie sich von allen anderen Browsersitzungen auf allen Ihren Geräten abmelden. Einige Ihrer letzten Sitzungen sind unten aufgelistet, diese Liste ist jedoch möglicherweise nicht vollständig. Wenn Sie der Meinung sind, dass Ihr Konto kompromittiert wurde, sollten Sie auch Ihr Kennwort aktualisieren.", + "If you already have an account, you may accept this invitation by clicking the button below:": "Wenn Sie bereits ein Konto haben, können Sie diese Einladung annehmen, indem Sie auf die Schaltfläche unten klicken:", + "If you did not create an account, no further action is required.": "Wenn Sie kein Konto erstellt haben, sind keine weiteren Handlungen nötig.", + "If you did not expect to receive an invitation to this team, you may discard this email.": "Wenn Sie keine Einladung zu diesem Team erwartet haben, kann die E-Mail gelöscht werden.", + "If you did not receive the email": "Wenn Sie die E-Mail nicht erhalten haben", + "If you did not request a password reset, no further action is required.": "Wenn Sie kein Zurücksetzen des Passworts beantragt haben, sind keine weiteren Handlungen nötig.", + "If you do not have an account, you may create one by clicking the button below. After creating an account, you may click the invitation acceptance button in this email to accept the team invitation:": "Wenn Sie kein Konto haben, können Sie ein Konto erstellen, indem Sie auf die Schaltfläche unten klicken. Nach dem Erstellen eines Kontos können Sie in dieser E-Mail auf die Schaltfläche zur Annahme der Einladung klicken, um die Teameinladung anzunehmen:", + "If you need to add specific contact or tax information to your invoices, like your full business name, VAT identification number, or address of record, you may add it here.": "Wenn Sie Ihren Rechnungen bestimmte Kontakt- oder Steuerinformationen hinzufügen müssen, z. B. Ihren vollständigen Firmennamen, Ihre Umsatzsteuer-Identifikationsnummer oder Ihre Anschrift, können Sie diese hier hinzufügen.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Sollten Sie Schwierigkeiten haben, die Schaltfläche \":actionText\" zu klicken, kopieren Sie den nachfolgenden Link\n in Ihre Adresszeile des Browsers.", + "Impersonate": "Imitieren", + "Increase": "erhöhen", + "India": "Indien", + "Indonesia": "Indonesien", + "Invalid filename.": "Ungültiger Dateiname.", + "Invalid JSON was returned from the route.": "Von der Route wurde ein ungültiger JSON-Code zurückgegeben.", + "Invoice Email Addresses": "E-Mail-Adressen für Rechnungen", + "Invoice emails updated successfully.": "Rechnungs-E-Mails wurden erfolgreich aktualisiert.", + "Invoices": "Rechnungen", + "Iran, Islamic Republic Of": "Iran", + "Iran, Islamic Republic of": "Iran", + "Iraq": "Irak", + "Ireland": "Irland", + "Isle Of Man": "Isle of Man", + "Isle of Man": "Isle of Man", + "Israel": "Israel", + "It looks like you do not have an active subscription. You may choose one of the subscription plans below to get started. Subscription plans may be changed or cancelled at your convenience.": "Es sieht so aus, als hätten Sie kein aktives Abonnement. Sie können einen der unten aufgeführten Abonnementpläne wählen, um zu beginnen. Abonnementpläne können jederzeit geändert oder gekündigt werden.", + "Italy": "Italien", + "Jamaica": "Jamaika", + "January": "Januar", + "Japan": "Japan", + "Jersey": "Jersey", + "Jordan": "Jordanien", + "July": "Juli", + "June": "Juni", + "Kazakhstan": "Kasachstan", + "Kenya": "Kenia", + "Key": "Schlüssel", + "Kiribati": "Kiribati", + "Korea": "Südkorea", + "Korea, Democratic People's Republic of": "Nordkorea", + "Korea, Republic of": "Republik Korea", + "Kosovo": "Kosovo", + "Kuwait": "Kuwait", + "Kyrgyzstan": "Kirgisistan", + "Lao People's Democratic Republic": "Laos", + "Last active": "Zuletzt aktiv", + "Last used": "Zuletzt verwendet", + "Latvia": "Lettland", + "Leave": "Verlassen", + "Leave Team": "Team verlassen", + "Lebanon": "Libanon", + "length": "Länge", + "Lens": "Lens", + "Lesotho": "Lesotho", + "Liberia": "Liberia", + "Libyan Arab Jamahiriya": "Libyen", + "Liechtenstein": "Liechtenstein", + "Light": "Hell", + "Lithuania": "Litauen", + "Load :perPage More": ":perPage weitere laden", + "Loading": "Wird geladen", + "Location": "Standort", + "Log in": "Einloggen", + "Log In": "Einloggen", + "Log Out": "Abmelden", + "Log out": "Ausloggen", + "Log Out Other Browser Sessions": "Andere Browser-Sitzungen abmelden", + "Log Viewer": "Protokollanzeige", + "Login": "Anmelden", + "Logout": "Abmelden", + "Logs": "Protokolle", + "Luxembourg": "Luxemburg", + "Macao": "Macao", + "Macedonia": "Nordmazedonien", + "Macedonia, the former Yugoslav Republic of": "Republik Nordmazedonien", + "Madagascar": "Madagaskar", + "Malawi": "Malawi", + "Malaysia": "Malaysia", + "Maldives": "Malediven", + "Mali": "Mali", + "Malta": "Malta", + "Manage Account": "Account verwalten", + "Manage and log out your active sessions on other browsers and devices.": "Verwalten und Abmelden Ihrer aktiven Sitzungen in anderen Browsern und auf anderen Geräten.", + "Manage API Tokens": "API-Token verwalten", + "Manage Role": "Rolle verwalten", + "Manage Team": "Team verwalten", + "Managing billing for :billableName": "Verwalten der Abrechnung für :billableName", + "March": "März", + "Mark all as Read": "Alle als gelesen markieren", + "Mark all notifications as read": "Alle Benachrichtigungen als gelesen markieren", + "Mark Read": "Als gelesen markieren", + "Mark Unread": "Als ungelesen markieren", + "Marshall Islands": "Marshallinseln", + "Martinique": "Martinique", + "Mauritania": "Mauretanien", + "Mauritius": "Mauritius", + "May": "Mai", + "Mayotte": "Mayotte", + "Mexico": "Mexiko", + "Micronesia, Federated States Of": "Föderierte Staaten von Mikronesien", + "Micronesia, Federated States of": "Föderierte Staaten von Mikronesien", + "Moldova": "Moldawien", + "Moldova, Republic of": "Republik Moldau", + "Monaco": "Monaco", + "Mongolia": "Mongolei", + "Montenegro": "Montenegro", + "Month To Date": "Monat bis dato", + "Monthly": "Monatlich", + "monthly": "monatlich", + "Montserrat": "Montserrat", + "Morocco": "Marokko", + "Mozambique": "Mosambik", + "Myanmar": "Myanmar", + "Name": "Name", + "name": "name", + "Namibia": "Namibia", + "Nauru": "Nauru", + "Nepal": "Nepal", + "Netherlands": "Niederlande", + "Netherlands Antilles": "Niederländische Antillen", + "Nevermind": "Macht nichts", + "Nevermind, I'll keep my old plan": "Macht nichts, ich behalte meinen alten Tarif", + "New": "Neu", + "New :resource": "Neu :resource", + "New Caledonia": "Neukaledonien", + "New Password": "Neues Passwort", + "New Zealand": "Neuseeland", + "Next": "Nächste", + "Next Payment": "Nächste Zahlung", + "Next Payment on": "Nächste Zahlung an", + "Nicaragua": "Nicaragua", + "Niger": "Niger", + "Nigeria": "Nigeria", + "Niue": "Niue", + "No": "Keine", + "No :resource matched the given criteria.": "Keine :resource entsprach den angegebenen Kriterien.", + "No additional information...": "Keine zusätzlichen Informationen...", + "No Current Data": "Keine aktuellen Daten", + "No Data": "Keine Daten", + "no file selected": "keine Datei ausgewählt", + "No Increase": "Keine Erhöhung", + "No payment methods on file.": "Keine Zahlungsmethoden hinterlegt.", + "No payment scheduled.": "Keine Zahlung geplant.", + "No Prior Data": "Keine vorherigen Daten", + "No Results Found.": "Keine Ergebnisse gefunden.", + "Norfolk Island": "Norfolkinsel", + "Northern Mariana Islands": "Nördliche Marianen", + "Norway": "Norwegen", + "Not Found": "Nicht gefunden", + "Notifications": "Benachrichtigungen", + "Nova": "Nova", + "Nova User": "Nova Benutzer", + "November": "November", + "October": "Oktober", + "of": "von", + "OK": "OK", + "Oman": "Oman", + "Once a team is deleted, all of its resources and data will be permanently deleted. Before deleting this team, please download any data or information regarding this team that you wish to retain.": "Sobald ein Team gelöscht wird, werden alle Ressourcen und Daten dauerhaft gelöscht. Laden Sie vor dem Löschen dieses Teams alle Daten oder Informationen zu diesem Team herunter, die Sie behalten möchten.", + "Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.": "Sobald Ihr Konto gelöscht wurde, werden alle Ressourcen und Daten dauerhaft gelöscht. Laden Sie vor dem Löschen Ihres Kontos alle Daten oder Informationen herunter, die Sie behalten möchten.", + "Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Sobald Ihr Konto gelöscht wurde, werden alle Ressourcen und Daten dauerhaft gelöscht. Bitte geben Sie Ihr Passwort zur Bestätigung ein, dass Sie Ihr Konto dauerhaft löschen möchten.", + "Only Trashed": "Nur gelöschte", + "Open Invoices": "Offene Rechnungen", + "Original": "Ursprünglich", + "Our billing management portal allows you to conveniently manage your subscription plan, payment method, and download your recent invoices.": "In unserem Portal zur Rechnungsverwaltung können Sie bequem Ihren Abonnementplan und Ihre Zahlungsmethode verwalten und Ihre letzten Rechnungen herunterladen.", + "Our billing management portal allows you to conveniently manage your subscription plan, payment methods, and download your recent invoices.": "Unser Abrechnungsverwaltungsportal ermöglicht es Ihnen, Ihren Abonnementplan und Ihre Zahlungsmethoden bequem zu verwalten und Ihre letzten Rechnungen herunterzuladen.", + "Page Expired": "Seite abgelaufen", + "Pagination Navigation": "Seiten-Navigation", + "Paid": "Bezahlt", + "Pakistan": "Pakistan", + "Palau": "Palau", + "Palestinian Territory, Occupied": "Palästinensische Autonomiegebiete", + "Panama": "Panama", + "Papua New Guinea": "Papua-Neuguinea", + "Paraguay": "Paraguay", + "password": "passwort", + "Password": "Passwort", + "Payment Confirmation": "Zahlungsbestätigung", + "Payment Information": "Informationen zur Zahlung", + "Payment information updated successfully.": "Zahlungsinformationen erfolgreich aktualisiert.", + "Payment Method": "Zahlungsmethode", + "Payment Methods": "Zahlungsarten", + "Payment Required": "Zahlung erforderlich", + "Payments": "Zahlungen", + "Pending Team Invitations": "Ausstehende Team Einladungen", + "Per Page": "Pro Seite", + "Permanently delete this team.": "Löschen Sie dieses Team dauerhaft.", + "Permanently delete your account.": "Löschen Sie Ihren Account dauerhaft.", + "Permissions": "Berechtigungen", + "Peru": "Peru", + "Philippines": "Philippinen", + "Photo": "Foto", + "Pitcairn": "Pitcairninseln", + "Please accept the terms of service.": "Bitte akzeptieren Sie die Servicebedingungen.", + "Please click the button below to verify your email address.": "Bitte klicken Sie auf die Schaltfläche, um Ihre E-Mail-Adresse zu bestätigen.", + "Please confirm access to your account by entering one of your emergency recovery codes.": "Bitte bestätigen Sie den Zugriff auf Ihr Konto, indem Sie einen Ihrer Notfall-Wiederherstellungscodes eingeben.", + "Please confirm access to your account by entering the authentication code provided by your authenticator application.": "Bitte bestätigen Sie den Zugriff auf Ihr Konto, indem Sie den von Ihrer Authentifizierungsanwendung bereitgestellten Authentifizierungscode eingeben.", + "Please confirm your password before continuing.": "Bitte bestätigen Sie Ihr Passwort, bevor Sie fortfahren.", + "Please copy your new API token. For your security, it won't be shown again.": "Bitte kopieren Sie Ihren neuen API-Token. Zu Ihrer Sicherheit wird er nicht mehr angezeigt", + "Please enter your password to confirm you would like to log out of your other browser sessions across all of your devices.": "Bitte geben Sie Ihr Passwort ein, um zu bestätigen, dass Sie sich von Ihren anderen Browser-Sitzungen auf allen Ihren Geräten abmelden möchten.", + "Please provide a maximum of three invoice emails addresses.": "Bitte geben Sie maximal drei Rechnungs-E-Mail-Adressen an.", + "Please provide the email address of the person you would like to add to this team.": "Bitte geben Sie die E-Mail-Adresse der Person an, die Sie diesem Team hinzufügen möchten.", + "Please set a default payment method before retrying payments.": "Bitte legen Sie eine Standardzahlungsmethode fest, bevor Sie Zahlungen erneut versuchen.", + "Please set a default payment method before swapping plans.": "Bitte legen Sie eine Standardzahlungsmethode fest, bevor Sie Pläne wechseln.", + "Poland": "Polen", + "Portugal": "Portugal", + "Press / to search": "Drücken Sie / zum Suchen", + "Preview": "Vorschau", + "Previewing": "Vorschau auf", + "Previous": "Vorherige", + "Privacy Policy": "Datenschutzerklärung", + "Profile": "Profil", + "Profile Information": "Profilinformationen", + "Puerto Rico": "Puerto Rico", + "Qatar": "Katar", + "Quarter To Date": "Quartal bis dato", + "Recovery Code": "Wiederherstellungscode", + "Refresh": "Aktualisieren", + "Regards,": "Mit freundlichen Grüßen,", + "Regenerate Recovery Codes": "Wiederherstellungscodes neu generieren", + "Register": "Registrieren", + "Reload": "Neu laden", + "Remember me": "Angemeldet bleiben", + "Remember Me": "Angemeldet bleiben", + "Remove": "Entfernen", + "Remove Photo": "Foto entfernen", + "Remove Team Member": "Teammitglied entfernen", + "Replicate": "Replizieren", + "Required fields": "Benötigte Felder", + "Resend Verification Email": "Bestätigungslink erneut senden", + "Reset Filters": "Filter zurücksetzen", + "Reset Password": "Passwort zurücksetzen", + "Reset Password Notification": "Benachrichtigung zum Zurücksetzen des Passworts", + "resource": "Ressource", + "Resource Row Dropdown": "Ressourcenleiste Dropdown", + "Resources": "Ressourcen", + "resources": "Ressourcen", + "Restore": "Wiederherstellen", + "Restore :resource": "Wiederherstellen :resource", + "Restore Resource": "Ressource wiederherstellen", + "Restore Selected": "Ausgewählte wiederherstellen", + "results": "Ergebnissen", + "Resume Subscription": "Abonnement fortsetzen", + "Retry Payment": "Zahlung erneut versuchen", + "Return to :appName": "Rückkehr zu :appName", + "Reunion": "Réunion", + "Role": "Rolle", + "Romania": "Rumänien", + "Run Action": "Aktion ausführen", + "Russian Federation": "Russische Föderation", + "Rwanda": "Ruanda", + "Réunion": "Réunion", + "Saint Barthelemy": "Saint-Barthélemy", + "Saint Barthélemy": "Saint-Barthélemy", + "Saint Helena": "St. Helena", + "Saint Kitts And Nevis": "St. Kitts und Nevis", + "Saint Kitts and Nevis": "St. Kitts und Nevis", + "Saint Lucia": "St. Lucia", + "Saint Martin": "St. Martin", + "Saint Martin (French part)": "Saint-Martin", + "Saint Pierre And Miquelon": "Saint-Pierre und Miquelon", + "Saint Pierre and Miquelon": "Saint-Pierre und Miquelon", + "Saint Vincent And Grenadines": "St. Vincent und die Grenadinen", + "Saint Vincent and the Grenadines": "St. Vincent und die Grenadinen", + "Samoa": "Samoa", + "San Marino": "San Marino", + "Sao Tome And Principe": "São Tomé und Príncipe", + "Sao Tome and Principe": "São Tomé und Príncipe", + "Saudi Arabia": "Saudi-Arabien", + "Save": "Speichern", + "Saved.": "Gespeichert.", + "Scroll to bottom": "Zum Ende scrollen", + "Scroll to top": "Zum Anfang scrollen", + "Search": "Suchen", + "Secure Area": "Geschützter Bereich", + "Select": "Wählen Sie", + "Select a different plan": "Wählen Sie einen anderen Plan", + "Select a log file...": "Protokolldatei auswählen...", + "Select A New Photo": "Wählen Sie ein neues Foto aus", + "Select Action": "Aktion auswählen", + "Select all": "Alles auswählen", + "Select All Dropdown": "Alle Dropdowns auswählen", + "Select this page": "Seite auswählen", + "Send Password Reset Link": "Link zum Zurücksetzen des Passworts senden", + "Senegal": "Senegal", + "September": "September", + "Serbia": "Serbien", + "Server Error": "Interner Fehler", + "Service Unavailable": "Service nicht verfügbar", + "Set as default": "Als Standard einstellen", + "Setup Key": "Einrichtungsschlüssel", + "Seychelles": "Seychellen", + "Show All Fields": "Alle Felder anzeigen", + "Show Content": "Inhalt anzeigen", + "Show Recovery Codes": "Zeige die Wiederherstellungscodes", + "Showing": "Zeige", + "Sierra Leone": "Sierra Leone", + "Signed in as": "Eingetragen als", + "Singapore": "Singapur", + "Sint Maarten (Dutch part)": "Sint Maarten", + "Slovakia": "Slowakei", + "Slovenia": "Slowenien", + "Soft Deleted": "Vorläufig gelöscht", + "Solomon Islands": "Salomon-Inseln", + "Somalia": "Somalia", + "Something went wrong.": "Da ist etwas schief gelaufen.", + "Sorry! You are not authorized to perform this action.": "Entschuldigung! Sie sind nicht berechtigt, diese Aktion durchzuführen.", + "Sorry, your session has expired.": "Entschuldigung, Ihre Sitzung ist abgelaufen.", + "South Africa": "Südafrika", + "South Georgia And Sandwich Isl.": "Südgeorgien und die Südlichen Sandwichinseln", + "South Georgia and the South Sandwich Islands": "Südgeorgien und die Südlichen Sandwichinseln", + "South Sudan": "Südsudan", + "Spain": "Spanien", + "Sri Lanka": "Sri Lanka", + "Standalone Actions": "Standalone Aktionen", + "Start Polling": "Abruf starten", + "Start polling": "Abruf starten", + "State / County": "Bundesland", + "Stop Impersonating": "Imitieren stoppen", + "Stop Polling": "Abruf stoppen", + "Stop polling": "Abruf stoppen", + "Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.": "Speichern Sie diese Wiederherstellungscodes in einem sicheren Passwortmanager. Sie können verwendet werden, um den Zugriff auf Ihr Konto wiederherzustellen, wenn Ihr Zwei-Faktor-Authentifizierungsgerät verloren geht.", + "Subscribe": "Abonnieren", + "Subscription Information": "Informationen zum Abonnement", + "Subscription Pending": "Abonnement ausstehend", + "Sudan": "Sudan", + "Suriname": "Suriname", + "Svalbard And Jan Mayen": "Svalbard und Jan Mayen", + "Svalbard and Jan Mayen": "Svalbard und Jan Mayen", + "Swaziland": "Eswatini", + "Sweden": "Schweden", + "Switch Teams": "Teams wechseln", + "Switzerland": "Schweiz", + "Syrian Arab Republic": "Arabische Republik Syrien", + "System": "System", + "Taiwan": "Taiwan", + "Taiwan, Province of China": "Republik China (Taiwan)", + "Tajikistan": "Tadschikistan", + "Tanzania": "Tansania", + "Tanzania, United Republic of": "Vereinigte Republik Tansania", + "TAX": "STEUER", + "Team Details": "Teamdetails", + "Team Invitation": "Teameinladung", + "Team Members": "Teammitglieder", + "Team Name": "Teamname", + "Team Owner": "Teambesitzer", + "Team Settings": "Teameinstellungen", + "Terms of Service": "Nutzungsbedingungen", + "Thailand": "Thailand", + "Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.": "Vielen Dank für Ihre Registrierung! Bevor Sie loslegen, möchten wir Sie bitten Ihre E-Mail-Adresse zu verifizieren, indem Sie auf den Link klicken, den wir Ihnen per E-Mail zugeschickt haben. Wenn Sie die E-Mail nicht erhalten haben, senden wir Ihnen gerne eine weitere zu.", + "Thanks for your continued support. We've attached a copy of your invoice for your records. Please let us know if you have any questions or concerns.": "Vielen Dank für Ihre kontinuierliche Unterstützung. Wir haben eine Kopie Ihrer Rechnung für Ihre Unterlagen beigefügt. Bitte lassen Sie uns wissen, wenn Sie irgendwelche Fragen oder Bedenken haben.", + "Thanks,": "Vielen Dank,", + "The :attribute must be a valid role.": ":Attribute muss eine gültige Rolle sein.", + "The :attribute must be at least :length characters and contain at least one number.": ":Attribute muss aus mindestens :length Zeichen bestehen und mindestens eine Zahl enthalten.", + "The :attribute must be at least :length characters and contain at least one special character and one number.": ":Attribute muss mindestens :length Zeichen lang sein und mindestens ein Sonderzeichen und eine Zahl enthalten.", + "The :attribute must be at least :length characters and contain at least one special character.": ":Attribute muss aus mindestens :length Zeichen bestehen und mindestens ein Sonderzeichen enthalten.", + "The :attribute must be at least :length characters and contain at least one uppercase character and one number.": ":Attribute muss aus mindestens :length Zeichen bestehen und mindestens einen Großbuchstaben und eine Zahl enthalten.", + "The :attribute must be at least :length characters and contain at least one uppercase character and one special character.": ":Attribute muss aus mindestens :length Zeichen bestehen und mindestens einen Großbuchstaben und ein Sonderzeichen enthalten.", + "The :attribute must be at least :length characters and contain at least one uppercase character, one number, and one special character.": ":Attribute muss aus mindestens :length Zeichen bestehen und mindestens einen Großbuchstaben, eine Zahl und ein Sonderzeichen enthalten.", + "The :attribute must be at least :length characters and contain at least one uppercase character.": ":Attribute muss aus mindestens :length Zeichen bestehen und mindestens einen Großbuchstaben enthalten.", + "The :attribute must be at least :length characters.": ":Attribute muss aus mindestens :length Zeichen bestehen.", + "The :attribute must contain at least one letter.": ":Attribute muss aus mindestens einem Zeichen bestehen.", + "The :attribute must contain at least one number.": ":Attribute muss aus mindestens einer Zahl bestehen.", + "The :attribute must contain at least one symbol.": ":Attribute muss aus mindestens einem Sonderzeichen bestehen.", + "The :attribute must contain at least one uppercase and one lowercase letter.": ":Attribute muss aus mindestens einem Groß- und einem Kleinbuchstaben bestehen.", + "The :resource was created!": ":Resource wurde erstellt!", + "The :resource was deleted!": ":Resource wurde gelöscht!", + "The :resource was restored!": ":Resource wurde wiederhergestellt!", + "The :resource was updated!": ":Resource wurde aktualisiert!", + "The action was executed successfully.": "Die Aktion wurde erfolgreich ausgeführt.", + "The default payment method cannot be removed.": "Die Standardzahlungsmethode kann nicht entfernt werden.", + "The file was deleted!": "Die Datei wurde gelöscht!", + "The given :attribute has appeared in a data leak. Please choose a different :attribute.": "Das :attribute ist bereits in einem Datenleck aufgetaucht. Bitte wähle ein anderes :attribute.", + "The given data was invalid.": "Die gegebenen Daten waren ungültig.", + "The government won't let us show you what's behind these doors": "Wir dürfen Ihnen nicht zeigen, was sich hinter diesen Türen verbirgt", + "The HasOne relationship has already been filled.": "Die HasOne-Beziehung wurde bereits befüllt.", + "The image could not be loaded": "Das Bild konnte nicht geladen werden", + "The image could not be loaded.": "Das Bild konnte nicht geladen werden.", + "The invoice emails must be valid email addresses.": "Die Rechnungs-E-Mails müssen gültige E-Mail-Adressen sein.", + "The password is incorrect.": "Das Passwort ist falsch.", + "The provided coupon code is invalid.": "Der angegebene Gutscheincode ist ungültig.", + "The provided password does not match your current password.": "Das angegebene Passwort stimmt nicht mit Ihrem aktuellen Passwort überein.", + "The provided password was incorrect.": "Das angegebene Passwort war falsch.", + "The provided two factor authentication code was invalid.": "Der angegebene Zwei-Faktor-Authentifizierungscode war ungültig.", + "The provided two factor recovery code was invalid.": "Der angegebene Zwei-Faktor-Wiederherstellungscode war ungültig.", + "The provided VAT number is invalid.": "Die angegebene Umsatzsteuer-Identifikationsnummer ist ungültig.", + "The resource was attached!": "Die Ressource wurde angehängt!", + "The resource was prevented from being saved!": "Die Ressource konnte nicht gespeichert werden!", + "The resource was updated!": "Die Ressource wurde aktualisiert!", + "The response is not a streamed response.": "Die Antwort ist keine gestreamte Antwort.", + "The response is not a view.": "Die Antwort ist keine Ansicht.", + "The selected country is invalid.": "Das gewählte Land ist ungültig.", + "The selected plan is invalid.": "Der gewählte Plan ist ungültig.", + "The selected resources have been :action!": "Die ausgewählten Ressourcen wurden :action!", + "The team's name and owner information.": "Teamname und Informationen zum Besitzer.", + "There are no available options for this resource.": "Es gibt keine verfügbaren Optionen für diese Ressource.", + "There are no fields to display.": "Es gibt keine Felder zum Anzeigen.", + "There are no new notifications.": "Es gibt keine neuen Benachrichtigungen.", + "There was a problem executing the action.": "Es gab ein Problem beim Ausführen der Aktion.", + "There was a problem fetching the resource.": "Es gab ein Problem beim Anfordern der Ressource.", + "There was a problem submitting the form.": "Es gab ein Problem beim Absenden des Formulars.", + "These people have been invited to your team and have been sent an invitation email. They may join the team by accepting the email invitation.": "Diese Personen wurden zu Ihrem Team eingeladen und haben eine Einladungs-E-Mail erhalten. Sie können dem Team beitreten, indem sie die E-Mail-Einladung annehmen.", + "This account does not have an active subscription.": "Dieses Konto hat kein aktives Abonnement.", + "This action is unauthorized.": "Diese Aktion ist nicht autorisiert.", + "This copy of Nova is unlicensed.": "Diese Installation von Nova ist nicht lizenziert.", + "This coupon code can only be used by new customers.": "Dieser Gutscheincode kann nur von Neukunden verwendet werden.", + "This device": "Dieses Gerät", + "This file field is read-only.": "Dieses Dateifeld ist schreibgeschützt.", + "This invoice is no longer open.": "Diese Rechnung ist nicht mehr offen.", + "This is a secure area of the application. Please confirm your password before continuing.": "Dies ist ein sicherer Bereich der Anwendung. Bitte geben Sie Ihr Passwort ein, bevor Sie fortfahren.", + "This password does not match our records.": "Dieses Passwort ist uns nicht bekannt.", + "This password reset link will expire in :count minutes.": "Dieser Link zum Zurücksetzen des Passworts läuft in :count Minuten ab.", + "This payment was initiated, but the funds have not been received yet. This can take up to 14 days.": "Diese Zahlung wurde veranlasst, aber das Geld ist noch nicht eingegangen. Dies kann bis zu 14 Tage dauern.", + "This resource no longer exists": "Diese Ressource existiert nicht mehr", + "This subscription has expired and cannot be resumed. Please create a new subscription.": "Dieses Abonnement ist abgelaufen und kann nicht wiederaufgenommen werden. Bitte legen Sie ein neues Abonnement an.", + "This user already belongs to the team.": "Dieser Benutzer gehört bereits zum Team.", + "This user has already been invited to the team.": "Dieser Benutzer wurde bereits in dieses Team eingeladen.", + "Timor-Leste": "Osttimor", + "to": "bis", + "To": "Bis", + "To finish enabling two factor authentication, scan the following QR code using your phone's authenticator application or enter the setup key and provide the generated OTP code.": "Um die Aktivierung der Zwei-Faktor-Authentifizierung abzuschließen, scannen Sie den folgenden QR-Code mit der Authentifizierungsanwendung Ihres Smartphones oder geben Sie den Einrichtungsschlüssel ein und geben Sie den generierten OTP-Code ein.", + "Today": "Heute", + "Toggle navigation": "Navigation umschalten", + "Togo": "Togo", + "Tokelau": "Tokelau", + "Token Name": "Tokenname", + "Tonga": "Tonga", + "Too Many Requests": "Zu viele Anfragen", + "total": "gesamt", + "Total:": "Gesamt:", + "Trashed": "Gelöscht", + "Trinidad And Tobago": "Trinidad und Tobago", + "Trinidad and Tobago": "Trinidad und Tobago", + "Tunisia": "Tunesien", + "Turkey": "Türkei", + "Turkmenistan": "Turkmenistan", + "Turks And Caicos Islands": "Turks- und Caicosinseln", + "Turks and Caicos Islands": "Turks- und Caicosinseln", + "Tuvalu": "Tuvalu", + "Two Factor Authentication": "Zwei-Faktor-Authentifizierung", + "Two factor authentication is now enabled. Scan the following QR code using your phone's authenticator application or enter the setup key.": "Die Zwei-Faktor-Authentifizierung ist jetzt aktiviert. Scannen Sie den folgenden QR-Code mit der Authentifizierungsanwendung Ihres Smartphones oder geben Sie den Einrichtungsschlüssel ein.", + "Type": "Typ", + "Uganda": "Uganda", + "Ukraine": "Ukraine", + "Unauthorized": "Nicht autorisiert", + "United Arab Emirates": "Vereinigte Arabische Emirate", + "United Kingdom": "Vereinigtes Königreich", + "United States": "Vereinigte Staaten", + "United States Minor Outlying Islands": "Kleinere Amerikanische Überseeinseln", + "United States Outlying Islands": "Kleinere Amerikanische Überseeinseln", + "Unknown": "Unbekannt", + "Unpaid": "Unbezahlt", + "Update": "Aktualisieren", + "Update & Continue Editing": "Aktualisieren & Weiterbearbeiten", + "Update :resource": ":Resource aktualisieren", + "Update :resource: :title": ":Resource aktualisieren: :title", + "Update attached :resource: :title": "Angehängte :resource aktualisieren: :title", + "Update Password": "Passwort aktualisieren", + "Update Payment Information": "Zahlungsinformationen aktualisieren", + "Update Payment Method": "Zahlungsmethode aktualisieren", + "Update your account's profile information and email address.": "Aktualisieren Sie die Profilinformationen und die E-Mail-Adresse Ihres Kontos.", + "Uploading": "Hochladen", + "Uploading files... (:current/:total)": "Dateien werden hochgeladen... (:current/:total)", + "Uruguay": "Uruguay", + "Use a recovery code": "Verwenden Sie einen Wiederherstellungscode", + "Use an authentication code": "Verwenden Sie einen Authentifizierungscode", + "User Actions": "Benutzeraktionen", + "User Security": "Benutzersicherheit", + "Username": "Benutzername", + "Uzbekistan": "Usbekistan", + "Value": "Wert", + "Vanuatu": "Vanuatu", + "VAT Number": "Umsatzsteuer-Identifikationsnummer", + "Venezuela": "Venezuela", + "Venezuela, Bolivarian Republic of": "Bolivarische Republik Venezuela", + "Verify Email Address": "E-Mail-Adresse bestätigen", + "Verify Your Email Address": "Überprüfen Sie Ihre E-Mail-Adresse", + "Viet Nam": "Vietnam", + "View": "Ansicht", + "Virgin Islands, British": "Britische Jungferninseln", + "Virgin Islands, U.S.": "Amerikanische Jungferninseln", + "Wallis And Futuna": "Wallis und Futuna", + "Wallis and Futuna": "Wallis und Futuna", + "We are processing your subscription. Once the subscription has successfully processed, this page will update automatically. Typically, this process should only take a few seconds.": "Wir bearbeiten Ihr Abonnement. Sobald das Abonnement erfolgreich verarbeitet wurde, wird diese Seite automatisch aktualisiert. Normalerweise sollte dieser Vorgang nur wenige Sekunden dauern.", + "We are unable to process your payment. Please contact customer support.": "Wir können Ihre Zahlung nicht bearbeiten. Bitte kontaktieren Sie den Kundensupport.", + "We have emailed your password reset link!": "Wir haben Ihnen den Link zum Zurücksetzen Ihres Passworts per E-Mail zugeschickt!", + "We were unable to find a registered user with this email address.": "Wir konnten keinen registrierten Benutzer mit dieser E-Mail-Adresse finden.", + "We will send an invoice download link to the email addresses that you specify below. You may separate multiple email addresses using commas.": "Wir senden einen Link zum Herunterladen der Rechnung an die von Ihnen unten angegebenen E-Mail-Adressen. Sie können mehrere E-Mail-Adressen durch Kommata trennen.", + "We're lost in space. The page you were trying to view does not exist.": "Wir sind im Weltraum verloren. Die Seite, die Sie aufrufen wollten, existiert nicht.", + "Welcome Back!": "Willkommen zurück!", + "Western Sahara": "Westsahara", + "When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone's Google Authenticator application.": "Wenn die Zwei-Faktor-Authentifizierung aktiviert ist, werden Sie während der Authentifizierung zur Eingabe eines sicheren, zufälligen Tokens aufgefordert. Sie können dieses Token in der Google Authenticator-Anwendung Ihres Telefons abrufen.", + "Whoops": "Ups", + "Whoops!": "Ups!", + "Whoops! Something went wrong.": "Ups, etwas ist schief gelaufen.", + "With Trashed": "Mit gelöschten", + "Write": "Schreiben", + "Year To Date": "Jahr bis dato", + "Yearly": "Jährlich", + "Yemen": "Jemen", + "Yes": "Ja", + "You are already subscribed.": "Sie sind bereits angemeldet.", + "You are currently within your free trial period. Your trial will expire on :date.": "Sie befinden sich derzeit in Ihrem kostenlosen Testzeitraum. Ihre Testphase läuft am :date ab.", + "You are currently within your free trial period. Your trial will expire on :date. Starting a new subscription will end your trial.": "Sie befinden sich derzeit in Ihrer kostenlosen Testphase. Ihre Testversion läuft am :date.. ab. Wenn Sie ein neues Abonnement starten, endet Ihre Testversion.", + "You are logged in!": "Sie sind eingeloggt!", + "You are receiving this email because we received a password reset request for your account.": "Sie erhalten diese E-Mail, weil wir einen Antrag auf eine Zurücksetzung Ihres Passworts bekommen haben.", + "You have been invited to join the :team team!": "Sie wurden eingeladen dem Team :team beizutreten!", + "You have enabled two factor authentication.": "Sie haben die Zwei-Faktor-Authentifizierung aktiviert.", + "You have not enabled two factor authentication.": "Sie haben die Zwei-Faktor-Authentifizierung nicht aktiviert.", + "You have some unpaid invoices. After updating your default payment method, you may retry the payments via the invoice list below.": "Sie haben einige unbezahlte Rechnungen. Nachdem Sie Ihre Standardzahlungsmethode aktualisiert haben, können Sie die Zahlungen über die folgende Rechnungsliste erneut versuchen.", + "You may accept this invitation by clicking the button below:": "Sie können diese Einladung annehmen, indem Sie auf die Schaltfläche unten klicken:", + "You may cancel your subscription at any time. Once your subscription has been cancelled, you will have the option to resume the subscription until the end of your current billing cycle.": "Sie können Ihr Abonnement jederzeit kündigen. Sobald Ihr Abonnement gekündigt wurde, haben Sie die Möglichkeit, das Abonnement bis zum Ende des aktuellen Abrechnungszyklus fortzusetzen.", + "You may delete any of your existing tokens if they are no longer needed.": "Sie können alle vorhandenen Token löschen, wenn sie nicht mehr benötigt werden.", + "You may not delete your personal team.": "Sie können Ihr persönliches Team nicht löschen.", + "You may not leave a team that you created.": "Sie können ein von Ihnen erstelltes Team nicht verlassen.", + "You will receive an invoice and payment link via email for each billing period.": "Sie erhalten für jeden Abrechnungszeitraum eine Rechnung und einen Zahlungslink per E-Mail.", + "You're logged in!": "Sie sind eingeloggt!", + "Your :invoiceName invoice is now available!": "Ihre :invoiceName Rechnung ist jetzt verfügbar!", + "Your billing address is :address :address2 :postal_code :city :state :country": "Ihre Rechnungsadresse lautet :address :address2 :postal_code :city :state :country", + "Your card was declined. Please contact your card issuer for more information.": "Ihre Karte wurde abgelehnt. Bitte kontaktieren Sie Ihren Kartenaussteller für weitere Informationen.", + "Your current payment method is a credit card ending in :lastFour that expires on :expiration.": "Ihre aktuelle Zahlungsmethode ist eine Kreditkarte mit der Endung :lastFour, die am :expiration ausläuft.", + "Your email address is unverified.": "Ihre E-Mail-Adresse ist nicht verifiziert.", + "Your last payment of :amount failed. Please update your payment method to retry the failed payment.": "Ihre letzte Zahlung von :amount ist fehlgeschlagen. Bitte aktualisieren Sie Ihre Zahlungsmethode, um die fehlgeschlagene Zahlung erneut zu versuchen.", + "Your last payment of :amount on :date failed. Please update your payment method to retry the failed payment.": "Ihre letzte Zahlung von :amount vom :date ist fehlgeschlagen. Bitte aktualisieren Sie Ihre Zahlungsmethode, um die fehlgeschlagene Zahlung erneut zu versuchen.", + "Your next payment of :amount will be processed on :date.": "Ihre nächste Zahlung von :amount erfolgt am :date.", + "Your payment method has been added successfully.": "Ihre Zahlungsmethode wurde erfolgreich hinzugefügt.", + "Your payment method will be charged automatically for each billing period.": "Ihre Zahlungsmethode wird automatisch für jeden Abrechnungszeitraum belastet.", + "Your registered VAT Number is :vatNumber.": "Ihre registrierte Umsatzsteuer-Identifikationsnummer lautet :vatNumber.", + "Your subscription has been started successfully.": "Ihr Abonnement wurde erfolgreich gestartet.", + "Your subscription has been successfully cancelled.": "Ihr Abonnement wurde erfolgreich gekündigt.", + "Your subscription has been successfully cancelled. You will still have access until the end of your billing period.": "Ihr Abonnement wurde erfolgreich gekündigt. Sie haben bis zum Ende Ihres Abrechnungszeitraums weiterhin Zugriff.", + "Your subscription was successfully resumed.": "Ihr Abonnement wurde erfolgreich fortgesetzt.", + "Your subscription was successfully updated.": "Ihr Abonnement wurde erfolgreich aktualisiert.", + "Zambia": "Sambia", + "Zimbabwe": "Simbabwe", + "Zip / Postal Code": "Postleitzahl", + "Åland Islands": "Åland", + "A reset link will be sent if the account exists.": "Wenn das Konto existiert, wird ein Link zum Zurücksetzen gesendet.", + "A Timeout Occurred": "Eine Zeitüberschreitung ist aufgetreten", + "Accept": "Akzeptieren", + "Accepted": "Akzeptiert", + "Add :name": ":name hinzufügen", + "Admin": "Administrator", + "Agree": "Zustimmen", + "Already Reported": "Bereits gemeldet", + "Archive": "Archiv", + "Assign": "Zuordnen", + "Associate": "Assoziieren", + "Bad Gateway": "Fehlerhaftes Gateway", + "Bad Request": "Ungültige Anfrage", + "Bandwidth Limit Exceeded": "Bandbreitenlimit überschritten", + "Browse": "Durchsuchen", + "Choose :name": "Wählen Sie :name", + "Choose Image": "Bild wählen", + "Click to copy": "Klicken Sie zum Kopieren", + "Client Closed Request": "Client hat die Anfrage geschlossen", + "Collapse": "Zusammenklappen", + "Collapse All": "Alle zusammenklappen", + "Comment": "Kommentar", + "Conflict": "Konflikt", + "Connect": "Verbinden", + "Connection Closed Without Response": "Verbindung ohne Antwort getrennt", + "Connection Timed Out": "Verbindungszeit überschritten", + "Continue": "Weiter", + "Create :name": ":name erstellen", + "Created": "Erstellt", + "Delete :name": ":name löschen", + "Discard": "Verwerfen", + "Done": "Erledigt", + "Down": "Runter", + "Duplicate": "Duplizieren", + "Duplicate :name": ":name duplizieren", + "Edit :name": ":name bearbeiten", + "Expand": "Erweitern", + "Expand All": "Alle erweitern", + "Expectation Failed": "Erwartung gescheitert", + "Explanation": "Erläuterung", + "Export": "Exportieren", + "Export :name": ":name exportieren", + "Failed Dependency": "Fehlgeschlagene Abhängigkeit", + "File": "Datei", + "Files": "Dateien", + "Found": "Gefunden", + "Gateway Timeout": "Gateway-Zeitüberschreitung", + "Gone": "Nicht mehr verfügbar", + "Hide": "Verstecken", + "Hide :name": ":name ausblenden", + "Home": "Startseite", + "HTTP Version Not Supported": "HTTP Version nicht unterstützt", + "I'm a teapot": "Ich bin eine Teekanne", + "IM Used": "IM verwendet", + "Image": "Bild", + "Impersonation": "Identitätswechsel", + "Import": "Importieren", + "Import :name": "Importieren Sie :name", + "Insufficient Storage": "Nicht genügend Speicherplatz", + "Internal Server Error": "Interner Serverfehler", + "Introduction": "Einführung", + "Invalid SSL Certificate": "Ungültiges SSL-Zertifikat", + "Length Required": "Längenangabe erforderlich", + "Like": "Wie", + "Load": "Belastung", + "Localize": "Lokalisieren", + "Locked": "Gesperrt", + "Loop Detected": "Endlosschleife erkannt", + "Maintenance Mode": "Wartungsmodus", + "Method Not Allowed": "Methode nicht erlaubt", + "Misdirected Request": "Fehlgeleitete Anfrage", + "Moved Permanently": "Permanent verschoben", + "Multi-Status": "Multistatus", + "Multiple Choices": "Mehrere Auswahlmöglichkeiten", + "Network Authentication Required": "Netzwerkauthentifizierung erforderlich", + "Network Connect Timeout Error": "Zeitüberschreitungsfehler bei Netzwerkverbindung", + "Network Read Timeout Error": "Zeitüberschreitungsfehler beim Lesen des Netzwerks", + "New :name": "Neu :name", + "No Content": "Kein Inhalt", + "Non-Authoritative Information": "Nicht maßgebende Informationen", + "Not Acceptable": "Nicht akzeptierbar", + "Not Extended": "Nicht erweitert", + "Not Implemented": "Nicht implementiert", + "Not Modified": "Nicht modifiziert", + "Open": "Offen", + "Open in a current window": "In einem aktuellen Fenster öffnen", + "Open in a new window": "In einem neuen Fenster öffnen", + "Open in a parent frame": "In einem übergeordneten Frame öffnen", + "Open in the topmost frame": "Im obersten Rahmen öffnen", + "Open on the website": "Auf der Website öffnen", + "Origin Is Unreachable": "Quelle ist nicht erreichbar", + "Partial Content": "Teilinhalt", + "Payload Too Large": "Nutzlast zu groß", + "Permanent Redirect": "Permanente Weiterleitung", + "Precondition Failed": "Vorbedingung fehlgeschlagen", + "Precondition Required": "Voraussetzung erforderlich", + "Price": "Preis", + "Processing": "In Bearbeitung", + "Proxy Authentication Required": "Proxy-Authentifizierung erforderlich", + "Railgun Error": "Railgun-Fehler", + "Range Not Satisfiable": "Bereich nicht erfüllbar", + "Record": "Aufzeichnen", + "Request Header Fields Too Large": "Anfrage-Header-Felder zu groß", + "Request Timeout": "Zeitüberschreitung der Anfrage", + "Reset Content": "Inhalt zurücksetzen", + "Restore :name": ":name wiederherstellen", + "Retry With": "Wiederhole mit", + "Save & Close": "Speichern und schließen", + "Save & Return": "Speichern und zurückgeben", + "Save :name": "Sparen Sie :name", + "Search :name": "Suche :name", + "See Other": "Siehe andere Seite", + "Select All": "Wählen Sie Alle", + "Send": "Schicken", + "Session Has Expired": "Sitzung ist abgelaufen", + "Settings": "Einstellungen", + "Show": "Zeigen", + "Show :name": ":name anzeigen", + "Show All": "Zeige alles", + "Sign In": "Anmelden", + "Solve": "Lösen", + "SSL Handshake Failed": "SSL Handshake fehlgeschlagen", + "Start": "Starten", + "status": "Status", + "Stop": "Stoppen", + "Submit": "Einreichen", + "Switch": "Wechseln", + "Switch To Role": "Zur Rolle wechseln", + "Switching Protocols": "Protokollwechsel", + "Tag": "Stichwort", + "Tags": "Stichworte", + "Temporary Redirect": "Temporäre Weiterleitung", + "Too Early": "Zu früh", + "Translate": "Übersetzen", + "Translate It": "Übersetze es", + "Unavailable For Legal Reasons": "Aus rechtlichen Gründen nicht verfügbar", + "Unknown Error": "Unbekannter Fehler", + "Unpack": "Auspacken", + "Unprocessable Entity": "Unverarbeitbare Entität", + "Unsubscribe": "Abbestellen", + "Unsupported Media Type": "Nicht unterstützter Medientyp", + "Up": "Hoch", + "Update :name": ":name aktualisieren", + "Upgrade Required": "Upgrade erforderlich", + "URI Too Long": "URI ist zu lang", + "Use Proxy": "Proxy verwenden", + "User": "Benutzer", + "Variant Also Negotiates": "Variante verhandelt ebenfalls", + "View :name": "Ansicht :name", + "Web Server is Down": "Webserver ist ausgefallen" +} diff --git a/lang/de/actions.php b/lang/de/actions.php new file mode 100644 index 00000000..e0776b6d --- /dev/null +++ b/lang/de/actions.php @@ -0,0 +1,119 @@ + 'Akzeptieren', + 'action' => 'Aktion', + 'actions' => 'Aktionen', + 'add' => 'Hinzufügen', + 'admin' => 'Administrator', + 'agree' => 'Zustimmen', + 'archive' => 'Archiv', + 'assign' => 'Zuordnen', + 'associate' => 'Assoziieren', + 'attach' => 'Anfügen', + 'browse' => 'Durchsuche', + 'cancel' => 'Stornieren', + 'choose' => 'Wählen', + 'choose_file' => 'Datei wählen', + 'choose_image' => 'Wählen Sie Bild', + 'click_to_copy' => 'Klicken Sie zum Kopieren', + 'close' => 'Schließen', + 'collapse' => 'Zusammenbruch', + 'collapse_all' => 'Alles reduzieren', + 'comment' => 'Kommentar', + 'confirm' => 'Bestätigen', + 'connect' => 'Verbinden', + 'create' => 'Erstellen', + 'delete' => 'Löschen', + 'detach' => 'Ablösen', + 'details' => 'Einzelheiten', + 'disable' => 'Deaktivieren', + 'discard' => 'Verwerfen', + 'done' => 'Erledigt', + 'down' => 'Runter', + 'duplicate' => 'Duplikat', + 'edit' => 'Bearbeiten', + 'enable' => 'Aktivieren', + 'expand' => 'Expandieren', + 'expand_all' => 'Alle erweitern', + 'explanation' => 'Erläuterung', + 'export' => 'Exportieren', + 'file' => 'Datei', + 'files' => 'Dateien', + 'go_home' => 'Nach Hause gehen', + 'hide' => 'Verstecken', + 'home' => 'Heim', + 'image' => 'Bild', + 'impersonate' => 'Imitieren', + 'impersonation' => 'Identitätswechsel', + 'import' => 'Importieren', + 'introduction' => 'Einführung', + 'like' => 'Wie', + 'load' => 'Belastung', + 'localize' => 'Lokalisieren', + 'log_in' => 'Anmeldung', + 'log_out' => 'Ausloggen', + 'named' => [ + 'add' => ':name hinzufügen', + 'choose' => ':name auswählen', + 'create' => ':name erstellen', + 'delete' => ':name löschen', + 'duplicate' => ':name duplizieren', + 'edit' => ':name bearbeiten', + 'export' => ':name exportieren', + 'hide' => ':name ausblenden', + 'import' => ':name importieren', + 'new' => 'Neu :name', + 'restore' => ':name wiederherstellen', + 'save' => ':name speichern', + 'search' => ':name suchen', + 'show' => ':name anzeigen', + 'update' => ':name aktualisieren', + 'view' => ':name anzeigen', + ], + 'new' => 'Neu', + 'no' => 'Nein', + 'open' => 'Öffen', + 'open_website' => 'Auf der Website öffnen', + 'preview' => 'Vorschau', + 'price' => 'Preis', + 'record' => 'Aufzeichnen', + 'restore' => 'Wiederherstellen', + 'save' => 'Speichern', + 'save_and_close' => 'Speichern und schließen', + 'save_and_return' => 'Speichern und zurückgehen', + 'search' => 'Suchen', + 'select' => 'Wählen', + 'select_all' => 'Alles auswählen', + 'send' => 'Absenden', + 'settings' => 'Einstellungen', + 'show' => 'Anzeigen', + 'show_all' => 'Alles anzeigen', + 'sign_in' => 'Anmelden', + 'solve' => 'Lösen', + 'start' => 'Starten', + 'stop' => 'Stoppen', + 'submit' => 'Absenden', + 'subscribe' => 'Abonnieren', + 'switch' => 'Umschalten', + 'switch_to_role' => 'Zur Rolle wechseln', + 'tag' => 'Schlagwort', + 'tags' => 'Stichworte', + 'target_link' => [ + 'blank' => 'In einem neuen Fenster öffnen', + 'parent' => 'In einem übergeordneten Frame öffnen', + 'self' => 'In einem aktuellen Fenster öffnen', + 'top' => 'Im obersten Rahmen öffnen', + ], + 'translate' => 'Übersetzen', + 'translate_it' => 'Übersetze es', + 'unpack' => 'Entpacken', + 'unsubscribe' => 'Abbestellen', + 'up' => 'Hoch', + 'update' => 'Aktualisieren', + 'user' => 'Benutzer', + 'view' => 'Ansicht', + 'yes' => 'Ja', +]; diff --git a/lang/de/auth.php b/lang/de/auth.php new file mode 100644 index 00000000..b9b93be7 --- /dev/null +++ b/lang/de/auth.php @@ -0,0 +1,9 @@ + 'Diese Kombination aus Zugangsdaten wurde nicht in unserer Datenbank gefunden.', + 'password' => 'Das Passwort ist falsch.', + 'throttle' => 'Zu viele Loginversuche. Versuchen Sie es bitte in :seconds Sekunden nochmal.', +]; diff --git a/lang/de/http-statuses.php b/lang/de/http-statuses.php new file mode 100644 index 00000000..58a68cf4 --- /dev/null +++ b/lang/de/http-statuses.php @@ -0,0 +1,84 @@ + 'Unbekannter Fehler', + '100' => 'Weiter', + '101' => 'Protokollwechsel', + '102' => 'In Bearbeitung', + '200' => 'OK', + '201' => 'Erstellt', + '202' => 'Akzeptiert', + '203' => 'Nicht verifizierte Information', + '204' => 'Kein Inhalt', + '205' => 'Inhalt zurücksetzen', + '206' => 'Teilinhalt', + '207' => 'Multistatus', + '208' => 'Bereits gemeldet', + '226' => 'IM verwendet', + '300' => 'Mehrere Auswahlmöglichkeiten', + '301' => 'Permanent verschoben', + '302' => 'Gefunden', + '303' => 'Siehe andere Seite', + '304' => 'Nicht modifiziert', + '305' => 'Proxy verwenden', + '307' => 'Temporäre Weiterleitung', + '308' => 'Permanente Weiterleitung', + '400' => 'Ungültige Anfrage', + '401' => 'Nicht autorisiert', + '402' => 'Zahlung erforderlich', + '403' => 'Verboten', + '404' => 'Nicht gefunden', + '405' => 'Methode nicht erlaubt', + '406' => 'Nicht annehmbar', + '407' => 'Proxy-Authentifizierung erforderlich', + '408' => 'Zeitüberschreitung der Anfrage', + '409' => 'Konflikt', + '410' => 'Nicht mehr verfügbar', + '411' => 'Länge erforderlich', + '412' => 'Vorbedingung fehlgeschlagen', + '413' => 'Nutzlast zu groß', + '414' => 'URI zu lang', + '415' => 'Nicht unterstützter Medientyp', + '416' => 'Bereich nicht erfüllbar', + '417' => 'Erwartung gescheitert', + '418' => 'Ich bin eine Teekanne', + '419' => 'Sitzung ist abgelaufen', + '421' => 'Fehlgeleitete Anfrage', + '422' => 'Unverarbeitbare Entität', + '423' => 'Gesperrt', + '424' => 'Fehlgeschlagene Abhängigkeit', + '425' => 'Zu früh', + '426' => 'Upgrade erforderlich', + '428' => 'Voraussetzung erforderlich', + '429' => 'Zu viele Anfragen', + '431' => 'Anfrage-Header-Felder zu groß', + '444' => 'Verbindung ohne Antwort geschlossen', + '449' => 'Wiederhole mit', + '451' => 'Aus rechtlichen Gründen nicht verfügbar', + '499' => 'Client-Closed-Request', + '500' => 'Interner Serverfehler', + '501' => 'Nicht implementiert', + '502' => 'Fehlerhaftes Gateway', + '503' => 'Wartungsmodus', + '504' => 'Gateway-Zeitüberschreitung', + '505' => 'HTTP Version nicht unterstützt', + '506' => 'Variante verhandelt auch', + '507' => 'Nicht genügend Speicherplatz', + '508' => 'Endlosschleife erkannt', + '509' => 'Bandbreitenlimit überschritten', + '510' => 'Nicht erweitert', + '511' => 'Netzwerkauthentifizierung erforderlich', + '520' => 'Unbekannter Fehler', + '521' => 'Webserver ist ausgefallen', + '522' => 'Verbindung abgelaufen', + '523' => 'Quelle ist nicht erreichbar', + '524' => 'Eine Zeitüberschreitung ist aufgetreten', + '525' => 'SSL Handshake fehlgeschlagen', + '526' => 'Ungültiges SSL-Zertifikat', + '527' => 'Railgun-Fehler', + '598' => 'Zeitüberschreitungsfehler beim Lesen des Netzwerks', + '599' => 'Zeitüberschreitungsfehler bei Netzwerkverbindung', + 'unknownError' => 'Unbekannter Fehler', +]; diff --git a/lang/de/pagination.php b/lang/de/pagination.php new file mode 100644 index 00000000..c912b5d4 --- /dev/null +++ b/lang/de/pagination.php @@ -0,0 +1,8 @@ + 'Weiter »', + 'previous' => '« Zurück', +]; diff --git a/lang/de/passwords.php b/lang/de/passwords.php new file mode 100644 index 00000000..9634bddb --- /dev/null +++ b/lang/de/passwords.php @@ -0,0 +1,11 @@ + 'Das Passwort wurde zurückgesetzt!', + 'sent' => 'E-Mail zum Zurücksetzen des Passworts wurde gesendet!', + 'throttled' => 'Bitte warten Sie, bevor Sie es erneut versuchen.', + 'token' => 'Der Passwort-Wiederherstellungsschlüssel ist ungültig oder abgelaufen.', + 'user' => 'Es konnte leider kein Nutzer mit dieser E-Mail-Adresse gefunden werden.', +]; diff --git a/lang/de/validation.php b/lang/de/validation.php new file mode 100644 index 00000000..47c12518 --- /dev/null +++ b/lang/de/validation.php @@ -0,0 +1,286 @@ + ':Attribute muss akzeptiert werden.', + 'accepted_if' => ':Attribute muss akzeptiert werden, wenn :other :value ist.', + 'active_url' => ':Attribute ist keine gültige Internet-Adresse.', + 'after' => ':Attribute muss ein Datum nach :date sein.', + 'after_or_equal' => ':Attribute muss ein Datum nach :date oder gleich :date sein.', + 'alpha' => ':Attribute darf nur aus Buchstaben bestehen.', + 'alpha_dash' => ':Attribute darf nur aus Buchstaben, Zahlen, Binde- und Unterstrichen bestehen.', + 'alpha_num' => ':Attribute darf nur aus Buchstaben und Zahlen bestehen.', + 'any_of' => ':Attribute ist ungültig.', + 'array' => ':Attribute muss ein Array sein.', + 'ascii' => 'Die :attribute darf nur alphanumerische Single-Byte-Zeichen und -Symbole enthalten.', + 'before' => ':Attribute muss ein Datum vor :date sein.', + 'before_or_equal' => ':Attribute muss ein Datum vor :date oder gleich :date sein.', + 'between' => [ + 'array' => ':Attribute muss zwischen :min & :max Elemente haben.', + 'file' => ':Attribute muss zwischen :min & :max Kilobytes groß sein.', + 'numeric' => ':Attribute muss zwischen :min & :max liegen.', + 'string' => ':Attribute muss zwischen :min & :max Zeichen lang sein.', + ], + 'boolean' => ':Attribute muss entweder \'true\' oder \'false\' sein.', + 'can' => 'Das Feld :attribute enthält einen nicht autorisierten Wert.', + 'confirmed' => ':Attribute stimmt nicht mit der Bestätigung überein.', + 'contains' => 'Dem Feld :attribute fehlt ein erforderlicher Wert.', + 'current_password' => 'Das Passwort ist falsch.', + 'date' => ':Attribute muss ein gültiges Datum sein.', + 'date_equals' => ':Attribute muss ein Datum gleich :date sein.', + 'date_format' => ':Attribute entspricht nicht dem gültigen Format für :format.', + 'decimal' => 'Die :attribute muss :decimal Dezimalstellen haben.', + 'declined' => ':Attribute muss abgelehnt werden.', + 'declined_if' => ':Attribute muss abgelehnt werden wenn :other :value ist.', + 'different' => ':Attribute und :other müssen sich unterscheiden.', + 'digits' => ':Attribute muss :digits Stellen haben.', + 'digits_between' => ':Attribute muss zwischen :min und :max Stellen haben.', + 'dimensions' => ':Attribute hat ungültige Bildabmessungen.', + 'distinct' => ':Attribute beinhaltet einen bereits vorhandenen Wert.', + 'doesnt_end_with' => ':Attribute darf nicht mit einem der folgenden enden: :values.', + 'doesnt_start_with' => ':Attribute darf nicht mit einem der folgenden beginnen: :values.', + 'email' => ':Attribute muss eine gültige E-Mail-Adresse sein.', + 'ends_with' => ':Attribute muss eine der folgenden Endungen aufweisen: :values', + 'enum' => 'Der ausgewählte Wert ist ungültig.', + 'exists' => 'Der gewählte Wert für :attribute ist ungültig.', + 'extensions' => 'Das Feld :attribute muss eine der folgenden Erweiterungen haben: :values.', + 'file' => ':Attribute muss eine Datei sein.', + 'filled' => ':Attribute muss ausgefüllt sein.', + 'gt' => [ + 'array' => ':Attribute muss mehr als :value Elemente haben.', + 'file' => ':Attribute muss größer als :value Kilobytes sein.', + 'numeric' => ':Attribute muss größer als :value sein.', + 'string' => ':Attribute muss länger als :value Zeichen sein.', + ], + 'gte' => [ + 'array' => ':Attribute muss mindestens :value Elemente haben.', + 'file' => ':Attribute muss größer oder gleich :value Kilobytes sein.', + 'numeric' => ':Attribute muss größer oder gleich :value sein.', + 'string' => ':Attribute muss mindestens :value Zeichen lang sein.', + ], + 'hex_color' => 'Das Feld :attribute muss eine gültige Hexadezimalfarbe sein.', + 'image' => ':Attribute muss ein Bild sein.', + 'in' => 'Der gewählte Wert für :attribute ist ungültig.', + 'in_array' => 'Der gewählte Wert für :attribute kommt nicht in :other vor.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => ':Attribute muss eine ganze Zahl sein.', + 'ip' => ':Attribute muss eine gültige IP-Adresse sein.', + 'ipv4' => ':Attribute muss eine gültige IPv4-Adresse sein.', + 'ipv6' => ':Attribute muss eine gültige IPv6-Adresse sein.', + 'json' => ':Attribute muss ein gültiger JSON-String sein.', + 'list' => ':Attribute muss eine Liste sein.', + 'lowercase' => ':Attribute muss in Kleinbuchstaben sein.', + 'lt' => [ + 'array' => ':Attribute muss weniger als :value Elemente haben.', + 'file' => ':Attribute muss kleiner als :value Kilobytes sein.', + 'numeric' => ':Attribute muss kleiner als :value sein.', + 'string' => ':Attribute muss kürzer als :value Zeichen sein.', + ], + 'lte' => [ + 'array' => ':Attribute darf maximal :value Elemente haben.', + 'file' => ':Attribute muss kleiner oder gleich :value Kilobytes sein.', + 'numeric' => ':Attribute muss kleiner oder gleich :value sein.', + 'string' => ':Attribute darf maximal :value Zeichen lang sein.', + ], + 'mac_address' => 'Der Wert muss eine gültige MAC-Adresse sein.', + 'max' => [ + 'array' => ':Attribute darf maximal :max Elemente haben.', + 'file' => ':Attribute darf maximal :max Kilobytes groß sein.', + 'numeric' => ':Attribute darf maximal :max sein.', + 'string' => ':Attribute darf maximal :max Zeichen haben.', + ], + 'max_digits' => ':Attribute darf maximal :max Ziffern lang sein.', + 'mimes' => ':Attribute muss den Dateityp :values haben.', + 'mimetypes' => ':Attribute muss den Dateityp :values haben.', + 'min' => [ + 'array' => ':Attribute muss mindestens :min Elemente haben.', + 'file' => ':Attribute muss mindestens :min Kilobytes groß sein.', + 'numeric' => ':Attribute muss mindestens :min sein.', + 'string' => ':Attribute muss mindestens :min Zeichen lang sein.', + ], + 'min_digits' => ':Attribute muss mindestens :min Ziffern lang sein.', + 'missing' => 'Das Feld :attribute muss fehlen.', + 'missing_if' => 'Das Feld :attribute muss fehlen, wenn :other gleich :value ist.', + 'missing_unless' => 'Das Feld :attribute muss fehlen, es sei denn, :other ist :value.', + 'missing_with' => 'Das Feld :attribute muss fehlen, wenn :values vorhanden ist.', + 'missing_with_all' => 'Das Feld :attribute muss fehlen, wenn :values vorhanden sind.', + 'multiple_of' => ':Attribute muss ein Vielfaches von :value sein.', + 'not_in' => 'Der gewählte Wert für :attribute ist ungültig.', + 'not_regex' => ':Attribute hat ein ungültiges Format.', + 'numeric' => ':Attribute muss eine Zahl sein.', + 'password' => [ + 'letters' => ':Attribute muss mindestens einen Buchstaben beinhalten.', + 'mixed' => ':Attribute muss mindestens einen Großbuchstaben und einen Kleinbuchstaben beinhalten.', + 'numbers' => ':Attribute muss mindestens eine Zahl beinhalten.', + 'symbols' => ':Attribute muss mindestens ein Sonderzeichen beinhalten.', + 'uncompromised' => ':Attribute wurde in einem Datenleck gefunden. Bitte wählen Sie ein anderes :attribute.', + ], + 'present' => ':Attribute muss vorhanden sein.', + 'present_if' => 'Das Feld :attribute muss vorhanden sein, wenn :other gleich :value ist.', + 'present_unless' => 'Das Feld :attribute muss vorhanden sein, es sei denn, :other ist :value.', + 'present_with' => 'Das Feld :attribute muss vorhanden sein, wenn :values vorhanden ist.', + 'present_with_all' => 'Das Feld :attribute muss vorhanden sein, wenn :values vorhanden sind.', + 'prohibited' => ':Attribute ist unzulässig.', + 'prohibited_if' => ':Attribute ist unzulässig, wenn :other :value ist.', + 'prohibited_if_accepted' => 'Das Feld :attribute ist unzulässig, wenn :other gewählt ist.', + 'prohibited_if_declined' => 'Das Feld :attribute ist unzulässig, wenn :other abgelehnt ist.', + 'prohibited_unless' => ':Attribute ist unzulässig, wenn :other nicht :values ist.', + 'prohibits' => ':Attribute verbietet die Angabe von :other.', + 'regex' => ':Attribute Format ist ungültig.', + 'required' => ':Attribute muss ausgefüllt werden.', + 'required_array_keys' => 'Dieses Feld muss Einträge enthalten für: :values.', + 'required_if' => ':Attribute muss ausgefüllt werden, wenn :other den Wert :value hat.', + 'required_if_accepted' => ':Attribute muss ausgefüllt werden, wenn :other gewählt ist.', + 'required_if_declined' => 'Das Feld :attribute ist erforderlich, wenn :other abgelehnt wird.', + 'required_unless' => ':Attribute muss ausgefüllt werden, wenn :other nicht den Wert :values hat.', + 'required_with' => ':Attribute muss ausgefüllt werden, wenn :values ausgefüllt wurde.', + 'required_with_all' => ':Attribute muss ausgefüllt werden, wenn :values ausgefüllt wurde.', + 'required_without' => ':Attribute muss ausgefüllt werden, wenn :values nicht ausgefüllt wurde.', + 'required_without_all' => ':Attribute muss ausgefüllt werden, wenn keines der Felder :values ausgefüllt wurde.', + 'same' => ':Attribute und :other müssen übereinstimmen.', + 'size' => [ + 'array' => ':Attribute muss genau :size Elemente haben.', + 'file' => ':Attribute muss :size Kilobyte groß sein.', + 'numeric' => ':Attribute muss gleich :size sein.', + 'string' => ':Attribute muss :size Zeichen lang sein.', + ], + 'starts_with' => ':Attribute muss mit einem der folgenden Anfänge aufweisen: :values', + 'string' => ':Attribute muss ein String sein.', + 'timezone' => ':Attribute muss eine gültige Zeitzone sein.', + 'ulid' => 'Die :attribute muss eine gültige ULID sein.', + 'unique' => ':Attribute ist bereits vergeben.', + 'uploaded' => ':Attribute konnte nicht hochgeladen werden.', + 'uppercase' => ':Attribute muss in Großbuchstaben sein.', + 'url' => ':Attribute muss eine URL sein.', + 'uuid' => ':Attribute muss ein UUID sein.', + 'attributes' => [ + 'address' => 'Adresse', + 'affiliate_url' => 'Affiliate-URL', + 'age' => 'Alter', + 'amount' => 'Höhe', + 'announcement' => 'Bekanntmachung', + 'area' => 'Gebiet', + 'audience_prize' => 'Publikumspreis', + 'audience_winner' => 'Publikumsgewinner', + 'available' => 'Verfügbar', + 'birthday' => 'Geburtstag', + 'body' => 'Körper', + 'city' => 'Stadt', + 'company' => 'Unternehmen', + 'compilation' => 'Zusammenstellung', + 'concept' => 'Konzept', + 'conditions' => 'Bedingungen', + 'content' => 'Inhalt', + 'contest' => 'Wettbewerb', + 'country' => 'Land', + 'cover' => 'Abdeckung', + 'created_at' => 'Erstellt am', + 'creator' => 'Ersteller', + 'currency' => 'Währung', + 'current_password' => 'Derzeitiges Passwort', + 'customer' => 'Kunde', + 'date' => 'Datum', + 'date_of_birth' => 'Geburtsdatum', + 'dates' => 'Termine', + 'day' => 'Tag', + 'deleted_at' => 'Gelöscht am', + 'description' => 'Beschreibung', + 'display_type' => 'Anzeigetyp', + 'district' => 'Bezirk', + 'duration' => 'Dauer', + 'email' => 'E-Mail-Adresse', + 'excerpt' => 'Auszug', + 'filter' => 'Filter', + 'finished_at' => 'fertig um', + 'first_name' => 'Vorname', + 'gender' => 'Geschlecht', + 'grand_prize' => 'Hauptpreis', + 'group' => 'Gruppe', + 'hour' => 'Stunde', + 'image' => 'Bild', + 'image_desktop' => 'Desktop-Bild', + 'image_main' => 'Hauptbild', + 'image_mobile' => 'mobiles Bild', + 'images' => 'Bilder', + 'is_audience_winner' => 'ist Publikumssieger', + 'is_hidden' => 'ist versteckt', + 'is_subscribed' => 'ist abonniert', + 'is_visible' => 'ist sichtbar', + 'is_winner' => 'ist Gewinner', + 'items' => 'Artikel', + 'key' => 'Schlüssel', + 'last_name' => 'Nachname', + 'lesson' => 'Lektion', + 'line_address_1' => 'Adresszeile 1', + 'line_address_2' => 'Adresszeile 2', + 'login' => 'Anmeldung', + 'message' => 'Nachricht', + 'middle_name' => 'Zweitname', + 'minute' => 'Minute', + 'mobile' => 'Handynummer', + 'month' => 'Monat', + 'name' => 'Name', + 'national_code' => 'Länderkennung', + 'nickname' => 'Spitzname', + 'number' => 'Nummer', + 'password' => 'Passwort', + 'password_confirmation' => 'Passwortbestätigung', + 'phone' => 'Telefonnummer', + 'photo' => 'Foto', + 'portfolio' => 'Portfolio', + 'postal_code' => 'Postleitzahl', + 'preview' => 'Vorschau', + 'price' => 'Preis', + 'product_id' => 'Produkt ID', + 'product_uid' => 'Produkt-UID', + 'product_uuid' => 'Produkt-UUID', + 'promo_code' => 'Aktionscode', + 'province' => 'Provinz', + 'quantity' => 'Menge', + 'reason' => 'Grund', + 'recaptcha_response_field' => 'Captcha-Feld', + 'referee' => 'Schiedsrichter', + 'referees' => 'Schiedsrichter', + 'reject_reason' => 'Ablehnungsgrund', + 'remember' => 'Erinnern', + 'restored_at' => 'Wiederhergestellt am', + 'result_text_under_image' => 'Ergebnistext unter Bild', + 'role' => 'Rolle', + 'rule' => 'Regel', + 'rules' => 'Regeln', + 'second' => 'Sekunde', + 'sex' => 'Geschlecht', + 'shipment' => 'Sendung', + 'short_text' => 'Kurzer Text', + 'size' => 'Größe', + 'situation' => 'Situation', + 'skills' => 'Fähigkeiten', + 'slug' => 'Schnecke', + 'specialization' => 'Spezialisierung', + 'started_at' => 'fing an bei', + 'state' => 'Bundesland', + 'status' => 'Status', + 'street' => 'Straße', + 'student' => 'Schüler/Student', + 'subject' => 'Gegenstand', + 'tag' => 'Etikett', + 'tags' => 'Stichworte', + 'teacher' => 'Lehrer', + 'terms' => 'Bedingungen', + 'test_description' => 'Test Beschreibung', + 'test_locale' => 'Test Region', + 'test_name' => 'Testname', + 'text' => 'Text', + 'time' => 'Uhrzeit', + 'title' => 'Titel', + 'type' => 'Typ', + 'updated_at' => 'Aktualisiert am', + 'user' => 'Benutzer', + 'username' => 'Benutzername', + 'value' => 'Wert', + 'winner' => 'Gewinner', + 'work' => 'Arbeit', + 'year' => 'Jahr', + ], +]; diff --git a/lang/de_CH.json b/lang/de_CH.json new file mode 100644 index 00000000..44adb948 --- /dev/null +++ b/lang/de_CH.json @@ -0,0 +1,231 @@ +{ + "(and :count more error)": "(und :count weiterer Fehler)", + "(and :count more errors)": "(und :count weiterer Fehler)|(und :count weitere Fehler)|(und :count weitere Fehler)", + "A decryption key is required.": "Ein Entschlüsselungsschlüssel ist nötig.", + "A reset link will be sent if the account exists.": "A reset link will be sent if the account exists.", + "A Timeout Occurred": "Eine Zeitüberschreitung ist aufgetreten", + "Accept": "Akzeptieren", + "Accepted": "Akzeptiert", + "Action": "Aktion", + "Actions": "Aktionen", + "Add": "Hinzufügen", + "Add :name": "Addiere :name", + "Admin": "Administrator", + "Agree": "Zustimmen", + "All rights reserved.": "Alle Rechte vorbehalten.", + "Already Reported": "Bereits gemeldet", + "Archive": "Archiv", + "Assign": "Zuordnen", + "Associate": "Assoziieren", + "Attach": "Anhängen", + "Bad Gateway": "Fehlerhaftes Gateway", + "Bad Request": "Ungültige Anfrage", + "Bandwidth Limit Exceeded": "Bandbreitenlimit überschritten", + "Browse": "Durchsuche", + "Cancel": "Abbrechen", + "Choose": "Wählen Sie", + "Choose :name": "Wählen Sie :name", + "Choose File": "Datei wählen", + "Choose Image": "Wählen Sie Bild", + "Click to copy": "Klicken Sie zum Kopieren", + "Client Closed Request": "Client hat die Anfrage geschlossen", + "Close": "Schliessen", + "Collapse": "Zusammenbruch", + "Collapse All": "Alles reduzieren", + "Comment": "Kommentar", + "Confirm": "Bestätigen", + "Conflict": "Konflikt", + "Connect": "Verbinden", + "Connection Closed Without Response": "Verbindung ohne Antwort getrennt", + "Connection Timed Out": "Verbindungszeit überschritten", + "Continue": "Weiter", + "Create": "Erstellen", + "Create :name": "Erstellen Sie :name", + "Created": "Erstellt", + "Delete": "Löschen", + "Delete :name": ":name löschen", + "Detach": "Trennen", + "Details": "Details", + "Disable": "Deaktivieren", + "Discard": "Verwerfen", + "Done": "Erledigt", + "Down": "Runter", + "Duplicate": "Duplikat", + "Duplicate :name": "Duplikat :name", + "Edit": "Bearbeiten", + "Edit :name": "Bearbeiten :name", + "Enable": "Aktivieren", + "Encrypted environment file already exists.": "Verschlüsselte Umgebungsdatei ist bereits vorhanden.", + "Encrypted environment file not found.": "Verschlüsselte Umgebungsdatei nicht gefunden.", + "Environment file already exists.": "Umgebungsdatei ist bereits vorhanden.", + "Environment file not found.": "Umgebungsdatei nicht gefunden.", + "errors": "Fehler", + "Expand": "Expandieren", + "Expand All": "Alle erweitern", + "Expectation Failed": "Erwartung gescheitert", + "Explanation": "Erläuterung", + "Export": "Export", + "Export :name": "Export :name", + "Failed Dependency": "Fehlgeschlagene Abhängigkeit", + "File": "Datei", + "Files": "Dateien", + "Forbidden": "Verboten", + "Found": "Gefunden", + "Gateway Timeout": "Gateway-Zeitüberschreitung", + "Go Home": "Zur Startseite", + "Go to page :page": "Gehe zur Seite :page", + "Gone": "Nicht mehr verfügbar", + "Hello!": "Hallo!", + "Hide": "Verstecken", + "Hide :name": ":name ausblenden", + "Home": "Heim", + "HTTP Version Not Supported": "HTTP Version nicht unterstützt", + "I'm a teapot": "Ich bin eine Teekanne", + "If you did not create an account, no further action is required.": "Wenn Sie kein Konto erstellt haben, sind keine weiteren Handlungen nötig.", + "If you did not request a password reset, no further action is required.": "Wenn Sie kein Zurücksetzen des Passworts beantragt haben, sind keine weiteren Handlungen nötig.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Sollten Sie Schwierigkeiten haben, die Schaltfläche \":actionText\" zu klicken, kopieren Sie den nachfolgenden Link\n in Ihre Adresszeile des Browsers.", + "IM Used": "IM verwendet", + "Image": "Bild", + "Impersonate": "Imitieren", + "Impersonation": "Identitätswechsel", + "Import": "Importieren", + "Import :name": "Importieren Sie :name", + "Insufficient Storage": "Nicht genügend Speicherplatz", + "Internal Server Error": "Interner Serverfehler", + "Introduction": "Einführung", + "Invalid filename.": "Ungültiger Dateiname.", + "Invalid JSON was returned from the route.": "Von der Route wurde ein ungültiger JSON-Code zurückgegeben.", + "Invalid SSL Certificate": "Ungültiges SSL-Zertifikat", + "length": "Länge", + "Length Required": "Längenangabe erforderlich", + "Like": "Wie", + "Load": "Belastung", + "Localize": "Lokalisieren", + "Location": "Standort", + "Locked": "Gesperrt", + "Log In": "Einloggen", + "Log Out": "Abmelden", + "Login": "Anmelden", + "Logout": "Abmelden", + "Loop Detected": "Endlosschleife erkannt", + "Maintenance Mode": "Wartungsmodus", + "Method Not Allowed": "Methode nicht erlaubt", + "Misdirected Request": "Fehlgeleitete Anfrage", + "Moved Permanently": "Permanent verschoben", + "Multi-Status": "Multistatus", + "Multiple Choices": "Mehrere Auswahlmöglichkeiten", + "Network Authentication Required": "Netzwerkauthentifizierung erforderlich", + "Network Connect Timeout Error": "Zeitüberschreitungsfehler bei Netzwerkverbindung", + "Network Read Timeout Error": "Zeitüberschreitungsfehler beim Lesen des Netzwerks", + "New": "Neu", + "New :name": "Neu :name", + "No": "Keine", + "No Content": "Kein Inhalt", + "Non-Authoritative Information": "Nicht maßgebende Informationen", + "Not Acceptable": "Nicht akzeptierbar", + "Not Extended": "Nicht erweitert", + "Not Found": "Nicht gefunden", + "Not Implemented": "Nicht implementiert", + "Not Modified": "Nicht modifiziert", + "of": "von", + "OK": "OK", + "Open": "Offen", + "Open in a current window": "In einem aktuellen Fenster öffnen", + "Open in a new window": "In einem neuen Fenster öffnen", + "Open in a parent frame": "In einem übergeordneten Frame öffnen", + "Open in the topmost frame": "Im obersten Rahmen öffnen", + "Open on the website": "Auf der Website öffnen", + "Origin Is Unreachable": "Quelle ist nicht erreichbar", + "Page Expired": "Seite abgelaufen", + "Pagination Navigation": "Seiten-Navigation", + "Partial Content": "Teilinhalt", + "Payload Too Large": "Nutzlast zu groß", + "Payment Required": "Zahlung erforderlich", + "Permanent Redirect": "Permanente Weiterleitung", + "Please click the button below to verify your email address.": "Bitte klicken Sie auf die Schaltfläche, um Ihre E-Mail-Adresse zu bestätigen.", + "Precondition Failed": "Vorbedingung fehlgeschlagen", + "Precondition Required": "Voraussetzung erforderlich", + "Preview": "Vorschau", + "Price": "Preis", + "Processing": "In Bearbeitung", + "Proxy Authentication Required": "Proxy-Authentifizierung erforderlich", + "Railgun Error": "Railgun-Fehler", + "Range Not Satisfiable": "Bereich nicht erfüllbar", + "Record": "Aufzeichnen", + "Regards,": "Mit freundlichen Grüssen,", + "Register": "Registrieren", + "Request Header Fields Too Large": "Anfrage-Header-Felder zu groß", + "Request Timeout": "Zeitüberschreitung der Anfrage", + "Reset Content": "Inhalt zurücksetzen", + "Reset Password": "Passwort zurücksetzen", + "Reset Password Notification": "Benachrichtigung zum Zurücksetzen des Passworts", + "Restore": "Wiederherstellen", + "Restore :name": ":name wiederherstellen", + "results": "Ergebnissen", + "Retry With": "Wiederhole mit", + "Save": "Speichern", + "Save & Close": "Speichern und schließen", + "Save & Return": "Speichern und zurückgeben", + "Save :name": "Sparen Sie :name", + "Search": "Search", + "Search :name": "Suche :name", + "See Other": "Siehe andere Seite", + "Select": "Wählen Sie", + "Select All": "Wählen Sie Alle", + "Send": "Schicken", + "Server Error": "Interner Fehler", + "Service Unavailable": "Service nicht verfügbar", + "Session Has Expired": "Sitzung ist abgelaufen", + "Settings": "Settings", + "Show": "Zeigen", + "Show :name": ":name anzeigen", + "Show All": "Zeige alles", + "Showing": "Zeige", + "Sign In": "Anmelden", + "Solve": "Lösen", + "SSL Handshake Failed": "SSL Handshake fehlgeschlagen", + "Start": "Start", + "status": "status", + "Stop": "Stoppen", + "Submit": "Einreichen", + "Subscribe": "Abonnieren", + "Switch": "Schalten", + "Switch To Role": "Zur Rolle wechseln", + "Switching Protocols": "Protokollwechsel", + "Tag": "Etikett", + "Tags": "Stichworte", + "Temporary Redirect": "Temporäre Weiterleitung", + "The given data was invalid.": "Die gegebenen Daten waren ungültig.", + "The response is not a streamed response.": "Die Antwort ist keine gestreamte Antwort.", + "The response is not a view.": "Die Antwort ist keine Ansicht.", + "This action is unauthorized.": "Diese Aktion ist nicht autorisiert.", + "This password reset link will expire in :count minutes.": "Dieser Link zum Zurücksetzen des Passworts läuft in :count Minuten ab.", + "to": "bis", + "Toggle navigation": "Navigation umschalten", + "Too Early": "Zu früh", + "Too Many Requests": "Zu viele Anfragen", + "Translate": "Übersetzen", + "Translate It": "Übersetze es", + "Unauthorized": "Nicht autorisiert", + "Unavailable For Legal Reasons": "Aus rechtlichen Gründen nicht verfügbar", + "Unknown Error": "Unbekannter Fehler", + "Unpack": "Auspacken", + "Unprocessable Entity": "Unverarbeitbare Entität", + "Unsubscribe": "Abbestellen", + "Unsupported Media Type": "Nicht unterstützter Medientyp", + "Up": "Hoch", + "Update": "Aktualisieren", + "Update :name": "Update :name", + "Upgrade Required": "Upgrade erforderlich", + "URI Too Long": "URI ist zu lang", + "Use Proxy": "Proxy verwenden", + "User": "Benutzer", + "Variant Also Negotiates": "Variante verhandelt ebenfalls", + "Verify Email Address": "E-Mail-Adresse bestätigen", + "View": "Ansicht", + "View :name": "Ansicht :name", + "Web Server is Down": "Webserver ist ausgefallen", + "Whoops!": "Ups!", + "Yes": "Ja", + "You are receiving this email because we received a password reset request for your account.": "Sie erhalten diese E-Mail, weil wir einen Antrag auf eine Zurücksetzung Ihres Passworts bekommen haben." +} \ No newline at end of file diff --git a/lang/de_CH/actions.php b/lang/de_CH/actions.php new file mode 100644 index 00000000..e8bddc02 --- /dev/null +++ b/lang/de_CH/actions.php @@ -0,0 +1,119 @@ + 'Akzeptieren', + 'action' => 'Aktion', + 'actions' => 'Aktionen', + 'add' => 'Hinzufügen', + 'admin' => 'Administrator', + 'agree' => 'Zustimmen', + 'archive' => 'Archiv', + 'assign' => 'Zuordnen', + 'associate' => 'Assoziieren', + 'attach' => 'Anfügen', + 'browse' => 'Durchsuche', + 'cancel' => 'Stornieren', + 'choose' => 'Wählen', + 'choose_file' => 'Datei wählen', + 'choose_image' => 'Wählen Sie Bild', + 'click_to_copy' => 'Klicken Sie zum Kopieren', + 'close' => 'Schließen', + 'collapse' => 'Zusammenbruch', + 'collapse_all' => 'Alles reduzieren', + 'comment' => 'Kommentar', + 'confirm' => 'Bestätigen', + 'connect' => 'Verbinden', + 'create' => 'Erstellen', + 'delete' => 'Löschen', + 'detach' => 'Ablösen', + 'details' => 'Einzelheiten', + 'disable' => 'Deaktivieren', + 'discard' => 'Verwerfen', + 'done' => 'Erledigt', + 'down' => 'Runter', + 'duplicate' => 'Duplikat', + 'edit' => 'Bearbeiten', + 'enable' => 'Aktivieren', + 'expand' => 'Expandieren', + 'expand_all' => 'Alle erweitern', + 'explanation' => 'Erläuterung', + 'export' => 'Export', + 'file' => 'Datei', + 'files' => 'Dateien', + 'go_home' => 'Nach Hause gehen', + 'hide' => 'Verstecken', + 'home' => 'Heim', + 'image' => 'Bild', + 'impersonate' => 'Imitieren', + 'impersonation' => 'Identitätswechsel', + 'import' => 'Importieren', + 'introduction' => 'Einführung', + 'like' => 'Wie', + 'load' => 'Belastung', + 'localize' => 'Lokalisieren', + 'log_in' => 'Anmeldung', + 'log_out' => 'Ausloggen', + 'named' => [ + 'add' => 'Addiere :name', + 'choose' => 'Wählen Sie :name', + 'create' => 'Erstellen Sie :name', + 'delete' => ':name löschen', + 'duplicate' => 'Duplikat :name', + 'edit' => 'Bearbeiten :name', + 'export' => 'Export :name', + 'hide' => ':name ausblenden', + 'import' => 'Importieren Sie :name', + 'new' => 'Neu :name', + 'restore' => ':name wiederherstellen', + 'save' => 'Sparen Sie :name', + 'search' => 'Suche :name', + 'show' => ':name anzeigen', + 'update' => 'Update :name', + 'view' => 'Ansicht :name', + ], + 'new' => 'Neu', + 'no' => 'NEIN', + 'open' => 'Offen', + 'open_website' => 'Auf der Website öffnen', + 'preview' => 'Vorschau', + 'price' => 'Preis', + 'record' => 'Aufzeichnen', + 'restore' => 'Wiederherstellen', + 'save' => 'Speichern', + 'save_and_close' => 'Speichern und schließen', + 'save_and_return' => 'Speichern und zurückgeben', + 'search' => 'Suchen', + 'select' => 'Wählen', + 'select_all' => 'Wählen Sie Alle', + 'send' => 'Schicken', + 'settings' => 'Einstellungen', + 'show' => 'Zeigen', + 'show_all' => 'Zeige alles', + 'sign_in' => 'Anmelden', + 'solve' => 'Lösen', + 'start' => 'Start', + 'stop' => 'Stoppen', + 'submit' => 'Einreichen', + 'subscribe' => 'Abonnieren', + 'switch' => 'Schalten', + 'switch_to_role' => 'Zur Rolle wechseln', + 'tag' => 'Etikett', + 'tags' => 'Stichworte', + 'target_link' => [ + 'blank' => 'In einem neuen Fenster öffnen', + 'parent' => 'In einem übergeordneten Frame öffnen', + 'self' => 'In einem aktuellen Fenster öffnen', + 'top' => 'Im obersten Rahmen öffnen', + ], + 'translate' => 'Übersetzen', + 'translate_it' => 'Übersetze es', + 'unpack' => 'Auspacken', + 'unsubscribe' => 'Abbestellen', + 'up' => 'Hoch', + 'update' => 'Aktualisieren', + 'user' => 'Benutzer', + 'view' => 'Sicht', + 'yes' => 'Ja', +]; diff --git a/lang/de_CH/auth.php b/lang/de_CH/auth.php new file mode 100644 index 00000000..b9b93be7 --- /dev/null +++ b/lang/de_CH/auth.php @@ -0,0 +1,9 @@ + 'Diese Kombination aus Zugangsdaten wurde nicht in unserer Datenbank gefunden.', + 'password' => 'Das Passwort ist falsch.', + 'throttle' => 'Zu viele Loginversuche. Versuchen Sie es bitte in :seconds Sekunden nochmal.', +]; diff --git a/lang/de_CH/http-statuses.php b/lang/de_CH/http-statuses.php new file mode 100644 index 00000000..58a68cf4 --- /dev/null +++ b/lang/de_CH/http-statuses.php @@ -0,0 +1,84 @@ + 'Unbekannter Fehler', + '100' => 'Weiter', + '101' => 'Protokollwechsel', + '102' => 'In Bearbeitung', + '200' => 'OK', + '201' => 'Erstellt', + '202' => 'Akzeptiert', + '203' => 'Nicht verifizierte Information', + '204' => 'Kein Inhalt', + '205' => 'Inhalt zurücksetzen', + '206' => 'Teilinhalt', + '207' => 'Multistatus', + '208' => 'Bereits gemeldet', + '226' => 'IM verwendet', + '300' => 'Mehrere Auswahlmöglichkeiten', + '301' => 'Permanent verschoben', + '302' => 'Gefunden', + '303' => 'Siehe andere Seite', + '304' => 'Nicht modifiziert', + '305' => 'Proxy verwenden', + '307' => 'Temporäre Weiterleitung', + '308' => 'Permanente Weiterleitung', + '400' => 'Ungültige Anfrage', + '401' => 'Nicht autorisiert', + '402' => 'Zahlung erforderlich', + '403' => 'Verboten', + '404' => 'Nicht gefunden', + '405' => 'Methode nicht erlaubt', + '406' => 'Nicht annehmbar', + '407' => 'Proxy-Authentifizierung erforderlich', + '408' => 'Zeitüberschreitung der Anfrage', + '409' => 'Konflikt', + '410' => 'Nicht mehr verfügbar', + '411' => 'Länge erforderlich', + '412' => 'Vorbedingung fehlgeschlagen', + '413' => 'Nutzlast zu groß', + '414' => 'URI zu lang', + '415' => 'Nicht unterstützter Medientyp', + '416' => 'Bereich nicht erfüllbar', + '417' => 'Erwartung gescheitert', + '418' => 'Ich bin eine Teekanne', + '419' => 'Sitzung ist abgelaufen', + '421' => 'Fehlgeleitete Anfrage', + '422' => 'Unverarbeitbare Entität', + '423' => 'Gesperrt', + '424' => 'Fehlgeschlagene Abhängigkeit', + '425' => 'Zu früh', + '426' => 'Upgrade erforderlich', + '428' => 'Voraussetzung erforderlich', + '429' => 'Zu viele Anfragen', + '431' => 'Anfrage-Header-Felder zu groß', + '444' => 'Verbindung ohne Antwort geschlossen', + '449' => 'Wiederhole mit', + '451' => 'Aus rechtlichen Gründen nicht verfügbar', + '499' => 'Client-Closed-Request', + '500' => 'Interner Serverfehler', + '501' => 'Nicht implementiert', + '502' => 'Fehlerhaftes Gateway', + '503' => 'Wartungsmodus', + '504' => 'Gateway-Zeitüberschreitung', + '505' => 'HTTP Version nicht unterstützt', + '506' => 'Variante verhandelt auch', + '507' => 'Nicht genügend Speicherplatz', + '508' => 'Endlosschleife erkannt', + '509' => 'Bandbreitenlimit überschritten', + '510' => 'Nicht erweitert', + '511' => 'Netzwerkauthentifizierung erforderlich', + '520' => 'Unbekannter Fehler', + '521' => 'Webserver ist ausgefallen', + '522' => 'Verbindung abgelaufen', + '523' => 'Quelle ist nicht erreichbar', + '524' => 'Eine Zeitüberschreitung ist aufgetreten', + '525' => 'SSL Handshake fehlgeschlagen', + '526' => 'Ungültiges SSL-Zertifikat', + '527' => 'Railgun-Fehler', + '598' => 'Zeitüberschreitungsfehler beim Lesen des Netzwerks', + '599' => 'Zeitüberschreitungsfehler bei Netzwerkverbindung', + 'unknownError' => 'Unbekannter Fehler', +]; diff --git a/lang/de_CH/pagination.php b/lang/de_CH/pagination.php new file mode 100644 index 00000000..c912b5d4 --- /dev/null +++ b/lang/de_CH/pagination.php @@ -0,0 +1,8 @@ + 'Weiter »', + 'previous' => '« Zurück', +]; diff --git a/lang/de_CH/passwords.php b/lang/de_CH/passwords.php new file mode 100644 index 00000000..9634bddb --- /dev/null +++ b/lang/de_CH/passwords.php @@ -0,0 +1,11 @@ + 'Das Passwort wurde zurückgesetzt!', + 'sent' => 'E-Mail zum Zurücksetzen des Passworts wurde gesendet!', + 'throttled' => 'Bitte warten Sie, bevor Sie es erneut versuchen.', + 'token' => 'Der Passwort-Wiederherstellungsschlüssel ist ungültig oder abgelaufen.', + 'user' => 'Es konnte leider kein Nutzer mit dieser E-Mail-Adresse gefunden werden.', +]; diff --git a/lang/de_CH/validation.php b/lang/de_CH/validation.php new file mode 100644 index 00000000..03fdd77e --- /dev/null +++ b/lang/de_CH/validation.php @@ -0,0 +1,286 @@ + ':Attribute muss akzeptiert werden.', + 'accepted_if' => ':Attribute muss akzeptiert werden, wenn :other :value ist.', + 'active_url' => ':Attribute ist keine gültige Internet-Adresse.', + 'after' => ':Attribute muss ein Datum nach :date sein.', + 'after_or_equal' => ':Attribute muss ein Datum nach :date oder gleich :date sein.', + 'alpha' => ':Attribute darf nur aus Buchstaben bestehen.', + 'alpha_dash' => ':Attribute darf nur aus Buchstaben, Zahlen, Binde- und Unterstrichen bestehen.', + 'alpha_num' => ':Attribute darf nur aus Buchstaben und Zahlen bestehen.', + 'any_of' => 'The :attribute field is invalid.', + 'array' => ':Attribute muss ein Array sein.', + 'ascii' => 'Die :attribute darf nur alphanumerische Single-Byte-Zeichen und -Symbole enthalten.', + 'before' => ':Attribute muss ein Datum vor :date sein.', + 'before_or_equal' => ':Attribute muss ein Datum vor :date oder gleich :date sein.', + 'between' => [ + 'array' => ':Attribute muss zwischen :min & :max Elemente haben.', + 'file' => ':Attribute muss zwischen :min & :max Kilobytes gross sein.', + 'numeric' => ':Attribute muss zwischen :min & :max liegen.', + 'string' => ':Attribute muss zwischen :min & :max Zeichen lang sein.', + ], + 'boolean' => ':Attribute muss entweder \'true\' oder \'false\' sein.', + 'can' => 'Das Feld :attribute enthält einen nicht autorisierten Wert.', + 'confirmed' => ':Attribute stimmt nicht mit der Bestätigung überein.', + 'contains' => 'Dem Feld :attribute fehlt ein erforderlicher Wert.', + 'current_password' => 'Das Passwort ist falsch.', + 'date' => ':Attribute muss ein gültiges Datum sein.', + 'date_equals' => ':Attribute muss ein Datum gleich :date sein.', + 'date_format' => ':Attribute entspricht nicht dem gültigen Format für :format.', + 'decimal' => 'Die :attribute muss :decimal Dezimalstellen haben.', + 'declined' => ':Attribute muss abgelehnt werden.', + 'declined_if' => ':Attribute muss abgelehnt werden wenn :other :value ist.', + 'different' => ':Attribute und :other müssen sich unterscheiden.', + 'digits' => ':Attribute muss :digits Stellen haben.', + 'digits_between' => ':Attribute muss zwischen :min und :max Stellen haben.', + 'dimensions' => ':Attribute hat ungültige Bildabmessungen.', + 'distinct' => ':Attribute beinhaltet einen bereits vorhandenen Wert.', + 'doesnt_end_with' => ':Attribute darf nicht mit einem der folgenden enden: :values.', + 'doesnt_start_with' => ':Attribute darf nicht mit einem der folgenden beginnen: :values.', + 'email' => ':Attribute muss eine gültige E-Mail-Adresse sein.', + 'ends_with' => ':Attribute muss eine der folgenden Endungen aufweisen: :values', + 'enum' => 'Der ausgewählte Wert ist ungültig.', + 'exists' => 'Der gewählte Wert für :attribute ist ungültig.', + 'extensions' => 'Das Feld :attribute muss eine der folgenden Erweiterungen haben: :values.', + 'file' => ':Attribute muss eine Datei sein.', + 'filled' => ':Attribute muss ausgefüllt sein.', + 'gt' => [ + 'array' => ':Attribute muss mehr als :value Elemente haben.', + 'file' => ':Attribute muss grösser als :value Kilobytes sein.', + 'numeric' => ':Attribute muss grösser als :value sein.', + 'string' => ':Attribute muss länger als :value Zeichen sein.', + ], + 'gte' => [ + 'array' => ':Attribute muss mindestens :value Elemente haben.', + 'file' => ':Attribute muss grösser oder gleich :value Kilobytes sein.', + 'numeric' => ':Attribute muss grösser oder gleich :value sein.', + 'string' => ':Attribute muss mindestens :value Zeichen lang sein.', + ], + 'hex_color' => 'Das Feld :attribute muss eine gültige Hexadezimalfarbe sein.', + 'image' => ':Attribute muss ein Bild sein.', + 'in' => 'Der gewählte Wert für :attribute ist ungültig.', + 'in_array' => 'Der gewählte Wert für :attribute kommt nicht in :other vor.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => ':Attribute muss eine ganze Zahl sein.', + 'ip' => ':Attribute muss eine gültige IP-Adresse sein.', + 'ipv4' => ':Attribute muss eine gültige IPv4-Adresse sein.', + 'ipv6' => ':Attribute muss eine gültige IPv6-Adresse sein.', + 'json' => ':Attribute muss ein gültiger JSON-String sein.', + 'list' => ':Attribute muss eine Liste sein.', + 'lowercase' => ':Attribute muss in Kleinbuchstaben sein.', + 'lt' => [ + 'array' => ':Attribute muss weniger als :value Elemente haben.', + 'file' => ':Attribute muss kleiner als :value Kilobytes sein.', + 'numeric' => ':Attribute muss kleiner als :value sein.', + 'string' => ':Attribute muss kürzer als :value Zeichen sein.', + ], + 'lte' => [ + 'array' => ':Attribute darf maximal :value Elemente haben.', + 'file' => ':Attribute muss kleiner oder gleich :value Kilobytes sein.', + 'numeric' => ':Attribute muss kleiner oder gleich :value sein.', + 'string' => ':Attribute darf maximal :value Zeichen lang sein.', + ], + 'mac_address' => 'Der Wert muss eine gültige MAC-Adresse sein.', + 'max' => [ + 'array' => ':Attribute darf maximal :max Elemente haben.', + 'file' => ':Attribute darf maximal :max Kilobytes gross sein.', + 'numeric' => ':Attribute darf maximal :max sein.', + 'string' => ':Attribute darf maximal :max Zeichen haben.', + ], + 'max_digits' => ':Attribute darf maximal :max Ziffern lang sein.', + 'mimes' => ':Attribute muss den Dateityp :values haben.', + 'mimetypes' => ':Attribute muss den Dateityp :values haben.', + 'min' => [ + 'array' => ':Attribute muss mindestens :min Elemente haben.', + 'file' => ':Attribute muss mindestens :min Kilobytes gross sein.', + 'numeric' => ':Attribute muss mindestens :min sein.', + 'string' => ':Attribute muss mindestens :min Zeichen lang sein.', + ], + 'min_digits' => ':Attribute muss mindestens :min Ziffern lang sein.', + 'missing' => 'Das Feld :attribute muss fehlen.', + 'missing_if' => 'Das Feld :attribute muss fehlen, wenn :other gleich :value ist.', + 'missing_unless' => 'Das Feld :attribute muss fehlen, es sei denn, :other ist :value.', + 'missing_with' => 'Das Feld :attribute muss fehlen, wenn :values vorhanden ist.', + 'missing_with_all' => 'Das Feld :attribute muss fehlen, wenn :values vorhanden sind.', + 'multiple_of' => ':Attribute muss ein Vielfaches von :value sein.', + 'not_in' => 'Der gewählte Wert für :attribute ist ungültig.', + 'not_regex' => ':Attribute hat ein ungültiges Format.', + 'numeric' => ':Attribute muss eine Zahl sein.', + 'password' => [ + 'letters' => ':Attribute muss mindestens einen Buchstaben beinhalten.', + 'mixed' => ':Attribute muss mindestens einen Grossbuchstaben und einen Kleinbuchstaben beinhalten.', + 'numbers' => ':Attribute muss mindestens eine Zahl beinhalten.', + 'symbols' => ':Attribute muss mindestens ein Sonderzeichen beinhalten.', + 'uncompromised' => ':Attribute wurde in einem Datenleck gefunden. Bitte wählen Sie ein anderes :attribute.', + ], + 'present' => ':Attribute muss vorhanden sein.', + 'present_if' => 'Das Feld :attribute muss vorhanden sein, wenn :other gleich :value ist.', + 'present_unless' => 'Das Feld :attribute muss vorhanden sein, es sei denn, :other ist :value.', + 'present_with' => 'Das Feld :attribute muss vorhanden sein, wenn :values vorhanden ist.', + 'present_with_all' => 'Das Feld :attribute muss vorhanden sein, wenn :values vorhanden sind.', + 'prohibited' => ':Attribute ist unzulässig.', + 'prohibited_if' => ':Attribute ist unzulässig, wenn :other :value ist.', + 'prohibited_if_accepted' => 'The :attribute field is prohibited when :other is accepted.', + 'prohibited_if_declined' => 'The :attribute field is prohibited when :other is declined.', + 'prohibited_unless' => ':Attribute ist unzulässig, wenn :other nicht :values ist.', + 'prohibits' => ':Attribute verbietet die Angabe von :other.', + 'regex' => ':Attribute Format ist ungültig.', + 'required' => ':Attribute muss ausgefüllt werden.', + 'required_array_keys' => 'Dieses Feld muss Einträge enthalten für: :values.', + 'required_if' => ':Attribute muss ausgefüllt werden, wenn :other den Wert :value hat.', + 'required_if_accepted' => ':Attribute muss ausgefüllt werden, wenn :other gewählt ist.', + 'required_if_declined' => 'Das Feld :attribute ist erforderlich, wenn :other abgelehnt wird.', + 'required_unless' => ':Attribute muss ausgefüllt werden, wenn :other nicht den Wert :values hat.', + 'required_with' => ':Attribute muss ausgefüllt werden, wenn :values ausgefüllt wurde.', + 'required_with_all' => ':Attribute muss ausgefüllt werden, wenn :values ausgefüllt wurde.', + 'required_without' => ':Attribute muss ausgefüllt werden, wenn :values nicht ausgefüllt wurde.', + 'required_without_all' => ':Attribute muss ausgefüllt werden, wenn keines der Felder :values ausgefüllt wurde.', + 'same' => ':Attribute und :other müssen übereinstimmen.', + 'size' => [ + 'array' => ':Attribute muss genau :size Elemente haben.', + 'file' => ':Attribute muss :size Kilobyte gross sein.', + 'numeric' => ':Attribute muss gleich :size sein.', + 'string' => ':Attribute muss :size Zeichen lang sein.', + ], + 'starts_with' => ':Attribute muss mit einem der folgenden Anfänge aufweisen: :values', + 'string' => ':Attribute muss ein String sein.', + 'timezone' => ':Attribute muss eine gültige Zeitzone sein.', + 'ulid' => 'Die :attribute muss eine gültige ULID sein.', + 'unique' => ':Attribute ist bereits vergeben.', + 'uploaded' => ':Attribute konnte nicht hochgeladen werden.', + 'uppercase' => ':Attribute muss in Grossbuchstaben sein.', + 'url' => ':Attribute muss eine URL sein.', + 'uuid' => ':Attribute muss ein UUID sein.', + 'attributes' => [ + 'address' => 'Adresse', + 'affiliate_url' => 'Affiliate-URL', + 'age' => 'Alter', + 'amount' => 'Höhe', + 'announcement' => 'Bekanntmachung', + 'area' => 'Gebiet', + 'audience_prize' => 'Publikumspreis', + 'audience_winner' => 'audience winner', + 'available' => 'Verfügbar', + 'birthday' => 'Geburtstag', + 'body' => 'Körper', + 'city' => 'Stadt', + 'company' => 'company', + 'compilation' => 'Zusammenstellung', + 'concept' => 'Konzept', + 'conditions' => 'Bedingungen', + 'content' => 'Inhalt', + 'contest' => 'contest', + 'country' => 'Land', + 'cover' => 'Abdeckung', + 'created_at' => 'Erstellt am', + 'creator' => 'Ersteller', + 'currency' => 'Währung', + 'current_password' => 'Derzeitiges Passwort', + 'customer' => 'Kunde', + 'date' => 'Datum', + 'date_of_birth' => 'Geburtsdatum', + 'dates' => 'Termine', + 'day' => 'Tag', + 'deleted_at' => 'Gelöscht am', + 'description' => 'Beschreibung', + 'display_type' => 'Anzeigetyp', + 'district' => 'Bezirk', + 'duration' => 'Dauer', + 'email' => 'E-Mail-Adresse', + 'excerpt' => 'Auszug', + 'filter' => 'Filter', + 'finished_at' => 'fertig um', + 'first_name' => 'Vorname', + 'gender' => 'Geschlecht', + 'grand_prize' => 'Hauptpreis', + 'group' => 'Gruppe', + 'hour' => 'Stunde', + 'image' => 'Bild', + 'image_desktop' => 'Desktop-Bild', + 'image_main' => 'Hauptbild', + 'image_mobile' => 'mobiles Bild', + 'images' => 'Bilder', + 'is_audience_winner' => 'ist Publikumssieger', + 'is_hidden' => 'ist versteckt', + 'is_subscribed' => 'ist abonniert', + 'is_visible' => 'ist sichtbar', + 'is_winner' => 'ist Gewinner', + 'items' => 'Artikel', + 'key' => 'Schlüssel', + 'last_name' => 'Nachname', + 'lesson' => 'Lektion', + 'line_address_1' => 'Adresszeile 1', + 'line_address_2' => 'Adresszeile 2', + 'login' => 'Anmeldung', + 'message' => 'Nachricht', + 'middle_name' => 'Zweitname', + 'minute' => 'Minute', + 'mobile' => 'Handynummer', + 'month' => 'Monat', + 'name' => 'Name', + 'national_code' => 'Länderkennung', + 'nickname' => 'Spitzname', + 'number' => 'Nummer', + 'password' => 'Passwort', + 'password_confirmation' => 'Passwortbestätigung', + 'phone' => 'Telefonnummer', + 'photo' => 'Foto', + 'portfolio' => 'Portfolio', + 'postal_code' => 'Postleitzahl', + 'preview' => 'Vorschau', + 'price' => 'Preis', + 'product_id' => 'Produkt ID', + 'product_uid' => 'Produkt-UID', + 'product_uuid' => 'Produkt-UUID', + 'promo_code' => 'Aktionscode', + 'province' => 'Provinz', + 'quantity' => 'Menge', + 'reason' => 'Grund', + 'recaptcha_response_field' => 'Captcha-Feld', + 'referee' => 'Schiedsrichter', + 'referees' => 'Schiedsrichter', + 'reject_reason' => 'Ablehnungsgrund', + 'remember' => 'Erinnern', + 'restored_at' => 'Wiederhergestellt am', + 'result_text_under_image' => 'Ergebnistext unter Bild', + 'role' => 'Rolle', + 'rule' => 'Regel', + 'rules' => 'Regeln', + 'second' => 'Sekunde', + 'sex' => 'Geschlecht', + 'shipment' => 'Sendung', + 'short_text' => 'Kurzer Text', + 'size' => 'Größe', + 'situation' => 'Situation', + 'skills' => 'Fähigkeiten', + 'slug' => 'Schnecke', + 'specialization' => 'Spezialisierung', + 'started_at' => 'fing an bei', + 'state' => 'Bundesland', + 'status' => 'Status', + 'street' => 'Straße', + 'student' => 'Schüler/Student', + 'subject' => 'Gegenstand', + 'tag' => 'Etikett', + 'tags' => 'Stichworte', + 'teacher' => 'Lehrer', + 'terms' => 'Bedingungen', + 'test_description' => 'Test Beschreibung', + 'test_locale' => 'Test Region', + 'test_name' => 'Testname', + 'text' => 'Text', + 'time' => 'Uhrzeit', + 'title' => 'Titel', + 'type' => 'Typ', + 'updated_at' => 'Aktualisiert am', + 'user' => 'Benutzer', + 'username' => 'Benutzername', + 'value' => 'Wert', + 'winner' => 'winner', + 'work' => 'work', + 'year' => 'Jahr', + ], +]; diff --git a/lang/en.json b/lang/en.json new file mode 100644 index 00000000..6005129b --- /dev/null +++ b/lang/en.json @@ -0,0 +1,231 @@ +{ + "(and :count more error)": "(and :count more error)", + "(and :count more errors)": "(and :count more error)|(and :count more errors)|(and :count more errors)", + "A decryption key is required.": "A decryption key is required.", + "A reset link will be sent if the account exists.": "A reset link will be sent if the account exists.", + "A Timeout Occurred": "A Timeout Occurred", + "Accept": "Accept", + "Accepted": "Accepted", + "Action": "Action", + "Actions": "Actions", + "Add": "Add", + "Add :name": "Add :name", + "Admin": "Admin", + "Agree": "Agree", + "All rights reserved.": "All rights reserved.", + "Already Reported": "Already Reported", + "Archive": "Archive", + "Assign": "Assign", + "Associate": "Associate", + "Attach": "Attach", + "Bad Gateway": "Bad Gateway", + "Bad Request": "Bad Request", + "Bandwidth Limit Exceeded": "Bandwidth Limit Exceeded", + "Browse": "Browse", + "Cancel": "Cancel", + "Choose": "Choose", + "Choose :name": "Choose :name", + "Choose File": "Choose File", + "Choose Image": "Choose Image", + "Click to copy": "Click to copy", + "Client Closed Request": "Client Closed Request", + "Close": "Close", + "Collapse": "Collapse", + "Collapse All": "Collapse All", + "Comment": "Comment", + "Confirm": "Confirm", + "Conflict": "Conflict", + "Connect": "Connect", + "Connection Closed Without Response": "Connection Closed Without Response", + "Connection Timed Out": "Connection Timed Out", + "Continue": "Continue", + "Create": "Create", + "Create :name": "Create :name", + "Created": "Created", + "Delete": "Delete", + "Delete :name": "Delete :name", + "Detach": "Detach", + "Details": "Details", + "Disable": "Disable", + "Discard": "Discard", + "Done": "Done", + "Down": "Down", + "Duplicate": "Duplicate", + "Duplicate :name": "Duplicate :name", + "Edit": "Edit", + "Edit :name": "Edit :name", + "Enable": "Enable", + "Encrypted environment file already exists.": "Encrypted environment file already exists.", + "Encrypted environment file not found.": "Encrypted environment file not found.", + "Environment file already exists.": "Environment file already exists.", + "Environment file not found.": "Environment file not found.", + "errors": "errors", + "Expand": "Expand", + "Expand All": "Expand All", + "Expectation Failed": "Expectation Failed", + "Explanation": "Explanation", + "Export": "Export", + "Export :name": "Export :name", + "Failed Dependency": "Failed Dependency", + "File": "File", + "Files": "Files", + "Forbidden": "Forbidden", + "Found": "Found", + "Gateway Timeout": "Gateway Timeout", + "Go Home": "Go Home", + "Go to page :page": "Go to page :page", + "Gone": "Gone", + "Hello!": "Hello!", + "Hide": "Hide", + "Hide :name": "Hide :name", + "Home": "Home", + "HTTP Version Not Supported": "HTTP Version Not Supported", + "I'm a teapot": "I'm a teapot", + "If you did not create an account, no further action is required.": "If you did not create an account, no further action is required.", + "If you did not request a password reset, no further action is required.": "If you did not request a password reset, no further action is required.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:", + "IM Used": "IM Used", + "Image": "Image", + "Impersonate": "Impersonate", + "Impersonation": "Impersonation", + "Import": "Import", + "Import :name": "Import :name", + "Insufficient Storage": "Insufficient Storage", + "Internal Server Error": "Internal Server Error", + "Introduction": "Introduction", + "Invalid filename.": "Invalid filename.", + "Invalid JSON was returned from the route.": "Invalid JSON was returned from the route.", + "Invalid SSL Certificate": "Invalid SSL Certificate", + "length": "length", + "Length Required": "Length Required", + "Like": "Like", + "Load": "Load", + "Localize": "Localize", + "Location": "Location", + "Locked": "Locked", + "Log In": "Log In", + "Log Out": "Log Out", + "Login": "Login", + "Logout": "Logout", + "Loop Detected": "Loop Detected", + "Maintenance Mode": "Maintenance Mode", + "Method Not Allowed": "Method Not Allowed", + "Misdirected Request": "Misdirected Request", + "Moved Permanently": "Moved Permanently", + "Multi-Status": "Multi-Status", + "Multiple Choices": "Multiple Choices", + "Network Authentication Required": "Network Authentication Required", + "Network Connect Timeout Error": "Network Connect Timeout Error", + "Network Read Timeout Error": "Network Read Timeout Error", + "New": "New", + "New :name": "New :name", + "No": "No", + "No Content": "No Content", + "Non-Authoritative Information": "Non-Authoritative Information", + "Not Acceptable": "Not Acceptable", + "Not Extended": "Not Extended", + "Not Found": "Not Found", + "Not Implemented": "Not Implemented", + "Not Modified": "Not Modified", + "of": "of", + "OK": "OK", + "Open": "Open", + "Open in a current window": "Open in a current window", + "Open in a new window": "Open in a new window", + "Open in a parent frame": "Open in a parent frame", + "Open in the topmost frame": "Open in the topmost frame", + "Open on the website": "Open on the website", + "Origin Is Unreachable": "Origin Is Unreachable", + "Page Expired": "Page Expired", + "Pagination Navigation": "Pagination Navigation", + "Partial Content": "Partial Content", + "Payload Too Large": "Payload Too Large", + "Payment Required": "Payment Required", + "Permanent Redirect": "Permanent Redirect", + "Please click the button below to verify your email address.": "Please click the button below to verify your email address.", + "Precondition Failed": "Precondition Failed", + "Precondition Required": "Precondition Required", + "Preview": "Preview", + "Price": "Price", + "Processing": "Processing", + "Proxy Authentication Required": "Proxy Authentication Required", + "Railgun Error": "Railgun Error", + "Range Not Satisfiable": "Range Not Satisfiable", + "Record": "Record", + "Regards,": "Regards,", + "Register": "Register", + "Request Header Fields Too Large": "Request Header Fields Too Large", + "Request Timeout": "Request Timeout", + "Reset Content": "Reset Content", + "Reset Password": "Reset Password", + "Reset Password Notification": "Reset Password Notification", + "Restore": "Restore", + "Restore :name": "Restore :name", + "results": "results", + "Retry With": "Retry With", + "Save": "Save", + "Save & Close": "Save & Close", + "Save & Return": "Save & Return", + "Save :name": "Save :name", + "Search": "Search", + "Search :name": "Search :name", + "See Other": "See Other", + "Select": "Select", + "Select All": "Select All", + "Send": "Send", + "Server Error": "Server Error", + "Service Unavailable": "Service Unavailable", + "Session Has Expired": "Session Has Expired", + "Settings": "Settings", + "Show": "Show", + "Show :name": "Show :name", + "Show All": "Show All", + "Showing": "Showing", + "Sign In": "Sign In", + "Solve": "Solve", + "SSL Handshake Failed": "SSL Handshake Failed", + "Start": "Start", + "status": "status", + "Stop": "Stop", + "Submit": "Submit", + "Subscribe": "Subscribe", + "Switch": "Switch", + "Switch To Role": "Switch To Role", + "Switching Protocols": "Switching Protocols", + "Tag": "Tag", + "Tags": "Tags", + "Temporary Redirect": "Temporary Redirect", + "The given data was invalid.": "The given data was invalid.", + "The response is not a streamed response.": "The response is not a streamed response.", + "The response is not a view.": "The response is not a view.", + "This action is unauthorized.": "This action is unauthorized.", + "This password reset link will expire in :count minutes.": "This password reset link will expire in :count minutes.", + "to": "to", + "Toggle navigation": "Toggle navigation", + "Too Early": "Too Early", + "Too Many Requests": "Too Many Requests", + "Translate": "Translate", + "Translate It": "Translate It", + "Unauthorized": "Unauthorized", + "Unavailable For Legal Reasons": "Unavailable For Legal Reasons", + "Unknown Error": "Unknown Error", + "Unpack": "Unpack", + "Unprocessable Entity": "Unprocessable Entity", + "Unsubscribe": "Unsubscribe", + "Unsupported Media Type": "Unsupported Media Type", + "Up": "Up", + "Update": "Update", + "Update :name": "Update :name", + "Upgrade Required": "Upgrade Required", + "URI Too Long": "URI Too Long", + "Use Proxy": "Use Proxy", + "User": "User", + "Variant Also Negotiates": "Variant Also Negotiates", + "Verify Email Address": "Verify Email Address", + "View": "View", + "View :name": "View :name", + "Web Server is Down": "Web Server is Down", + "Whoops!": "Whoops!", + "Yes": "Yes", + "You are receiving this email because we received a password reset request for your account.": "You are receiving this email because we received a password reset request for your account." +} \ No newline at end of file diff --git a/lang/en/actions.php b/lang/en/actions.php new file mode 100644 index 00000000..7ff2b68b --- /dev/null +++ b/lang/en/actions.php @@ -0,0 +1,119 @@ + 'Accept', + 'action' => 'Action', + 'actions' => 'Actions', + 'add' => 'Add', + 'admin' => 'Admin', + 'agree' => 'Agree', + 'archive' => 'Archive', + 'assign' => 'Assign', + 'associate' => 'Associate', + 'attach' => 'Attach', + 'browse' => 'Browse', + 'cancel' => 'Cancel', + 'choose' => 'Choose', + 'choose_file' => 'Choose File', + 'choose_image' => 'Choose Image', + 'click_to_copy' => 'Click to copy', + 'close' => 'Close', + 'collapse' => 'Collapse', + 'collapse_all' => 'Collapse All', + 'comment' => 'Comment', + 'confirm' => 'Confirm', + 'connect' => 'Connect', + 'create' => 'Create', + 'delete' => 'Delete', + 'detach' => 'Detach', + 'details' => 'Details', + 'disable' => 'Disable', + 'discard' => 'Discard', + 'done' => 'Done', + 'down' => 'Down', + 'duplicate' => 'Duplicate', + 'edit' => 'Edit', + 'enable' => 'Enable', + 'expand' => 'Expand', + 'expand_all' => 'Expand All', + 'explanation' => 'Explanation', + 'export' => 'Export', + 'file' => 'File', + 'files' => 'Files', + 'go_home' => 'Go Home', + 'hide' => 'Hide', + 'home' => 'Home', + 'image' => 'Image', + 'impersonate' => 'Impersonate', + 'impersonation' => 'Impersonation', + 'import' => 'Import', + 'introduction' => 'Introduction', + 'like' => 'Like', + 'load' => 'Load', + 'localize' => 'Localize', + 'log_in' => 'Log In', + 'log_out' => 'Log Out', + 'named' => [ + 'add' => 'Add :name', + 'choose' => 'Choose :name', + 'create' => 'Create :name', + 'delete' => 'Delete :name', + 'duplicate' => 'Duplicate :name', + 'edit' => 'Edit :name', + 'export' => 'Export :name', + 'hide' => 'Hide :name', + 'import' => 'Import :name', + 'new' => 'New :name', + 'restore' => 'Restore :name', + 'save' => 'Save :name', + 'search' => 'Search :name', + 'show' => 'Show :name', + 'update' => 'Update :name', + 'view' => 'View :name', + ], + 'new' => 'New', + 'no' => 'No', + 'open' => 'Open', + 'open_website' => 'Open on the website', + 'preview' => 'Preview', + 'price' => 'Price', + 'record' => 'Record', + 'restore' => 'Restore', + 'save' => 'Save', + 'save_and_close' => 'Save & Close', + 'save_and_return' => 'Save & Return', + 'search' => 'Search', + 'select' => 'Select', + 'select_all' => 'Select All', + 'send' => 'Send', + 'settings' => 'Settings', + 'show' => 'Show', + 'show_all' => 'Show All', + 'sign_in' => 'Sign In', + 'solve' => 'Solve', + 'start' => 'Start', + 'stop' => 'Stop', + 'submit' => 'Submit', + 'subscribe' => 'Subscribe', + 'switch' => 'Switch', + 'switch_to_role' => 'Switch To Role', + 'tag' => 'Tag', + 'tags' => 'Tags', + 'target_link' => [ + 'blank' => 'Open in a new window', + 'parent' => 'Open in a parent frame', + 'self' => 'Open in a current window', + 'top' => 'Open in the topmost frame', + ], + 'translate' => 'Translate', + 'translate_it' => 'Translate It', + 'unpack' => 'Unpack', + 'unsubscribe' => 'Unsubscribe', + 'up' => 'Up', + 'update' => 'Update', + 'user' => 'User', + 'view' => 'View', + 'yes' => 'Yes', +]; diff --git a/lang/en/auth.php b/lang/en/auth.php new file mode 100644 index 00000000..ad725d8b --- /dev/null +++ b/lang/en/auth.php @@ -0,0 +1,9 @@ + 'These credentials do not match our records.', + 'password' => 'The provided password is incorrect.', + 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', +]; diff --git a/lang/en/http-statuses.php b/lang/en/http-statuses.php new file mode 100644 index 00000000..3346f78c --- /dev/null +++ b/lang/en/http-statuses.php @@ -0,0 +1,84 @@ + 'Unknown Error', + '100' => 'Continue', + '101' => 'Switching Protocols', + '102' => 'Processing', + '200' => 'OK', + '201' => 'Created', + '202' => 'Accepted', + '203' => 'Non-Authoritative Information', + '204' => 'No Content', + '205' => 'Reset Content', + '206' => 'Partial Content', + '207' => 'Multi-Status', + '208' => 'Already Reported', + '226' => 'IM Used', + '300' => 'Multiple Choices', + '301' => 'Moved Permanently', + '302' => 'Found', + '303' => 'See Other', + '304' => 'Not Modified', + '305' => 'Use Proxy', + '307' => 'Temporary Redirect', + '308' => 'Permanent Redirect', + '400' => 'Bad Request', + '401' => 'Unauthorized', + '402' => 'Payment Required', + '403' => 'Forbidden', + '404' => 'Not Found', + '405' => 'Method Not Allowed', + '406' => 'Not Acceptable', + '407' => 'Proxy Authentication Required', + '408' => 'Request Timeout', + '409' => 'Conflict', + '410' => 'Gone', + '411' => 'Length Required', + '412' => 'Precondition Failed', + '413' => 'Payload Too Large', + '414' => 'URI Too Long', + '415' => 'Unsupported Media Type', + '416' => 'Range Not Satisfiable', + '417' => 'Expectation Failed', + '418' => 'I\'m a teapot', + '419' => 'Session Has Expired', + '421' => 'Misdirected Request', + '422' => 'Unprocessable Entity', + '423' => 'Locked', + '424' => 'Failed Dependency', + '425' => 'Too Early', + '426' => 'Upgrade Required', + '428' => 'Precondition Required', + '429' => 'Too Many Requests', + '431' => 'Request Header Fields Too Large', + '444' => 'Connection Closed Without Response', + '449' => 'Retry With', + '451' => 'Unavailable For Legal Reasons', + '499' => 'Client Closed Request', + '500' => 'Internal Server Error', + '501' => 'Not Implemented', + '502' => 'Bad Gateway', + '503' => 'Maintenance Mode', + '504' => 'Gateway Timeout', + '505' => 'HTTP Version Not Supported', + '506' => 'Variant Also Negotiates', + '507' => 'Insufficient Storage', + '508' => 'Loop Detected', + '509' => 'Bandwidth Limit Exceeded', + '510' => 'Not Extended', + '511' => 'Network Authentication Required', + '520' => 'Unknown Error', + '521' => 'Web Server is Down', + '522' => 'Connection Timed Out', + '523' => 'Origin Is Unreachable', + '524' => 'A Timeout Occurred', + '525' => 'SSL Handshake Failed', + '526' => 'Invalid SSL Certificate', + '527' => 'Railgun Error', + '598' => 'Network Read Timeout Error', + '599' => 'Network Connect Timeout Error', + 'unknownError' => 'Unknown Error', +]; diff --git a/lang/en/pagination.php b/lang/en/pagination.php new file mode 100644 index 00000000..f4ceddec --- /dev/null +++ b/lang/en/pagination.php @@ -0,0 +1,8 @@ + 'Next »', + 'previous' => '« Previous', +]; diff --git a/lang/en/passwords.php b/lang/en/passwords.php new file mode 100644 index 00000000..f3b65bab --- /dev/null +++ b/lang/en/passwords.php @@ -0,0 +1,11 @@ + 'Your password has been reset.', + 'sent' => 'We have emailed your password reset link.', + 'throttled' => 'Please wait before retrying.', + 'token' => 'This password reset token is invalid.', + 'user' => 'We can\'t find a user with that email address.', +]; diff --git a/lang/en/validation.php b/lang/en/validation.php new file mode 100644 index 00000000..f35d9906 --- /dev/null +++ b/lang/en/validation.php @@ -0,0 +1,286 @@ + 'The :attribute field must be accepted.', + 'accepted_if' => 'The :attribute field must be accepted when :other is :value.', + 'active_url' => 'The :attribute field must be a valid URL.', + 'after' => 'The :attribute field must be a date after :date.', + 'after_or_equal' => 'The :attribute field must be a date after or equal to :date.', + 'alpha' => 'The :attribute field must only contain letters.', + 'alpha_dash' => 'The :attribute field must only contain letters, numbers, dashes, and underscores.', + 'alpha_num' => 'The :attribute field must only contain letters and numbers.', + 'any_of' => 'The :attribute field is invalid.', + 'array' => 'The :attribute field must be an array.', + 'ascii' => 'The :attribute field must only contain single-byte alphanumeric characters and symbols.', + 'before' => 'The :attribute field must be a date before :date.', + 'before_or_equal' => 'The :attribute field must be a date before or equal to :date.', + 'between' => [ + 'array' => 'The :attribute field must have between :min and :max items.', + 'file' => 'The :attribute field must be between :min and :max kilobytes.', + 'numeric' => 'The :attribute field must be between :min and :max.', + 'string' => 'The :attribute field must be between :min and :max characters.', + ], + 'boolean' => 'The :attribute field must be true or false.', + 'can' => 'The :attribute field contains an unauthorized value.', + 'confirmed' => 'The :attribute field confirmation does not match.', + 'contains' => 'The :attribute field is missing a required value.', + 'current_password' => 'The password is incorrect.', + 'date' => 'The :attribute field must be a valid date.', + 'date_equals' => 'The :attribute field must be a date equal to :date.', + 'date_format' => 'The :attribute field must match the format :format.', + 'decimal' => 'The :attribute field must have :decimal decimal places.', + 'declined' => 'The :attribute field must be declined.', + 'declined_if' => 'The :attribute field must be declined when :other is :value.', + 'different' => 'The :attribute field and :other must be different.', + 'digits' => 'The :attribute field must be :digits digits.', + 'digits_between' => 'The :attribute field must be between :min and :max digits.', + 'dimensions' => 'The :attribute field has invalid image dimensions.', + 'distinct' => 'The :attribute field has a duplicate value.', + 'doesnt_end_with' => 'The :attribute field must not end with one of the following: :values.', + 'doesnt_start_with' => 'The :attribute field must not start with one of the following: :values.', + 'email' => 'The :attribute field must be a valid email address.', + 'ends_with' => 'The :attribute field must end with one of the following: :values.', + 'enum' => 'The selected :attribute is invalid.', + 'exists' => 'The selected :attribute is invalid.', + 'extensions' => 'The :attribute field must have one of the following extensions: :values.', + 'file' => 'The :attribute field must be a file.', + 'filled' => 'The :attribute field must have a value.', + 'gt' => [ + 'array' => 'The :attribute field must have more than :value items.', + 'file' => 'The :attribute field must be greater than :value kilobytes.', + 'numeric' => 'The :attribute field must be greater than :value.', + 'string' => 'The :attribute field must be greater than :value characters.', + ], + 'gte' => [ + 'array' => 'The :attribute field must have :value items or more.', + 'file' => 'The :attribute field must be greater than or equal to :value kilobytes.', + 'numeric' => 'The :attribute field must be greater than or equal to :value.', + 'string' => 'The :attribute field must be greater than or equal to :value characters.', + ], + 'hex_color' => 'The :attribute field must be a valid hexadecimal color.', + 'image' => 'The :attribute field must be an image.', + 'in' => 'The selected :attribute is invalid.', + 'in_array' => 'The :attribute field must exist in :other.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => 'The :attribute field must be an integer.', + 'ip' => 'The :attribute field must be a valid IP address.', + 'ipv4' => 'The :attribute field must be a valid IPv4 address.', + 'ipv6' => 'The :attribute field must be a valid IPv6 address.', + 'json' => 'The :attribute field must be a valid JSON string.', + 'list' => 'The :attribute field must be a list.', + 'lowercase' => 'The :attribute field must be lowercase.', + 'lt' => [ + 'array' => 'The :attribute field must have less than :value items.', + 'file' => 'The :attribute field must be less than :value kilobytes.', + 'numeric' => 'The :attribute field must be less than :value.', + 'string' => 'The :attribute field must be less than :value characters.', + ], + 'lte' => [ + 'array' => 'The :attribute field must not have more than :value items.', + 'file' => 'The :attribute field must be less than or equal to :value kilobytes.', + 'numeric' => 'The :attribute field must be less than or equal to :value.', + 'string' => 'The :attribute field must be less than or equal to :value characters.', + ], + 'mac_address' => 'The :attribute field must be a valid MAC address.', + 'max' => [ + 'array' => 'The :attribute field must not have more than :max items.', + 'file' => 'The :attribute field must not be greater than :max kilobytes.', + 'numeric' => 'The :attribute field must not be greater than :max.', + 'string' => 'The :attribute field must not be greater than :max characters.', + ], + 'max_digits' => 'The :attribute field must not have more than :max digits.', + 'mimes' => 'The :attribute field must be a file of type: :values.', + 'mimetypes' => 'The :attribute field must be a file of type: :values.', + 'min' => [ + 'array' => 'The :attribute field must have at least :min items.', + 'file' => 'The :attribute field must be at least :min kilobytes.', + 'numeric' => 'The :attribute field must be at least :min.', + 'string' => 'The :attribute field must be at least :min characters.', + ], + 'min_digits' => 'The :attribute field must have at least :min digits.', + 'missing' => 'The :attribute field must be missing.', + 'missing_if' => 'The :attribute field must be missing when :other is :value.', + 'missing_unless' => 'The :attribute field must be missing unless :other is :value.', + 'missing_with' => 'The :attribute field must be missing when :values is present.', + 'missing_with_all' => 'The :attribute field must be missing when :values are present.', + 'multiple_of' => 'The :attribute field must be a multiple of :value.', + 'not_in' => 'The selected :attribute is invalid.', + 'not_regex' => 'The :attribute field format is invalid.', + 'numeric' => 'The :attribute field must be a number.', + 'password' => [ + 'letters' => 'The :attribute field must contain at least one letter.', + 'mixed' => 'The :attribute field must contain at least one uppercase and one lowercase letter.', + 'numbers' => 'The :attribute field must contain at least one number.', + 'symbols' => 'The :attribute field must contain at least one symbol.', + 'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.', + ], + 'present' => 'The :attribute field must be present.', + 'present_if' => 'The :attribute field must be present when :other is :value.', + 'present_unless' => 'The :attribute field must be present unless :other is :value.', + 'present_with' => 'The :attribute field must be present when :values is present.', + 'present_with_all' => 'The :attribute field must be present when :values are present.', + 'prohibited' => 'The :attribute field is prohibited.', + 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.', + 'prohibited_if_accepted' => 'The :attribute field is prohibited when :other is accepted.', + 'prohibited_if_declined' => 'The :attribute field is prohibited when :other is declined.', + 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.', + 'prohibits' => 'The :attribute field prohibits :other from being present.', + 'regex' => 'The :attribute field format is invalid.', + 'required' => 'The :attribute field is required.', + 'required_array_keys' => 'The :attribute field must contain entries for: :values.', + 'required_if' => 'The :attribute field is required when :other is :value.', + 'required_if_accepted' => 'The :attribute field is required when :other is accepted.', + 'required_if_declined' => 'The :attribute field is required when :other is declined.', + 'required_unless' => 'The :attribute field is required unless :other is in :values.', + 'required_with' => 'The :attribute field is required when :values is present.', + 'required_with_all' => 'The :attribute field is required when :values are present.', + 'required_without' => 'The :attribute field is required when :values is not present.', + 'required_without_all' => 'The :attribute field is required when none of :values are present.', + 'same' => 'The :attribute field must match :other.', + 'size' => [ + 'array' => 'The :attribute field must contain :size items.', + 'file' => 'The :attribute field must be :size kilobytes.', + 'numeric' => 'The :attribute field must be :size.', + 'string' => 'The :attribute field must be :size characters.', + ], + 'starts_with' => 'The :attribute field must start with one of the following: :values.', + 'string' => 'The :attribute field must be a string.', + 'timezone' => 'The :attribute field must be a valid timezone.', + 'ulid' => 'The :attribute field must be a valid ULID.', + 'unique' => 'The :attribute has already been taken.', + 'uploaded' => 'The :attribute failed to upload.', + 'uppercase' => 'The :attribute field must be uppercase.', + 'url' => 'The :attribute field must be a valid URL.', + 'uuid' => 'The :attribute field must be a valid UUID.', + 'attributes' => [ + 'address' => 'address', + 'affiliate_url' => 'affiliate URL', + 'age' => 'age', + 'amount' => 'amount', + 'announcement' => 'announcement', + 'area' => 'area', + 'audience_prize' => 'audience prize', + 'audience_winner' => 'audience winner', + 'available' => 'available', + 'birthday' => 'birthday', + 'body' => 'body', + 'city' => 'city', + 'company' => 'company', + 'compilation' => 'compilation', + 'concept' => 'concept', + 'conditions' => 'conditions', + 'content' => 'content', + 'contest' => 'contest', + 'country' => 'country', + 'cover' => 'cover', + 'created_at' => 'created at', + 'creator' => 'creator', + 'currency' => 'currency', + 'current_password' => 'current password', + 'customer' => 'customer', + 'date' => 'date', + 'date_of_birth' => 'date of birth', + 'dates' => 'dates', + 'day' => 'day', + 'deleted_at' => 'deleted at', + 'description' => 'description', + 'display_type' => 'display type', + 'district' => 'district', + 'duration' => 'duration', + 'email' => 'email', + 'excerpt' => 'excerpt', + 'filter' => 'filter', + 'finished_at' => 'finished at', + 'first_name' => 'first name', + 'gender' => 'gender', + 'grand_prize' => 'grand prize', + 'group' => 'group', + 'hour' => 'hour', + 'image' => 'image', + 'image_desktop' => 'desktop image', + 'image_main' => 'main image', + 'image_mobile' => 'mobile image', + 'images' => 'images', + 'is_audience_winner' => 'is audience winner', + 'is_hidden' => 'is hidden', + 'is_subscribed' => 'is subscribed', + 'is_visible' => 'is visible', + 'is_winner' => 'is winner', + 'items' => 'items', + 'key' => 'key', + 'last_name' => 'last name', + 'lesson' => 'lesson', + 'line_address_1' => 'line address 1', + 'line_address_2' => 'line address 2', + 'login' => 'login', + 'message' => 'message', + 'middle_name' => 'middle name', + 'minute' => 'minute', + 'mobile' => 'mobile', + 'month' => 'month', + 'name' => 'name', + 'national_code' => 'national code', + 'nickname' => 'nickname', + 'number' => 'number', + 'password' => 'password', + 'password_confirmation' => 'password confirmation', + 'phone' => 'phone', + 'photo' => 'photo', + 'portfolio' => 'portfolio', + 'postal_code' => 'postal code', + 'preview' => 'preview', + 'price' => 'price', + 'product_id' => 'product ID', + 'product_uid' => 'product UID', + 'product_uuid' => 'product UUID', + 'promo_code' => 'promo code', + 'province' => 'province', + 'quantity' => 'quantity', + 'reason' => 'reason', + 'recaptcha_response_field' => 'recaptcha response field', + 'referee' => 'referee', + 'referees' => 'referees', + 'reject_reason' => 'reject reason', + 'remember' => 'remember', + 'restored_at' => 'restored at', + 'result_text_under_image' => 'result text under image', + 'role' => 'role', + 'rule' => 'rule', + 'rules' => 'rules', + 'second' => 'second', + 'sex' => 'sex', + 'shipment' => 'shipment', + 'short_text' => 'short text', + 'size' => 'size', + 'situation' => 'situation', + 'skills' => 'skills', + 'slug' => 'slug', + 'specialization' => 'specialization', + 'started_at' => 'started at', + 'state' => 'state', + 'status' => 'status', + 'street' => 'street', + 'student' => 'student', + 'subject' => 'subject', + 'tag' => 'tag', + 'tags' => 'tags', + 'teacher' => 'teacher', + 'terms' => 'terms', + 'test_description' => 'test description', + 'test_locale' => 'test locale', + 'test_name' => 'test name', + 'text' => 'text', + 'time' => 'time', + 'title' => 'title', + 'type' => 'type', + 'updated_at' => 'updated at', + 'user' => 'user', + 'username' => 'username', + 'value' => 'value', + 'winner' => 'winner', + 'work' => 'work', + 'year' => 'year', + ], +]; diff --git a/lang/es.json b/lang/es.json new file mode 100644 index 00000000..a44d30ea --- /dev/null +++ b/lang/es.json @@ -0,0 +1,231 @@ +{ + "(and :count more error)": "(y :count error más)", + "(and :count more errors)": "(y :count error más)|(y :count errores más)|(y :count errores más)", + "A decryption key is required.": "Se requiere una clave de descifrado.", + "A reset link will be sent if the account exists.": "Se enviará un enlace de restablecimiento si la cuenta existe.", + "A Timeout Occurred": "Se produjo un tiempo de espera", + "Accept": "Aceptar", + "Accepted": "Aceptado", + "Action": "Acción", + "Actions": "Acciones", + "Add": "Añadir", + "Add :name": "Agregar :name", + "Admin": "Administrar", + "Agree": "Aceptar", + "All rights reserved.": "Todos los derechos reservados.", + "Already Reported": "Ya Reportado", + "Archive": "Archivar", + "Assign": "Asignar", + "Associate": "Asociar", + "Attach": "Adjuntar", + "Bad Gateway": "Mala puerta de enlace", + "Bad Request": "Solicitud incorrecta", + "Bandwidth Limit Exceeded": "Límite de ancho de banda excedido", + "Browse": "Navegar", + "Cancel": "Cancelar", + "Choose": "Elija", + "Choose :name": "Elegir :name", + "Choose File": "Elija archivo", + "Choose Image": "Elegir Imagen", + "Click to copy": "Haga clic para copiar", + "Client Closed Request": "Solicitud cerrada del cliente", + "Close": "Cerrar", + "Collapse": "Colapsar", + "Collapse All": "Colapsar todo", + "Comment": "Comentar", + "Confirm": "Confirmar", + "Conflict": "Conflicto", + "Connect": "Conectar", + "Connection Closed Without Response": "Conexión cerrada sin respuesta", + "Connection Timed Out": "Tiempo de conexión agotado", + "Continue": "Continuar", + "Create": "Crear", + "Create :name": "Crear :name", + "Created": "Creado", + "Delete": "Eliminar", + "Delete :name": "Eliminar :name", + "Detach": "Desvincular", + "Details": "Detalles", + "Disable": "Deshabilitar", + "Discard": "Descartar", + "Done": "Hecho", + "Down": "Abajo", + "Duplicate": "Duplicar", + "Duplicate :name": "Duplicar :name", + "Edit": "Editar", + "Edit :name": "Editar :name", + "Enable": "Habilitar", + "Encrypted environment file already exists.": "El archivo de entorno cifrado ya existe.", + "Encrypted environment file not found.": "No se encontró el archivo de entorno cifrado.", + "Environment file already exists.": "El archivo de entorno ya existe.", + "Environment file not found.": "Archivo de entorno no encontrado.", + "errors": "errores", + "Expand": "Expandir", + "Expand All": "Expandir todo", + "Expectation Failed": "Expectativa fallida", + "Explanation": "Explicación", + "Export": "Exportar", + "Export :name": "Exportar :name", + "Failed Dependency": "Dependencia fallida", + "File": "Archivo", + "Files": "Archivos", + "Forbidden": "Prohibido", + "Found": "Encontrado", + "Gateway Timeout": "Tiempo de espera de puerta de enlace", + "Go Home": "Ir a inicio", + "Go to page :page": "Ir a la página :page", + "Gone": "Recurso no disponible", + "Hello!": "¡Hola!", + "Hide": "Ocultar", + "Hide :name": "Ocultar :name", + "Home": "Inicio", + "HTTP Version Not Supported": "Versión HTTP no compatible", + "I'm a teapot": "Soy una tetera", + "If you did not create an account, no further action is required.": "Si no ha creado una cuenta, no se requiere ninguna acción adicional.", + "If you did not request a password reset, no further action is required.": "Si no ha solicitado el restablecimiento de contraseña, omita este mensaje de correo electrónico.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Si está teniendo problemas al hacer clic en el botón \":actionText\", copie y pegue la URL de abajo\nen su navegador web:", + "IM Used": "IM usado", + "Image": "Imagen", + "Impersonate": "Personificar", + "Impersonation": "Personificación", + "Import": "Importar", + "Import :name": "Importar :name", + "Insufficient Storage": "Espacio insuficiente", + "Internal Server Error": "Error interno del servidor", + "Introduction": "Introducción", + "Invalid filename.": "Nombre de archivo no válido.", + "Invalid JSON was returned from the route.": "Se devolvió un JSON no válido desde la ruta.", + "Invalid SSL Certificate": "Certificado SSL no válido", + "length": "longitud", + "Length Required": "Longitud requerida", + "Like": "Me gusta", + "Load": "Cargar", + "Localize": "Localizar", + "Location": "Ubicación", + "Locked": "Bloqueado", + "Log In": "Iniciar sesión", + "Log Out": "Finalizar sesión", + "Login": "Iniciar sesión", + "Logout": "Finalizar sesión", + "Loop Detected": "Bucle detectado", + "Maintenance Mode": "Modo de mantenimiento", + "Method Not Allowed": "Método no permitido", + "Misdirected Request": "Solicitud mal dirigida", + "Moved Permanently": "Movido permanentemente", + "Multi-Status": "Multiestado", + "Multiple Choices": "Múltiples opciones", + "Network Authentication Required": "Se requiere autenticación de red", + "Network Connect Timeout Error": "Error de tiempo de espera de conexión de red", + "Network Read Timeout Error": "Error de tiempo de espera de lectura de red", + "New": "Nuevo", + "New :name": "Nuevo :name", + "No": "No", + "No Content": "Sin contenido", + "Non-Authoritative Information": "Información no autorizada", + "Not Acceptable": "Inaceptable", + "Not Extended": "no extendido", + "Not Found": "No encontrado", + "Not Implemented": "No se ha implementado", + "Not Modified": "No modificado", + "of": "de", + "OK": "Correcto", + "Open": "Abrir", + "Open in a current window": "Abrir en una ventana actual", + "Open in a new window": "Abrir en una ventana nueva", + "Open in a parent frame": "Abrir en un marco principal", + "Open in the topmost frame": "Abrir en el marco superior", + "Open on the website": "Abrir en el sitio web", + "Origin Is Unreachable": "El origen es inalcanzable", + "Page Expired": "Página expirada", + "Pagination Navigation": "Navegación por los enlaces de paginación", + "Partial Content": "Contenido parcial", + "Payload Too Large": "Solicitud demasiado grande", + "Payment Required": "Pago requerido", + "Permanent Redirect": "Redirección permanente", + "Please click the button below to verify your email address.": "Por favor, haga clic en el botón de abajo para verificar su dirección de correo electrónico.", + "Precondition Failed": "Error de condición previa", + "Precondition Required": "Precondición requerida", + "Preview": "Previsualizar", + "Price": "Precio", + "Processing": "Procesando", + "Proxy Authentication Required": "Se requiere autenticación proxy", + "Railgun Error": "Error de cañón de riel", + "Range Not Satisfiable": "Rango no satisfactorio", + "Record": "Registro", + "Regards,": "Saludos,", + "Register": "Registrarse", + "Request Header Fields Too Large": "Campos de encabezado de solicitud demasiado grandes", + "Request Timeout": "Solicitud de tiempo de espera", + "Reset Content": "Restablecer contenido", + "Reset Password": "Restablecer contraseña", + "Reset Password Notification": "Notificación de restablecimiento de contraseña", + "Restore": "Restaurar", + "Restore :name": "Restaurar :name", + "results": "resultados", + "Retry With": "Reintentar con", + "Save": "Guardar", + "Save & Close": "Guardar y cerrar", + "Save & Return": "Guardar y volver", + "Save :name": "Guardar :name", + "Search": "Buscar", + "Search :name": "Buscar :name", + "See Other": "Ver otros", + "Select": "Seleccione", + "Select All": "Seleccionar todo", + "Send": "Enviar", + "Server Error": "Error del servidor", + "Service Unavailable": "Servicio no disponible", + "Session Has Expired": "La sesión ha expirado", + "Settings": "Configuración", + "Show": "Mostrar", + "Show :name": "Mostrar :name", + "Show All": "Mostrar todo", + "Showing": "Mostrando", + "Sign In": "Iniciar sesión", + "Solve": "Resolver", + "SSL Handshake Failed": "Protocolo de enlace SSL fallido", + "Start": "Comenzar", + "status": "estado", + "Stop": "Detener", + "Submit": "Enviar", + "Subscribe": "Suscriba", + "Switch": "Cambiar", + "Switch To Role": "Cambiar de rol", + "Switching Protocols": "Protocolos de conmutación", + "Tag": "Etiqueta", + "Tags": "Etiquetas", + "Temporary Redirect": "Redirección temporal", + "The given data was invalid.": "Los datos proporcionados no son válidos.", + "The response is not a streamed response.": "La respuesta no es una respuesta transmitida.", + "The response is not a view.": "La respuesta no es una vista.", + "This action is unauthorized.": "Esta acción no está autorizada.", + "This password reset link will expire in :count minutes.": "Este enlace de restablecimiento de contraseña expirará en :count minutos.", + "to": "al", + "Toggle navigation": "Alternar navegación", + "Too Early": "Demasiado temprano", + "Too Many Requests": "Demasiadas peticiones", + "Translate": "Traducir", + "Translate It": "Traducirlo", + "Unauthorized": "No autorizado", + "Unavailable For Legal Reasons": "No disponible por razones legales", + "Unknown Error": "Error desconocido", + "Unpack": "Desglosar", + "Unprocessable Entity": "Entidad no procesable", + "Unsubscribe": "Darse de baja", + "Unsupported Media Type": "Tipo de medio no admitido", + "Up": "Arriba", + "Update": "Actualizar", + "Update :name": "Actualizar :name", + "Upgrade Required": "Se requiere actualización", + "URI Too Long": "URI demasiado largo", + "Use Proxy": "Usa proxy", + "User": "Usuario", + "Variant Also Negotiates": "Variante También Negocia", + "Verify Email Address": "Confirme su correo electrónico", + "View": "Ver", + "View :name": "Ver :name", + "Web Server is Down": "El servidor web está caído", + "Whoops!": "¡Ups!", + "Yes": "Sí", + "You are receiving this email because we received a password reset request for your account.": "Ha recibido este mensaje porque se solicitó un restablecimiento de contraseña para su cuenta." +} \ No newline at end of file diff --git a/lang/es/actions.php b/lang/es/actions.php new file mode 100644 index 00000000..f709ddfe --- /dev/null +++ b/lang/es/actions.php @@ -0,0 +1,119 @@ + 'Aceptar', + 'action' => 'Acción', + 'actions' => 'Acciones', + 'add' => 'Agregar', + 'admin' => 'Administrar', + 'agree' => 'Aceptar', + 'archive' => 'Archivar', + 'assign' => 'Asignar', + 'associate' => 'Asociar', + 'attach' => 'Adjuntar', + 'browse' => 'Navegar', + 'cancel' => 'Cancelar', + 'choose' => 'Elegir', + 'choose_file' => 'Elegir archivo', + 'choose_image' => 'Elegir Imagen', + 'click_to_copy' => 'Haga clic para copiar', + 'close' => 'Cerrar', + 'collapse' => 'Colapsar', + 'collapse_all' => 'Colapsar todo', + 'comment' => 'Comentar', + 'confirm' => 'Confirmar', + 'connect' => 'Conectar', + 'create' => 'Crear', + 'delete' => 'Borrar', + 'detach' => 'Desasociar', + 'details' => 'Detalles', + 'disable' => 'Desactivar', + 'discard' => 'Descartar', + 'done' => 'Hecho', + 'down' => 'Abajo', + 'duplicate' => 'Duplicar', + 'edit' => 'Editar', + 'enable' => 'Permitir', + 'expand' => 'Expandir', + 'expand_all' => 'Expandir todo', + 'explanation' => 'Explicación', + 'export' => 'Exportar', + 'file' => 'Archivo', + 'files' => 'Archivos', + 'go_home' => 'Ir a Inicio', + 'hide' => 'Ocultar', + 'home' => 'Inicio', + 'image' => 'Imagen', + 'impersonate' => 'Personificar', + 'impersonation' => 'Personificación', + 'import' => 'Importar', + 'introduction' => 'Introducción', + 'like' => 'Me gusta', + 'load' => 'Cargar', + 'localize' => 'Localizar', + 'log_in' => 'Acceder', + 'log_out' => 'Cerrar sesión', + 'named' => [ + 'add' => 'Agregar :name', + 'choose' => 'Elegir :name', + 'create' => 'Crear :name', + 'delete' => 'Eliminar :name', + 'duplicate' => 'Duplicar :name', + 'edit' => 'Editar :name', + 'export' => 'Exportar :name', + 'hide' => 'Ocultar :name', + 'import' => 'Importar :name', + 'new' => 'Nuevo :name', + 'restore' => 'Restaurar :name', + 'save' => 'Guardar :name', + 'search' => 'Buscar :name', + 'show' => 'Mostrar :name', + 'update' => 'Actualizar :name', + 'view' => 'Ver :name', + ], + 'new' => 'Nuevo', + 'no' => 'No', + 'open' => 'Abrir', + 'open_website' => 'Abrir en el sitio web', + 'preview' => 'Previsualizar', + 'price' => 'Precio', + 'record' => 'Registro', + 'restore' => 'Restaurar', + 'save' => 'Guardar', + 'save_and_close' => 'Guardar y cerrar', + 'save_and_return' => 'Guardar y volver', + 'search' => 'Buscar', + 'select' => 'Seleccionar', + 'select_all' => 'Seleccionar todo', + 'send' => 'Enviar', + 'settings' => 'Ajustes', + 'show' => 'Mostrar', + 'show_all' => 'Mostrar todo', + 'sign_in' => 'Iniciar sesión', + 'solve' => 'Resolver', + 'start' => 'Comenzar', + 'stop' => 'Detener', + 'submit' => 'Enviar', + 'subscribe' => 'Suscribir', + 'switch' => 'Cambiar', + 'switch_to_role' => 'Cambiar de rol', + 'tag' => 'Etiqueta', + 'tags' => 'Etiquetas', + 'target_link' => [ + 'blank' => 'Abrir en una ventana nueva', + 'parent' => 'Abrir en el marco principal', + 'self' => 'Abrir en la ventana actual', + 'top' => 'Abrir en el marco superior', + ], + 'translate' => 'Traducir', + 'translate_it' => 'Traducirlo', + 'unpack' => 'Desglosar', + 'unsubscribe' => 'Darse de baja', + 'up' => 'Arriba', + 'update' => 'Actualizar', + 'user' => 'Usuario', + 'view' => 'Ver', + 'yes' => 'Sí', +]; diff --git a/lang/es/auth.php b/lang/es/auth.php new file mode 100644 index 00000000..888279b0 --- /dev/null +++ b/lang/es/auth.php @@ -0,0 +1,9 @@ + 'Estas credenciales no coinciden con nuestros registros.', + 'password' => 'La contraseña es incorrecta.', + 'throttle' => 'Demasiados intentos de acceso. Por favor intente nuevamente en :seconds segundos.', +]; diff --git a/lang/es/http-statuses.php b/lang/es/http-statuses.php new file mode 100644 index 00000000..0548dab8 --- /dev/null +++ b/lang/es/http-statuses.php @@ -0,0 +1,84 @@ + 'Error desconocido', + '100' => 'Continuar', + '101' => 'Protocolos de conmutación', + '102' => 'Procesando', + '200' => 'DE ACUERDO', + '201' => 'Creado', + '202' => 'Aceptado', + '203' => 'Información no autorizada', + '204' => 'Sin contenido', + '205' => 'Restablecer contenido', + '206' => 'Contenido parcial', + '207' => 'Multiestado', + '208' => 'Ya Reportado', + '226' => 'IM usado', + '300' => 'Múltiples opciones', + '301' => 'Movido permanentemente', + '302' => 'Encontrado', + '303' => 'Ver otros', + '304' => 'No modificado', + '305' => 'Usa proxy', + '307' => 'Redirección temporal', + '308' => 'Redirección permanente', + '400' => 'Solicitud incorrecta', + '401' => 'No autorizado', + '402' => 'Pago requerido', + '403' => 'Prohibido', + '404' => 'No encontrado', + '405' => 'Método no permitido', + '406' => 'Inaceptable', + '407' => 'Se requiere autenticación proxy', + '408' => 'Solicitud de tiempo de espera', + '409' => 'Conflicto', + '410' => 'Recurso no disponible', + '411' => 'Longitud requerida', + '412' => 'Error de condición previa', + '413' => 'Solicitud demasiado grande', + '414' => 'URI demasiado largo', + '415' => 'Tipo de medio no admitido', + '416' => 'Rango no satisfactorio', + '417' => 'Expectativa fallida', + '418' => 'Soy una tetera', + '419' => 'La sesión ha expirado', + '421' => 'Solicitud mal dirigida', + '422' => 'Entidad no procesable', + '423' => 'Bloqueado', + '424' => 'Dependencia fallida', + '425' => 'Demasiado temprano', + '426' => 'Se requiere actualización', + '428' => 'Precondición requerida', + '429' => 'Demasiadas solicitudes', + '431' => 'Campos de encabezado de solicitud demasiado grandes', + '444' => 'Conexión cerrada sin respuesta', + '449' => 'Reintentar con', + '451' => 'No disponible por razones legales', + '499' => 'Solicitud cerrada del cliente', + '500' => 'Error interno del servidor', + '501' => 'No se ha implementado', + '502' => 'Mala puerta de enlace', + '503' => 'Modo de mantenimiento', + '504' => 'Tiempo de espera de puerta de enlace', + '505' => 'Versión HTTP no compatible', + '506' => 'Variante También Negocia', + '507' => 'Espacio insuficiente', + '508' => 'Bucle detectado', + '509' => 'Límite de ancho de banda excedido', + '510' => 'no extendido', + '511' => 'Se requiere autenticación de red', + '520' => 'Error desconocido', + '521' => 'El servidor web está caído', + '522' => 'Tiempo de conexión agotado', + '523' => 'El origen es inalcanzable', + '524' => 'Se produjo un tiempo de espera', + '525' => 'Protocolo de enlace SSL fallido', + '526' => 'Certificado SSL no válido', + '527' => 'Error de cañón de riel', + '598' => 'Error de tiempo de espera de lectura de red', + '599' => 'Error de tiempo de espera de conexión de red', + 'unknownError' => 'Error desconocido', +]; diff --git a/lang/es/pagination.php b/lang/es/pagination.php new file mode 100644 index 00000000..03816a38 --- /dev/null +++ b/lang/es/pagination.php @@ -0,0 +1,8 @@ + 'Siguiente »', + 'previous' => '« Anterior', +]; diff --git a/lang/es/passwords.php b/lang/es/passwords.php new file mode 100644 index 00000000..75b5e89c --- /dev/null +++ b/lang/es/passwords.php @@ -0,0 +1,11 @@ + 'Su contraseña ha sido restablecida.', + 'sent' => 'Le hemos enviado por correo electrónico el enlace para restablecer su contraseña.', + 'throttled' => 'Por favor espere antes de intentar de nuevo.', + 'token' => 'El token de restablecimiento de contraseña es inválido.', + 'user' => 'No encontramos ningún usuario con ese correo electrónico.', +]; diff --git a/lang/es/validation.php b/lang/es/validation.php new file mode 100644 index 00000000..d1425a00 --- /dev/null +++ b/lang/es/validation.php @@ -0,0 +1,286 @@ + 'El campo :attribute debe ser aceptado.', + 'accepted_if' => 'El campo :attribute debe ser aceptado cuando :other sea :value.', + 'active_url' => 'El campo :attribute debe ser una URL válida.', + 'after' => 'El campo :attribute debe ser una fecha posterior a :date.', + 'after_or_equal' => 'El campo :attribute debe ser una fecha posterior o igual a :date.', + 'alpha' => 'El campo :attribute sólo debe contener letras.', + 'alpha_dash' => 'El campo :attribute sólo debe contener letras, números, guiones y guiones bajos.', + 'alpha_num' => 'El campo :attribute sólo debe contener letras y números.', + 'any_of' => 'El campo :attribute no es válido.', + 'array' => 'El campo :attribute debe ser un conjunto.', + 'ascii' => 'El campo :attribute solo debe contener caracteres alfanuméricos y símbolos de un solo byte.', + 'before' => 'El campo :attribute debe ser una fecha anterior a :date.', + 'before_or_equal' => 'El campo :attribute debe ser una fecha anterior o igual a :date.', + 'between' => [ + 'array' => 'El campo :attribute tiene que tener entre :min - :max elementos.', + 'file' => 'El campo :attribute debe pesar entre :min - :max kilobytes.', + 'numeric' => 'El campo :attribute tiene que estar entre :min - :max.', + 'string' => 'El campo :attribute tiene que tener entre :min - :max caracteres.', + ], + 'boolean' => 'El campo :attribute debe tener un valor verdadero o falso.', + 'can' => 'El campo :attribute contiene un valor no autorizado.', + 'confirmed' => 'La confirmación de :attribute no coincide.', + 'contains' => 'Al campo :attribute le falta un valor obligatorio.', + 'current_password' => 'La contraseña es incorrecta.', + 'date' => 'El campo :attribute debe ser una fecha válida.', + 'date_equals' => 'El campo :attribute debe ser una fecha igual a :date.', + 'date_format' => 'El campo :attribute debe coincidir con el formato :format.', + 'decimal' => 'El campo :attribute debe tener :decimal cifras decimales.', + 'declined' => 'El campo :attribute debe ser rechazado.', + 'declined_if' => 'El campo :attribute debe ser rechazado cuando :other sea :value.', + 'different' => 'El campo :attribute y :other deben ser diferentes.', + 'digits' => 'El campo :attribute debe tener :digits dígitos.', + 'digits_between' => 'El campo :attribute debe tener entre :min y :max dígitos.', + 'dimensions' => 'El campo :attribute tiene dimensiones de imagen no válidas.', + 'distinct' => 'El campo :attribute contiene un valor duplicado.', + 'doesnt_end_with' => 'El campo :attribute no debe finalizar con uno de los siguientes: :values.', + 'doesnt_start_with' => 'El campo :attribute no debe comenzar con uno de los siguientes: :values.', + 'email' => 'El campo :attribute no es un correo válido.', + 'ends_with' => 'El campo :attribute debe finalizar con uno de los siguientes valores: :values', + 'enum' => 'El campo :attribute no está en la lista de valores permitidos.', + 'exists' => 'El campo :attribute no existe.', + 'extensions' => 'El campo :attribute debe tener una de las siguientes extensiones: :values.', + 'file' => 'El campo :attribute debe ser un archivo.', + 'filled' => 'El campo :attribute es obligatorio.', + 'gt' => [ + 'array' => 'El campo :attribute debe tener más de :value elementos.', + 'file' => 'El campo :attribute debe tener más de :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser mayor que :value.', + 'string' => 'El campo :attribute debe tener más de :value caracteres.', + ], + 'gte' => [ + 'array' => 'El campo :attribute debe tener como mínimo :value elementos.', + 'file' => 'El campo :attribute debe tener como mínimo :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser como mínimo :value.', + 'string' => 'El campo :attribute debe tener como mínimo :value caracteres.', + ], + 'hex_color' => 'El campo :attribute debe tener un color hexadecimal válido.', + 'image' => 'El campo :attribute debe ser una imagen.', + 'in' => 'El campo :attribute no está en la lista de valores permitidos.', + 'in_array' => 'El campo :attribute debe existir en :other.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => 'El campo :attribute debe ser un número entero.', + 'ip' => 'El campo :attribute debe ser una dirección IP válida.', + 'ipv4' => 'El campo :attribute debe ser una dirección IPv4 válida.', + 'ipv6' => 'El campo :attribute debe ser una dirección IPv6 válida.', + 'json' => 'El campo :attribute debe ser una cadena JSON válida.', + 'list' => 'El campo :attribute debe ser una lista.', + 'lowercase' => 'El campo :attribute debe estar en minúscula.', + 'lt' => [ + 'array' => 'El campo :attribute debe tener menos de :value elementos.', + 'file' => 'El campo :attribute debe tener menos de :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser menor que :value.', + 'string' => 'El campo :attribute debe tener menos de :value caracteres.', + ], + 'lte' => [ + 'array' => 'El campo :attribute debe tener como máximo :value elementos.', + 'file' => 'El campo :attribute debe tener como máximo :value kilobytes.', + 'numeric' => 'El campo :attribute debe ser como máximo :value.', + 'string' => 'El campo :attribute debe tener como máximo :value caracteres.', + ], + 'mac_address' => 'El campo :attribute debe ser una dirección MAC válida.', + 'max' => [ + 'array' => 'El campo :attribute no debe tener más de :max elementos.', + 'file' => 'El campo :attribute no debe ser mayor que :max kilobytes.', + 'numeric' => 'El campo :attribute no debe ser mayor que :max.', + 'string' => 'El campo :attribute no debe ser mayor que :max caracteres.', + ], + 'max_digits' => 'El campo :attribute no debe tener más de :max dígitos.', + 'mimes' => 'El campo :attribute debe ser un archivo con formato: :values.', + 'mimetypes' => 'El campo :attribute debe ser un archivo con formato: :values.', + 'min' => [ + 'array' => 'El campo :attribute debe tener al menos :min elementos.', + 'file' => 'El tamaño de :attribute debe ser de al menos :min kilobytes.', + 'numeric' => 'El tamaño de :attribute debe ser de al menos :min.', + 'string' => 'El campo :attribute debe contener al menos :min caracteres.', + ], + 'min_digits' => 'El campo :attribute debe tener al menos :min dígitos.', + 'missing' => 'El campo :attribute no debe estar presente.', + 'missing_if' => 'El campo :attribute no debe estar presente cuando :other sea :value.', + 'missing_unless' => 'El campo :attribute no debe estar presente a menos que :other sea :value.', + 'missing_with' => 'El campo :attribute no debe estar presente si alguno de los campos :values está presente.', + 'missing_with_all' => 'El campo :attribute no debe estar presente cuando los campos :values estén presentes.', + 'multiple_of' => 'El campo :attribute debe ser múltiplo de :value', + 'not_in' => 'El campo :attribute no debe estar en la lista.', + 'not_regex' => 'El formato del campo :attribute no es válido.', + 'numeric' => 'El campo :attribute debe ser numérico.', + 'password' => [ + 'letters' => 'La :attribute debe contener al menos una letra.', + 'mixed' => 'La :attribute debe contener al menos una letra mayúscula y una minúscula.', + 'numbers' => 'La :attribute debe contener al menos un número.', + 'symbols' => 'La :attribute debe contener al menos un símbolo.', + 'uncompromised' => 'La :attribute proporcionada se ha visto comprometida en una filtración de datos (data leak). Elija una :attribute diferente.', + ], + 'present' => 'El campo :attribute debe estar presente.', + 'present_if' => 'El campo :attribute debe estar presente cuando :other es :value.', + 'present_unless' => 'El campo :attribute debe estar presente a menos que :other sea :value.', + 'present_with' => 'El campo :attribute debe estar presente cuando :values esté presente.', + 'present_with_all' => 'El campo :attribute debe estar presente cuando :values estén presentes.', + 'prohibited' => 'El campo :attribute está prohibido.', + 'prohibited_if' => 'El campo :attribute está prohibido cuando :other es :value.', + 'prohibited_if_accepted' => 'El campo :attribute está prohibido cuando se acepta :other.', + 'prohibited_if_declined' => 'El campo :attribute está prohibido cuando se rechaza :other.', + 'prohibited_unless' => 'El campo :attribute está prohibido a menos que :other sea :values.', + 'prohibits' => 'El campo :attribute prohibe que :other esté presente.', + 'regex' => 'El formato del campo :attribute no es válido.', + 'required' => 'El campo :attribute es obligatorio.', + 'required_array_keys' => 'El campo :attribute debe contener entradas para: :values.', + 'required_if' => 'El campo :attribute es obligatorio cuando :other es :value.', + 'required_if_accepted' => 'El campo :attribute es obligatorio si :other es aceptado.', + 'required_if_declined' => 'El campo :attribute es obligatorio si :other es rechazado.', + 'required_unless' => 'El campo :attribute es obligatorio a menos que :other esté en :values.', + 'required_with' => 'El campo :attribute es obligatorio cuando :values está presente.', + 'required_with_all' => 'El campo :attribute es obligatorio cuando :values están presentes.', + 'required_without' => 'El campo :attribute es obligatorio cuando :values no está presente.', + 'required_without_all' => 'El campo :attribute es obligatorio cuando ninguno de :values está presente.', + 'same' => 'Los campos :attribute y :other deben coincidir.', + 'size' => [ + 'array' => 'El campo :attribute debe contener :size elementos.', + 'file' => 'El tamaño de :attribute debe ser :size kilobytes.', + 'numeric' => 'El tamaño de :attribute debe ser :size.', + 'string' => 'El campo :attribute debe contener :size caracteres.', + ], + 'starts_with' => 'El campo :attribute debe comenzar con uno de los siguientes valores: :values', + 'string' => 'El campo :attribute debe ser una cadena de caracteres.', + 'timezone' => 'El campo :attribute debe ser una zona horaria válida.', + 'ulid' => 'El campo :attribute debe ser un ULID válido.', + 'unique' => 'El campo :attribute ya ha sido registrado.', + 'uploaded' => 'Subir :attribute ha fallado.', + 'uppercase' => 'El campo :attribute debe estar en mayúscula.', + 'url' => 'El campo :attribute debe ser una URL válida.', + 'uuid' => 'El campo :attribute debe ser un UUID válido.', + 'attributes' => [ + 'address' => 'dirección', + 'affiliate_url' => 'URL de afiliado', + 'age' => 'edad', + 'amount' => 'cantidad', + 'announcement' => 'anuncio', + 'area' => 'área', + 'audience_prize' => 'premio del público', + 'audience_winner' => 'ganador del público', + 'available' => 'disponible', + 'birthday' => 'cumpleaños', + 'body' => 'contenido', + 'city' => 'ciudad', + 'company' => 'compañía', + 'compilation' => 'compilación', + 'concept' => 'concepto', + 'conditions' => 'condiciones', + 'content' => 'contenido', + 'contest' => 'concurso', + 'country' => 'país', + 'cover' => 'portada', + 'created_at' => 'creado el', + 'creator' => 'creador', + 'currency' => 'moneda', + 'current_password' => 'contraseña actual', + 'customer' => 'cliente', + 'date' => 'fecha', + 'date_of_birth' => 'fecha de nacimiento', + 'dates' => 'fechas', + 'day' => 'día', + 'deleted_at' => 'eliminado el', + 'description' => 'descripción', + 'display_type' => 'tipo de visualización', + 'district' => 'distrito', + 'duration' => 'duración', + 'email' => 'correo electrónico', + 'excerpt' => 'extracto', + 'filter' => 'filtro', + 'finished_at' => 'terminado el', + 'first_name' => 'nombre', + 'gender' => 'género', + 'grand_prize' => 'gran Premio', + 'group' => 'grupo', + 'hour' => 'hora', + 'image' => 'imagen', + 'image_desktop' => 'imagen de escritorio', + 'image_main' => 'imagen principal', + 'image_mobile' => 'imagen móvil', + 'images' => 'imágenes', + 'is_audience_winner' => 'es ganador de audiencia', + 'is_hidden' => 'está oculto', + 'is_subscribed' => 'está suscrito', + 'is_visible' => 'es visible', + 'is_winner' => 'es ganador', + 'items' => 'elementos', + 'key' => 'clave', + 'last_name' => 'apellidos', + 'lesson' => 'lección', + 'line_address_1' => 'línea de dirección 1', + 'line_address_2' => 'línea de dirección 2', + 'login' => 'acceso', + 'message' => 'mensaje', + 'middle_name' => 'segundo nombre', + 'minute' => 'minuto', + 'mobile' => 'móvil', + 'month' => 'mes', + 'name' => 'nombre', + 'national_code' => 'código nacional', + 'nickname' => 'apodo', + 'number' => 'número', + 'password' => 'contraseña', + 'password_confirmation' => 'confirmación de la contraseña', + 'phone' => 'teléfono', + 'photo' => 'foto', + 'portfolio' => 'portafolio', + 'postal_code' => 'código postal', + 'preview' => 'vista preliminar', + 'price' => 'precio', + 'product_id' => 'ID del producto', + 'product_uid' => 'UID del producto', + 'product_uuid' => 'UUID del producto', + 'promo_code' => 'código promocional', + 'province' => 'provincia', + 'quantity' => 'cantidad', + 'reason' => 'razón', + 'recaptcha_response_field' => 'respuesta del recaptcha', + 'referee' => 'árbitro', + 'referees' => 'árbitros', + 'reject_reason' => 'motivo de rechazo', + 'remember' => 'recordar', + 'restored_at' => 'restaurado el', + 'result_text_under_image' => 'texto bajo la imagen', + 'role' => 'rol', + 'rule' => 'regla', + 'rules' => 'reglas', + 'second' => 'segundo', + 'sex' => 'sexo', + 'shipment' => 'envío', + 'short_text' => 'texto corto', + 'size' => 'tamaño', + 'situation' => 'situación', + 'skills' => 'habilidades', + 'slug' => 'slug', + 'specialization' => 'especialización', + 'started_at' => 'comenzado el', + 'state' => 'estado', + 'status' => 'estado', + 'street' => 'calle', + 'student' => 'estudiante', + 'subject' => 'asunto', + 'tag' => 'etiqueta', + 'tags' => 'etiquetas', + 'teacher' => 'profesor', + 'terms' => 'términos', + 'test_description' => 'descripción de prueba', + 'test_locale' => 'idioma de prueba', + 'test_name' => 'nombre de prueba', + 'text' => 'texto', + 'time' => 'hora', + 'title' => 'título', + 'type' => 'tipo', + 'updated_at' => 'actualizado el', + 'user' => 'usuario', + 'username' => 'usuario', + 'value' => 'valor', + 'winner' => 'ganador', + 'work' => 'trabajo', + 'year' => 'año', + ], +]; diff --git a/lang/fr.json b/lang/fr.json new file mode 100644 index 00000000..c8db9f71 --- /dev/null +++ b/lang/fr.json @@ -0,0 +1,231 @@ +{ + "(and :count more error)": "(et :count erreur en plus)", + "(and :count more errors)": "(et :count erreur en plus)|(et :count erreurs en plus)|(et :count erreurs en plus)", + "A decryption key is required.": "A decryption key is required.", + "A reset link will be sent if the account exists.": "Un lien de réinitialisation sera envoyé si le compte existe.", + "A Timeout Occurred": "Temps d'attente dépassé", + "Accept": "Accepter", + "Accepted": "Accepté", + "Action": "Action", + "Actions": "Actions", + "Add": "Ajouter", + "Add :name": "Ajouter :name", + "Admin": "Administrateur", + "Agree": "Accepter", + "All rights reserved.": "Tous droits réservés.", + "Already Reported": "Déjà rapporté", + "Archive": "Archive", + "Assign": "Attribuer", + "Associate": "Associé", + "Attach": "Attacher", + "Bad Gateway": "Passerelle invalide", + "Bad Request": "Requête erronée", + "Bandwidth Limit Exceeded": "Limite de bande passante dépassée", + "Browse": "Parcourir", + "Cancel": "Annuler", + "Choose": "Choisir", + "Choose :name": "Choisir :name", + "Choose File": "Choisir le fichier", + "Choose Image": "Choisir une image", + "Click to copy": "Cliquer pour copier", + "Client Closed Request": "Demande fermée par le client", + "Close": "Fermer", + "Collapse": "Réduire", + "Collapse All": "Réduire tout", + "Comment": "Commentaire", + "Confirm": "Confirmer", + "Conflict": "Conflit", + "Connect": "Connecter", + "Connection Closed Without Response": "Connexion fermée sans réponse", + "Connection Timed Out": "La connexion a expiré", + "Continue": "Continuer", + "Create": "Créer", + "Create :name": "Créer :name", + "Created": "Créé", + "Delete": "Supprimer", + "Delete :name": "Supprimer :name", + "Detach": "Détacher", + "Details": "Détails", + "Disable": "Désactiver", + "Discard": "Jeter", + "Done": "Fait", + "Down": "Descendre", + "Duplicate": "Dupliquer", + "Duplicate :name": "Dupliquer :name", + "Edit": "Éditer", + "Edit :name": "Modifier :name", + "Enable": "Activer", + "Encrypted environment file already exists.": "Encrypted environment file already exists.", + "Encrypted environment file not found.": "Encrypted environment file not found.", + "Environment file already exists.": "Environment file already exists.", + "Environment file not found.": "Environment file not found.", + "errors": "les erreurs", + "Expand": "Développer", + "Expand All": "Développer tout", + "Expectation Failed": "Comportement attendu insatisfaisant", + "Explanation": "Explication", + "Export": "Exporter", + "Export :name": "Exporter :name", + "Failed Dependency": "Dépendance échouée", + "File": "Déposer", + "Files": "Des dossiers", + "Forbidden": "Interdit", + "Found": "Trouvé", + "Gateway Timeout": "Temps d'attente de la passerelle dépassé", + "Go Home": "Aller à l'accueil", + "Go to page :page": "Aller à la page :page", + "Gone": "Disparu", + "Hello!": "Bonjour !", + "Hide": "Cacher", + "Hide :name": "Cacher :name", + "Home": "Accueil", + "HTTP Version Not Supported": "Version HTTP non prise en charge", + "I'm a teapot": "Je suis une théière", + "If you did not create an account, no further action is required.": "Si vous n'avez pas créé de compte, vous pouvez ignorer ce message.", + "If you did not request a password reset, no further action is required.": "Si vous n'avez pas demandé de réinitialisation de mot de passe, vous pouvez ignorer ce message.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Si vous avez des difficultés à cliquer sur le bouton \":actionText\", copiez et collez l'URL ci-dessous\ndans votre navigateur Web :", + "IM Used": "IM utilisé", + "Image": "Image", + "Impersonate": "Utiliser un autre compte", + "Impersonation": "Imitation", + "Import": "Importer", + "Import :name": "Importer :name", + "Insufficient Storage": "Espace insuffisant", + "Internal Server Error": "Erreur interne du serveur", + "Introduction": "Introduction", + "Invalid filename.": "Invalid filename.", + "Invalid JSON was returned from the route.": "Un JSON non valide a été renvoyé par la route.", + "Invalid SSL Certificate": "Certificat SSL invalide", + "length": "length", + "Length Required": "Longueur requise", + "Like": "Aimer", + "Load": "Charger", + "Localize": "Localiser", + "Location": "Emplacement", + "Locked": "Verrouillé", + "Log In": "Se connecter", + "Log Out": "Se déconnecter", + "Login": "Connexion", + "Logout": "Déconnexion", + "Loop Detected": "Boucle détectée", + "Maintenance Mode": "Mode de maintenance", + "Method Not Allowed": "Méthode non autorisée", + "Misdirected Request": "Demande mal dirigée", + "Moved Permanently": "Déplacé de façon permanente", + "Multi-Status": "Statut multiple", + "Multiple Choices": "Choix multiples", + "Network Authentication Required": "Authentification réseau requise", + "Network Connect Timeout Error": "Temps d'attente de la connexion réseau dépassé", + "Network Read Timeout Error": "Temps d'attente de la lecture réseau dépassé", + "New": "Nouveau", + "New :name": "Nouveau :name", + "No": "Non", + "No Content": "Pas de contenu", + "Non-Authoritative Information": "Informations non certifiées", + "Not Acceptable": "Pas acceptable", + "Not Extended": "Non prolongé", + "Not Found": "Non trouvé", + "Not Implemented": "Non implémenté", + "Not Modified": "Non modifié", + "of": "de", + "OK": "OK", + "Open": "Ouvrir", + "Open in a current window": "Ouvrir dans une fenêtre actuelle", + "Open in a new window": "Ouvrir dans une nouvelle fenêtre", + "Open in a parent frame": "Ouvrir dans un cadre parent", + "Open in the topmost frame": "Ouvrir dans le cadre le plus haut", + "Open on the website": "Ouvrir sur le site", + "Origin Is Unreachable": "L'origine est inaccessible", + "Page Expired": "Page expirée", + "Pagination Navigation": "Pagination", + "Partial Content": "Contenu partiel", + "Payload Too Large": "Charge utile trop grande", + "Payment Required": "Paiement requis", + "Permanent Redirect": "Redirection permanente", + "Please click the button below to verify your email address.": "Veuillez cliquer sur le bouton ci-dessous pour vérifier votre adresse e-mail :", + "Precondition Failed": "La précondition a échoué", + "Precondition Required": "Condition préalable requise", + "Preview": "Aperçu", + "Price": "Prix", + "Processing": "En traitement", + "Proxy Authentication Required": "Authentification proxy requise", + "Railgun Error": "Erreur de Railgun", + "Range Not Satisfiable": "Plage non satisfaisante", + "Record": "Enregistrer", + "Regards,": "Cordialement,", + "Register": "Inscription", + "Request Header Fields Too Large": "Champs d'en-tête de requête trop grands", + "Request Timeout": "Temps d'attente de la requête dépassé", + "Reset Content": "Réinitialiser le contenu", + "Reset Password": "Réinitialisation du mot de passe", + "Reset Password Notification": "Notification de réinitialisation du mot de passe", + "Restore": "Restaurer", + "Restore :name": "Restaurer :name", + "results": "résultats", + "Retry With": "Réessayer avec", + "Save": "Sauvegarder", + "Save & Close": "Sauvegarder et fermer", + "Save & Return": "Sauvegarder et retourner", + "Save :name": "Sauvegarder :name", + "Search": "Rechercher", + "Search :name": "Chercher :name", + "See Other": "Voir autre", + "Select": "Sélectionner", + "Select All": "Tout sélectionner", + "Send": "Envoyer", + "Server Error": "Erreur serveur", + "Service Unavailable": "Service indisponible", + "Session Has Expired": "La session a expiré", + "Settings": "Paramètres", + "Show": "Afficher", + "Show :name": "Afficher :name", + "Show All": "Afficher tout", + "Showing": "Montrant", + "Sign In": "Se connecter", + "Solve": "Résoudre", + "SSL Handshake Failed": "Échec de la prise de contact SSL", + "Start": "Commencer", + "status": "statut", + "Stop": "Arrêter", + "Submit": "Soumettre", + "Subscribe": "S'abonner", + "Switch": "Changer", + "Switch To Role": "Passer au rôle", + "Switching Protocols": "Protocoles de commutation", + "Tag": "Mot clé", + "Tags": "Mots clés", + "Temporary Redirect": "Redirection temporaire", + "The given data was invalid.": "La donnée renseignée est incorrecte.", + "The response is not a streamed response.": "La réponse n'est pas une réponse diffusée.", + "The response is not a view.": "La réponse n'est pas une vue.", + "This action is unauthorized.": "Cette action n'est pas autorisée.", + "This password reset link will expire in :count minutes.": "Ce lien de réinitialisation du mot de passe expirera dans :count minutes.", + "to": "à", + "Toggle navigation": "Afficher / masquer le menu de navigation", + "Too Early": "Trop tôt", + "Too Many Requests": "Trop de requêtes", + "Translate": "Traduire", + "Translate It": "Traduis le", + "Unauthorized": "Non autorisé", + "Unavailable For Legal Reasons": "Indisponible pour des raisons légales", + "Unknown Error": "Erreur inconnue", + "Unpack": "Déballer", + "Unprocessable Entity": "Entité non traitable", + "Unsubscribe": "Se désabonner", + "Unsupported Media Type": "Type de média non supporté", + "Up": "Monter", + "Update": "Mettre à jour", + "Update :name": "Mettre à jour :name", + "Upgrade Required": "Mise à niveau requise", + "URI Too Long": "URI trop long", + "Use Proxy": "Utiliser un proxy", + "User": "Utilisateur", + "Variant Also Negotiates": "La variante négocie également", + "Verify Email Address": "Vérifier l'adresse e-mail", + "View": "Vue", + "View :name": "Voir :name", + "Web Server is Down": "Le serveur Web est en panne", + "Whoops!": "Oups !", + "Yes": "Oui", + "You are receiving this email because we received a password reset request for your account.": "Vous recevez cet e-mail car nous avons reçu une demande de réinitialisation de mot de passe pour votre compte." +} \ No newline at end of file diff --git a/lang/fr/actions.php b/lang/fr/actions.php new file mode 100644 index 00000000..b853eed5 --- /dev/null +++ b/lang/fr/actions.php @@ -0,0 +1,119 @@ + 'Accepter', + 'action' => 'Action', + 'actions' => 'Actions', + 'add' => 'Ajouter', + 'admin' => 'Administrateur', + 'agree' => 'Approuver', + 'archive' => 'Archiver', + 'assign' => 'Attribuer', + 'associate' => 'Associer', + 'attach' => 'Attacher', + 'browse' => 'Parcourir', + 'cancel' => 'Annuler', + 'choose' => 'Choisir', + 'choose_file' => 'Choisir le fichier', + 'choose_image' => 'Choisir une image', + 'click_to_copy' => 'Cliquer pour copier', + 'close' => 'Fermer', + 'collapse' => 'Réduire', + 'collapse_all' => 'Réduire tout', + 'comment' => 'Commentaire', + 'confirm' => 'Confirmer', + 'connect' => 'Connecter', + 'create' => 'Créer', + 'delete' => 'Supprimer', + 'detach' => 'Détacher', + 'details' => 'Détails', + 'disable' => 'Désactiver', + 'discard' => 'Jeter', + 'done' => 'Fait', + 'down' => 'Descendre', + 'duplicate' => 'Dupliquer', + 'edit' => 'Editer', + 'enable' => 'Activer', + 'expand' => 'Développer', + 'expand_all' => 'Développer tout', + 'explanation' => 'Explication', + 'export' => 'Exporter', + 'file' => 'Déposer', + 'files' => 'Fichiers', + 'go_home' => 'Aller à l\'accueil', + 'hide' => 'Cacher', + 'home' => 'Accueil', + 'image' => 'Image', + 'impersonate' => 'Imiter', + 'impersonation' => 'Imitation', + 'import' => 'Importer', + 'introduction' => 'Introduction', + 'like' => 'Aimer', + 'load' => 'Charger', + 'localize' => 'Localiser', + 'log_in' => 'Se connecter', + 'log_out' => 'Se déconnecter', + 'named' => [ + 'add' => 'Ajouter :name', + 'choose' => 'Choisir :name', + 'create' => 'Créer :name', + 'delete' => 'Supprimer :name', + 'duplicate' => 'Dupliquer :name', + 'edit' => 'Editer :name', + 'export' => 'Exporter :name', + 'hide' => 'Cacher :name', + 'import' => 'Importer :name', + 'new' => 'Nouveau :name', + 'restore' => 'Restaurer :name', + 'save' => 'Sauvegarder :name', + 'search' => 'Chercher :name', + 'show' => 'Afficher :name', + 'update' => 'Mettre à jour :name', + 'view' => 'Voir :name', + ], + 'new' => 'Nouveau', + 'no' => 'Non', + 'open' => 'Ouvrir', + 'open_website' => 'Ouvrir sur le site', + 'preview' => 'Aperçu', + 'price' => 'Prix', + 'record' => 'Enregistrer', + 'restore' => 'Restaurer', + 'save' => 'Sauvegarder', + 'save_and_close' => 'Sauvegarder et fermer', + 'save_and_return' => 'Sauvegarder et retourner', + 'search' => 'Chercher', + 'select' => 'Sélectionner', + 'select_all' => 'Tout sélectionner', + 'send' => 'Envoyer', + 'settings' => 'Paramètres', + 'show' => 'Montrer', + 'show_all' => 'Afficher tout', + 'sign_in' => 'Se connecter', + 'solve' => 'Résoudre', + 'start' => 'Commencer', + 'stop' => 'Arrêter', + 'submit' => 'Soumettre', + 'subscribe' => 'S\'abonner', + 'switch' => 'Changer', + 'switch_to_role' => 'Passer au rôle', + 'tag' => 'Mot clé', + 'tags' => 'Mots clés', + 'target_link' => [ + 'blank' => 'Ouvrir dans une nouvelle fenêtre', + 'parent' => 'Ouvrir dans la fenêtre parente', + 'self' => 'Ouvrir dans la fenêtre actuelle', + 'top' => 'Ouvrir dans le cadre le plus haut', + ], + 'translate' => 'Traduire', + 'translate_it' => 'Traduis le', + 'unpack' => 'Déballer', + 'unsubscribe' => 'Se désabonner', + 'up' => 'Monter', + 'update' => 'Mettre à jour', + 'user' => 'Utilisateur', + 'view' => 'Voir', + 'yes' => 'Oui', +]; diff --git a/lang/fr/auth.php b/lang/fr/auth.php new file mode 100644 index 00000000..a22cd3f7 --- /dev/null +++ b/lang/fr/auth.php @@ -0,0 +1,9 @@ + 'Ces identifiants ne correspondent pas à nos enregistrements.', + 'password' => 'Le mot de passe est incorrect', + 'throttle' => 'Tentatives de connexion trop nombreuses. Veuillez essayer de nouveau dans :seconds secondes.', +]; diff --git a/lang/fr/http-statuses.php b/lang/fr/http-statuses.php new file mode 100644 index 00000000..77a499cc --- /dev/null +++ b/lang/fr/http-statuses.php @@ -0,0 +1,84 @@ + 'Erreur inconnue', + '100' => 'Continuer', + '101' => 'Protocoles de commutation', + '102' => 'En traitement', + '200' => 'OK', + '201' => 'Créé', + '202' => 'Accepté', + '203' => 'Informations non certifiées', + '204' => 'Pas de contenu', + '205' => 'Réinitialiser le contenu', + '206' => 'Contenu partiel', + '207' => 'Statut multiple', + '208' => 'Déjà rapporté', + '226' => 'IM utilisé', + '300' => 'Choix multiples', + '301' => 'Déplacé de façon permanente', + '302' => 'A trouvé', + '303' => 'Voir autre', + '304' => 'Non modifié', + '305' => 'Utiliser un proxy', + '307' => 'Redirection temporaire', + '308' => 'Redirection permanente', + '400' => 'Requête invalide', + '401' => 'Non authentifié', + '402' => 'Paiement requis', + '403' => 'Interdit', + '404' => 'Page non trouvée', + '405' => 'Méthode non autorisée', + '406' => 'Non acceptable', + '407' => 'Authentification proxy requise', + '408' => 'Requête expirée', + '409' => 'Conflit', + '410' => 'Disparu', + '411' => 'Longueur requise', + '412' => 'La précondition a échoué', + '413' => 'Charge utile trop grande', + '414' => 'URI trop long', + '415' => 'Type de média non supporté', + '416' => 'Plage non satisfaisante', + '417' => 'Comportement attendu insatisfaisant', + '418' => 'Je suis une théière', + '419' => 'La session a expiré', + '421' => 'Demande mal dirigée', + '422' => 'Contenu non traitable', + '423' => 'Verrouillé', + '424' => 'Dépendance échouée', + '425' => 'Trop tôt', + '426' => 'Mise à niveau requise', + '428' => 'Condition préalable requise', + '429' => 'Trop de demandes', + '431' => 'Champs d\'en-tête de requête trop grands', + '444' => 'Connexion fermée sans réponse', + '449' => 'Réessayer avec', + '451' => 'Indisponible pour des raisons légales', + '499' => 'Demande fermée par le client', + '500' => 'Erreur interne dus erveur', + '501' => 'Non implémenté', + '502' => 'Mauvaise passerelle', + '503' => 'Service non disponible', + '504' => 'Temps d\'attente de la passerelle dépassé', + '505' => 'Version HTTP non prise en charge', + '506' => 'La variante négocie également', + '507' => 'Espace insuffisant', + '508' => 'Boucle détectée', + '509' => 'Limite de bande passante dépassée', + '510' => 'Non prolongé', + '511' => 'Authentification réseau requise', + '520' => 'Erreur inconnue', + '521' => 'Le serveur Web est en panne', + '522' => 'La connexion a expiré', + '523' => 'L\'origine est inaccessible', + '524' => 'Un dépassement de délai s\'est produit', + '525' => 'Échec de la prise de contact SSL', + '526' => 'Certificat SSL invalide', + '527' => 'Erreur de Railgun', + '598' => 'Temps d\'attente de la lecture réseau dépassé', + '599' => 'Temps d\'attente de la connexion réseau dépassé', + 'unknownError' => 'Erreur inconnue', +]; diff --git a/lang/fr/pagination.php b/lang/fr/pagination.php new file mode 100644 index 00000000..225391eb --- /dev/null +++ b/lang/fr/pagination.php @@ -0,0 +1,8 @@ + 'Suivant »', + 'previous' => '« Précédent', +]; diff --git a/lang/fr/passwords.php b/lang/fr/passwords.php new file mode 100644 index 00000000..75ae1485 --- /dev/null +++ b/lang/fr/passwords.php @@ -0,0 +1,11 @@ + 'Votre mot de passe a été réinitialisé !', + 'sent' => 'Nous vous avons envoyé par email le lien de réinitialisation du mot de passe !', + 'throttled' => 'Veuillez patienter avant de réessayer.', + 'token' => 'Ce jeton de réinitialisation du mot de passe n\'est pas valide.', + 'user' => 'Aucun utilisateur n\'a été trouvé avec cette adresse email.', +]; diff --git a/lang/fr/validation.php b/lang/fr/validation.php new file mode 100644 index 00000000..41d10978 --- /dev/null +++ b/lang/fr/validation.php @@ -0,0 +1,286 @@ + 'Le champ :attribute doit être accepté.', + 'accepted_if' => 'Le champ :attribute doit être accepté quand :other a la valeur :value.', + 'active_url' => 'Le champ :attribute n\'est pas une URL valide.', + 'after' => 'Le champ :attribute doit être une date postérieure au :date.', + 'after_or_equal' => 'Le champ :attribute doit être une date postérieure ou égale au :date.', + 'alpha' => 'Le champ :attribute doit contenir uniquement des lettres.', + 'alpha_dash' => 'Le champ :attribute doit contenir uniquement des lettres, des chiffres et des tirets.', + 'alpha_num' => 'Le champ :attribute doit contenir uniquement des chiffres et des lettres.', + 'any_of' => 'The :attribute field is invalid.', + 'array' => 'Le champ :attribute doit être un tableau.', + 'ascii' => 'Le champ :attribute ne doit contenir que des caractères alphanumériques et des symboles codés sur un octet.', + 'before' => 'Le champ :attribute doit être une date antérieure au :date.', + 'before_or_equal' => 'Le champ :attribute doit être une date antérieure ou égale au :date.', + 'between' => [ + 'array' => 'Le tableau :attribute doit contenir entre :min et :max éléments.', + 'file' => 'La taille du fichier de :attribute doit être comprise entre :min et :max kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être comprise entre :min et :max.', + 'string' => 'Le texte :attribute doit contenir entre :min et :max caractères.', + ], + 'boolean' => 'Le champ :attribute doit être vrai ou faux.', + 'can' => 'Le champ :attribute contient une valeur non autorisée.', + 'confirmed' => 'Le champ de confirmation :attribute ne correspond pas.', + 'contains' => 'Le champ :attribute manque une valeur requise.', + 'current_password' => 'Le mot de passe est incorrect.', + 'date' => 'Le champ :attribute n\'est pas une date valide.', + 'date_equals' => 'Le champ :attribute doit être une date égale à :date.', + 'date_format' => 'Le champ :attribute ne correspond pas au format :format.', + 'decimal' => 'Le champ :attribute doit comporter :decimal décimales.', + 'declined' => 'Le champ :attribute doit être décliné.', + 'declined_if' => 'Le champ :attribute doit être décliné quand :other a la valeur :value.', + 'different' => 'Les champs :attribute et :other doivent être différents.', + 'digits' => 'Le champ :attribute doit contenir :digits chiffres.', + 'digits_between' => 'Le champ :attribute doit contenir entre :min et :max chiffres.', + 'dimensions' => 'La taille de l\'image :attribute n\'est pas conforme.', + 'distinct' => 'Le champ :attribute a une valeur en double.', + 'doesnt_end_with' => 'Le champ :attribute ne doit pas finir avec une des valeurs suivantes : :values.', + 'doesnt_start_with' => 'Le champ :attribute ne doit pas commencer avec une des valeurs suivantes : :values.', + 'email' => 'Le champ :attribute doit être une adresse e-mail valide.', + 'ends_with' => 'Le champ :attribute doit se terminer par une des valeurs suivantes : :values', + 'enum' => 'Le champ :attribute sélectionné est invalide.', + 'exists' => 'Le champ :attribute sélectionné est invalide.', + 'extensions' => 'Le champ :attribute doit avoir l\'une des extensions suivantes : :values.', + 'file' => 'Le champ :attribute doit être un fichier.', + 'filled' => 'Le champ :attribute doit avoir une valeur.', + 'gt' => [ + 'array' => 'Le tableau :attribute doit contenir plus de :value éléments.', + 'file' => 'La taille du fichier de :attribute doit être supérieure à :value kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être supérieure à :value.', + 'string' => 'Le texte :attribute doit contenir plus de :value caractères.', + ], + 'gte' => [ + 'array' => 'Le tableau :attribute doit contenir au moins :value éléments.', + 'file' => 'La taille du fichier de :attribute doit être supérieure ou égale à :value kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être supérieure ou égale à :value.', + 'string' => 'Le texte :attribute doit contenir au moins :value caractères.', + ], + 'hex_color' => 'Le champ :attribute doit être une couleur hexadécimale valide.', + 'image' => 'Le champ :attribute doit être une image.', + 'in' => 'Le champ :attribute est invalide.', + 'in_array' => 'Le champ :attribute n\'existe pas dans :other.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => 'Le champ :attribute doit être un entier.', + 'ip' => 'Le champ :attribute doit être une adresse IP valide.', + 'ipv4' => 'Le champ :attribute doit être une adresse IPv4 valide.', + 'ipv6' => 'Le champ :attribute doit être une adresse IPv6 valide.', + 'json' => 'Le champ :attribute doit être un document JSON valide.', + 'list' => 'Le champ :attribute doit être une liste.', + 'lowercase' => 'Le champ :attribute doit être en minuscules.', + 'lt' => [ + 'array' => 'Le tableau :attribute doit contenir moins de :value éléments.', + 'file' => 'La taille du fichier de :attribute doit être inférieure à :value kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être inférieure à :value.', + 'string' => 'Le texte :attribute doit contenir moins de :value caractères.', + ], + 'lte' => [ + 'array' => 'Le tableau :attribute doit contenir au plus :value éléments.', + 'file' => 'La taille du fichier de :attribute doit être inférieure ou égale à :value kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être inférieure ou égale à :value.', + 'string' => 'Le texte :attribute doit contenir au plus :value caractères.', + ], + 'mac_address' => 'Le champ :attribute doit être une adresse MAC valide.', + 'max' => [ + 'array' => 'Le tableau :attribute ne peut pas contenir plus que :max éléments.', + 'file' => 'La taille du fichier de :attribute ne peut pas dépasser :max kilo-octets.', + 'numeric' => 'La valeur de :attribute ne peut pas être supérieure à :max.', + 'string' => 'Le texte de :attribute ne peut pas contenir plus de :max caractères.', + ], + 'max_digits' => 'Le champ :attribute ne doit pas avoir plus de :max chiffres.', + 'mimes' => 'Le champ :attribute doit être un fichier de type : :values.', + 'mimetypes' => 'Le champ :attribute doit être un fichier de type : :values.', + 'min' => [ + 'array' => 'Le tableau :attribute doit contenir au moins :min éléments.', + 'file' => 'La taille du fichier de :attribute doit être supérieure ou égale à :min kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être supérieure ou égale à :min.', + 'string' => 'Le texte de :attribute doit contenir au moins :min caractères.', + ], + 'min_digits' => 'Le champ :attribute doit avoir au moins :min chiffres.', + 'missing' => 'Le champ :attribute doit être manquant.', + 'missing_if' => 'Le champ :attribute doit être manquant quand :other a la valeur :value.', + 'missing_unless' => 'Le champ :attribute doit être manquant sauf si :other a la valeur :value.', + 'missing_with' => 'Le champ :attribute doit être manquant quand :values est présent.', + 'missing_with_all' => 'Le champ :attribute doit être manquant quand :values sont présents.', + 'multiple_of' => 'La valeur de :attribute doit être un multiple de :value', + 'not_in' => 'Le champ :attribute sélectionné n\'est pas valide.', + 'not_regex' => 'Le format du champ :attribute n\'est pas valide.', + 'numeric' => 'Le champ :attribute doit contenir un nombre.', + 'password' => [ + 'letters' => 'Le champ :attribute doit contenir au moins une lettre.', + 'mixed' => 'Le champ :attribute doit contenir au moins une majuscule et une minuscule.', + 'numbers' => 'Le champ :attribute doit contenir au moins un chiffre.', + 'symbols' => 'Le champ :attribute doit contenir au moins un symbole.', + 'uncompromised' => 'La valeur du champ :attribute est apparue dans une fuite de données. Veuillez choisir une valeur différente.', + ], + 'present' => 'Le champ :attribute doit être présent.', + 'present_if' => 'Le champ :attribute doit être présent lorsque :other est :value.', + 'present_unless' => 'Le champ :attribute doit être présent sauf si :other vaut :value.', + 'present_with' => 'Le champ :attribute doit être présent lorsque :values est présent.', + 'present_with_all' => 'Le champ :attribute doit être présent lorsque :values sont présents.', + 'prohibited' => 'Le champ :attribute est interdit.', + 'prohibited_if' => 'Le champ :attribute est interdit quand :other a la valeur :value.', + 'prohibited_if_accepted' => 'Le champ :attribute est interdit quand :other a été accepté.', + 'prohibited_if_declined' => 'Le champ :attribute est interdit quand :other a été refusé.', + 'prohibited_unless' => 'Le champ :attribute est interdit à moins que :other est l\'une des valeurs :values.', + 'prohibits' => 'Le champ :attribute interdit :other d\'être présent.', + 'regex' => 'Le format du champ :attribute est invalide.', + 'required' => 'Le champ :attribute est obligatoire.', + 'required_array_keys' => 'Le champ :attribute doit contenir des entrées pour : :values.', + 'required_if' => 'Le champ :attribute est obligatoire quand la valeur de :other est :value.', + 'required_if_accepted' => 'Le champ :attribute est obligatoire quand le champ :other a été accepté.', + 'required_if_declined' => 'Le champ :attribute est obligatoire quand le champ :other a été refusé.', + 'required_unless' => 'Le champ :attribute est obligatoire sauf si :other est :values.', + 'required_with' => 'Le champ :attribute est obligatoire quand :values est présent.', + 'required_with_all' => 'Le champ :attribute est obligatoire quand :values sont présents.', + 'required_without' => 'Le champ :attribute est obligatoire quand :values n\'est pas présent.', + 'required_without_all' => 'Le champ :attribute est requis quand aucun de :values n\'est présent.', + 'same' => 'Les champs :attribute et :other doivent être identiques.', + 'size' => [ + 'array' => 'Le tableau :attribute doit contenir :size éléments.', + 'file' => 'La taille du fichier de :attribute doit être de :size kilo-octets.', + 'numeric' => 'La valeur de :attribute doit être :size.', + 'string' => 'Le texte de :attribute doit contenir :size caractères.', + ], + 'starts_with' => 'Le champ :attribute doit commencer avec une des valeurs suivantes : :values', + 'string' => 'Le champ :attribute doit être une chaîne de caractères.', + 'timezone' => 'Le champ :attribute doit être un fuseau horaire valide.', + 'ulid' => 'Le champ :attribute doit être un ULID valide.', + 'unique' => 'La valeur du champ :attribute est déjà utilisée.', + 'uploaded' => 'Le fichier du champ :attribute n\'a pu être téléversé.', + 'uppercase' => 'Le champ :attribute doit être en majuscules.', + 'url' => 'Le format de l\'URL de :attribute n\'est pas valide.', + 'uuid' => 'Le champ :attribute doit être un UUID valide', + 'attributes' => [ + 'address' => 'adresse', + 'affiliate_url' => 'URL d\'affiliation', + 'age' => 'âge', + 'amount' => 'montant', + 'announcement' => 'annonce', + 'area' => 'zone', + 'audience_prize' => 'prix du public', + 'audience_winner' => 'audience winner', + 'available' => 'disponible', + 'birthday' => 'anniversaire', + 'body' => 'corps', + 'city' => 'ville', + 'company' => 'company', + 'compilation' => 'compilation', + 'concept' => 'concept', + 'conditions' => 'conditions', + 'content' => 'contenu', + 'contest' => 'contest', + 'country' => 'pays', + 'cover' => 'couverture', + 'created_at' => 'date de création', + 'creator' => 'créateur', + 'currency' => 'devise', + 'current_password' => 'mot de passe actuel', + 'customer' => 'client', + 'date' => 'date', + 'date_of_birth' => 'date de naissance', + 'dates' => 'rendez-vous', + 'day' => 'jour', + 'deleted_at' => 'date de suppression', + 'description' => 'description', + 'display_type' => 'type d\'affichage', + 'district' => 'quartier', + 'duration' => 'durée', + 'email' => 'adresse e-mail', + 'excerpt' => 'extrait', + 'filter' => 'filtre', + 'finished_at' => 'date de fin', + 'first_name' => 'prénom', + 'gender' => 'genre', + 'grand_prize' => 'grand prix', + 'group' => 'groupe', + 'hour' => 'heure', + 'image' => 'image', + 'image_desktop' => 'image de bureau', + 'image_main' => 'image principale', + 'image_mobile' => 'image mobile', + 'images' => 'images', + 'is_audience_winner' => 'est le gagnant du public', + 'is_hidden' => 'est caché', + 'is_subscribed' => 'est abonné', + 'is_visible' => 'est visible', + 'is_winner' => 'est gagnant', + 'items' => 'articles', + 'key' => 'clé', + 'last_name' => 'nom de famille', + 'lesson' => 'leçon', + 'line_address_1' => 'ligne d\'adresse 1', + 'line_address_2' => 'ligne d\'adresse 2', + 'login' => 'identifiant', + 'message' => 'message', + 'middle_name' => 'deuxième prénom', + 'minute' => 'minute', + 'mobile' => 'portable', + 'month' => 'mois', + 'name' => 'nom', + 'national_code' => 'code national', + 'nickname' => 'surnom', + 'number' => 'numéro', + 'password' => 'mot de passe', + 'password_confirmation' => 'confirmation du mot de passe', + 'phone' => 'téléphone', + 'photo' => 'photo', + 'portfolio' => 'portefeuille', + 'postal_code' => 'code postal', + 'preview' => 'aperçu', + 'price' => 'prix', + 'product_id' => 'identifiant du produit', + 'product_uid' => 'UID du produit', + 'product_uuid' => 'UUID du produit', + 'promo_code' => 'code promo', + 'province' => 'région', + 'quantity' => 'quantité', + 'reason' => 'raison', + 'recaptcha_response_field' => 'champ de réponse reCAPTCHA', + 'referee' => 'arbitre', + 'referees' => 'arbitres', + 'reject_reason' => 'motif de rejet', + 'remember' => 'se souvenir', + 'restored_at' => 'date de restauration', + 'result_text_under_image' => 'texte de résultat sous l\'image', + 'role' => 'rôle', + 'rule' => 'règle', + 'rules' => 'règles', + 'second' => 'seconde', + 'sex' => 'sexe', + 'shipment' => 'expédition', + 'short_text' => 'texte court', + 'size' => 'taille', + 'situation' => 'situation', + 'skills' => 'compétences', + 'slug' => 'slug', + 'specialization' => 'spécialisation', + 'started_at' => 'date de début', + 'state' => 'état', + 'status' => 'statut', + 'street' => 'rue', + 'student' => 'étudiant', + 'subject' => 'sujet', + 'tag' => 'mot clé', + 'tags' => 'mots clés', + 'teacher' => 'professeur', + 'terms' => 'conditions', + 'test_description' => 'description du test', + 'test_locale' => 'localisation du test', + 'test_name' => 'nom du test', + 'text' => 'texte', + 'time' => 'heure', + 'title' => 'titre', + 'type' => 'type', + 'updated_at' => 'date de mise à jour', + 'user' => 'utilisateur', + 'username' => 'nom d\'utilisateur', + 'value' => 'valeur', + 'winner' => 'winner', + 'work' => 'work', + 'year' => 'année', + ], +]; diff --git a/lang/it.json b/lang/it.json new file mode 100644 index 00000000..1cb1fce8 --- /dev/null +++ b/lang/it.json @@ -0,0 +1,231 @@ +{ + "(and :count more error)": "(e :count altro errore)", + "(and :count more errors)": "(e :count altro errore)|(e :count altri errori)|(e :count altri errori)", + "A decryption key is required.": "Una chiave di decrittazione è richiesta.", + "A reset link will be sent if the account exists.": "Se l'account esiste, verrà inviato un link per il reset.", + "A Timeout Occurred": "Un timeout è avvenuto", + "Accept": "Accettare", + "Accepted": "Accettato", + "Action": "Azione", + "Actions": "Azioni", + "Add": "Aggiungi", + "Add :name": "Aggiungi :name", + "Admin": "Ammin", + "Agree": "Essere d'accordo", + "All rights reserved.": "Tutti i diritti riservati", + "Already Reported": "Già riportato", + "Archive": "Archivio", + "Assign": "Assegnare", + "Associate": "Associare", + "Attach": "Collegare", + "Bad Gateway": "Gateway cattivo", + "Bad Request": "Cattiva richiesta", + "Bandwidth Limit Exceeded": "Limita di banda superato", + "Browse": "Naviga", + "Cancel": "Annulla", + "Choose": "Seleziona", + "Choose :name": "Scegli :name", + "Choose File": "Scegli un file", + "Choose Image": "Scegli Immagine", + "Click to copy": "Fare clic per copiare", + "Client Closed Request": "Richiesta chiusa del cliente", + "Close": "Chiudi", + "Collapse": "Comprimi", + "Collapse All": "Comprimi tutto", + "Comment": "Commenta", + "Confirm": "Conferma", + "Conflict": "Conflitto", + "Connect": "Collega", + "Connection Closed Without Response": "Connessione chiusa senza risposta", + "Connection Timed Out": "Tempo scaduto per la connessione", + "Continue": "Continua", + "Create": "Crea", + "Create :name": "Crea :name", + "Created": "Creato", + "Delete": "Elimina", + "Delete :name": "Cancella :name", + "Detach": "Scollega", + "Details": "Dettagli", + "Disable": "Disabilita", + "Discard": "Scarta", + "Done": "Fatto", + "Down": "Giù", + "Duplicate": "Duplica", + "Duplicate :name": "Duplica: nome", + "Edit": "Modifica", + "Edit :name": "Modifica :name", + "Enable": "Abilita", + "Encrypted environment file already exists.": "Il file di ambiente criptato esiste già.", + "Encrypted environment file not found.": "Non è stato trovato il file di ambiente criptato.", + "Environment file already exists.": "Il file di ambiente esiste già.", + "Environment file not found.": "File di ambiente non trovato.", + "errors": "errori", + "Expand": "Espandi", + "Expand All": "Espandi tutto", + "Expectation Failed": "Aspettativa fallita", + "Explanation": "Spiegazione", + "Export": "Esporta", + "Export :name": "Esporta :name", + "Failed Dependency": "Dipendenza fallita", + "File": "File", + "Files": "File", + "Forbidden": "Vietato", + "Found": "Trovato", + "Gateway Timeout": "Tempo scaduto per il gateway", + "Go Home": "Vai alla Home", + "Go to page :page": "Vai alla pagina :page", + "Gone": "Andata", + "Hello!": "Ciao!", + "Hide": "Nascondi", + "Hide :name": "Nascondi :name", + "Home": "Home", + "HTTP Version Not Supported": "Versione HTTP non supportata", + "I'm a teapot": "Sono una teiera", + "If you did not create an account, no further action is required.": "Se non hai creato un account, non è richiesta alcuna azione.", + "If you did not request a password reset, no further action is required.": "Se non hai richiesto un reset della password, non è richiesta alcuna azione.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Se non riesci a cliccare sul pulsante \":actionText\", copia e incolla l'URL seguente\nnel tuo browser:", + "IM Used": "IM utilizzati", + "Image": "Immagine", + "Impersonate": "Impersona", + "Impersonation": "Impersonificazione", + "Import": "Importa", + "Import :name": "Importa :name", + "Insufficient Storage": "Spazio insufficiente", + "Internal Server Error": "Errore interno al server", + "Introduction": "introduzione", + "Invalid filename.": "Nome file non valido.", + "Invalid JSON was returned from the route.": "JSON non valido è stato restituito dalla route.", + "Invalid SSL Certificate": "Certificato SSL invalido", + "length": "dimensione", + "Length Required": "Lunghezza necessaria", + "Like": "Mi Piace", + "Load": "Carica", + "Localize": "Localizza", + "Location": "Posizione", + "Locked": "Bloccata", + "Log In": "Accedi", + "Log Out": "Esci", + "Login": "Accedi", + "Logout": "Esci", + "Loop Detected": "Loop identificato", + "Maintenance Mode": "In manutenzione", + "Method Not Allowed": "Metodo non consentito", + "Misdirected Request": "Richiesta mal indirizzata", + "Moved Permanently": "Trasferito permanentemente", + "Multi-Status": "Stati multipli", + "Multiple Choices": "Scelte multiple", + "Network Authentication Required": "Autenticazione di rete necessaria", + "Network Connect Timeout Error": "Errore di timeout della connessione di rete", + "Network Read Timeout Error": "Errore timeout lettura rete", + "New": "Crea", + "New :name": "Nuovo :name", + "No": "No", + "No Content": "Nessun contenuto", + "Non-Authoritative Information": "Informazione non autorevole", + "Not Acceptable": "Non accettabile", + "Not Extended": "Non esteso", + "Not Found": "Non trovato", + "Not Implemented": "Non implementato", + "Not Modified": "Non modificata", + "of": "di", + "OK": "OK", + "Open": "Aprire", + "Open in a current window": "Apri in una finestra corrente", + "Open in a new window": "Apri in una nuova finestra", + "Open in a parent frame": "Apri in un frame principale", + "Open in the topmost frame": "Apri nel riquadro più in alto", + "Open on the website": "Apri sul sito", + "Origin Is Unreachable": "Origine non raggiungibile", + "Page Expired": "Pagina scaduta", + "Pagination Navigation": "Navigazione della Paginazione", + "Partial Content": "Contenuto parziale", + "Payload Too Large": "Payload troppo grande", + "Payment Required": "Pagamento richiesto", + "Permanent Redirect": "Re-indirizzamento permanente", + "Please click the button below to verify your email address.": "Clicca sul pulsante qui sotto per verificare il tuo indirizzo email.", + "Precondition Failed": "Precondizione fallita", + "Precondition Required": "Precondizione necessaria", + "Preview": "Anteprima", + "Price": "Prezzo", + "Processing": "In processo", + "Proxy Authentication Required": "Autenticazione al proxy richiesta", + "Railgun Error": "Errore del cannone a rotaia", + "Range Not Satisfiable": "intervallo non soddisfacibile", + "Record": "Documentazione", + "Regards,": "Distinti saluti,", + "Register": "Registrati", + "Request Header Fields Too Large": "Campi header della richiesta troppo grandi", + "Request Timeout": "Tempo scaduto per la richiesta", + "Reset Content": "Resetta il contenuto", + "Reset Password": "Resetta la password", + "Reset Password Notification": "Notifica di reset della password", + "Restore": "Ripristina", + "Restore :name": "Ripristina :name", + "results": "risultati", + "Retry With": "Riprova con", + "Save": "Salva", + "Save & Close": "Salva e chiudi", + "Save & Return": "Salva e ritorna", + "Save :name": "Salva :name", + "Search": "Cerca", + "Search :name": "Cerca :name", + "See Other": "Guarda altro", + "Select": "Seleziona", + "Select All": "Seleziona tutto", + "Send": "Invia", + "Server Error": "Errore server", + "Service Unavailable": "Servizio non disponibile", + "Session Has Expired": "Sessione scaduta", + "Settings": "Impostazioni", + "Show": "Mostra", + "Show :name": "Mostra :name", + "Show All": "Mostra tutto", + "Showing": "Mostra", + "Sign In": "Accedi", + "Solve": "Risolvere", + "SSL Handshake Failed": "Handshake SSL fallita", + "Start": "Avvia", + "status": "stato", + "Stop": "Ferma", + "Submit": "Invia", + "Subscribe": "Abbonati", + "Switch": "Passa", + "Switch To Role": "Passa al ruolo", + "Switching Protocols": "Scambiando protocolli", + "Tag": "Etichetta", + "Tags": "Etichette", + "Temporary Redirect": "Re-indirizzamento temporaneo", + "The given data was invalid.": "I dati forniti non sono validi.", + "The response is not a streamed response.": "La risposta non è una risposta in streaming.", + "The response is not a view.": "La risposta non è una visione.", + "This action is unauthorized.": "Questa azione non è autorizzata.", + "This password reset link will expire in :count minutes.": "Questo link di reset della password scadrà tra :count minuti.", + "to": "a", + "Toggle navigation": "Cambia navigazione", + "Too Early": "Troppo presto", + "Too Many Requests": "Troppe richieste", + "Translate": "Traduci", + "Translate It": "Traducilo", + "Unauthorized": "Non autorizzato", + "Unavailable For Legal Reasons": "Non disponibile per motivi legali", + "Unknown Error": "Errore sconosciuto", + "Unpack": "Decomprimi", + "Unprocessable Entity": "Entità improcessabile", + "Unsubscribe": "Annulla l'iscrizione", + "Unsupported Media Type": "Media Type non supportato", + "Up": "Su", + "Update": "Aggiorna", + "Update :name": "Aggiorna :name", + "Upgrade Required": "Aggiornamento richiesto", + "URI Too Long": "URI troppo lungo", + "Use Proxy": "Usa un proxy", + "User": "Utente", + "Variant Also Negotiates": "Variante anche negozia", + "Verify Email Address": "Verifica indirizzo email", + "View": "Visualizza", + "View :name": "Visualizza :name", + "Web Server is Down": "Web server spento", + "Whoops!": "Ops!", + "Yes": "Sì", + "You are receiving this email because we received a password reset request for your account.": "Hai ricevuto questa email perché abbiamo ricevuto una richiesta di reset della password per il tuo account." +} \ No newline at end of file diff --git a/lang/it/actions.php b/lang/it/actions.php new file mode 100644 index 00000000..b50c5d3f --- /dev/null +++ b/lang/it/actions.php @@ -0,0 +1,119 @@ + 'Accettare', + 'action' => 'Azione', + 'actions' => 'Azioni', + 'add' => 'Aggiungi', + 'admin' => 'Ammin', + 'agree' => 'Essere d\'accordo', + 'archive' => 'Archivio', + 'assign' => 'Assegnare', + 'associate' => 'Associare', + 'attach' => 'Allega', + 'browse' => 'Naviga', + 'cancel' => 'Annulla', + 'choose' => 'Scegli', + 'choose_file' => 'Scegli il file', + 'choose_image' => 'Scegli Immagine', + 'click_to_copy' => 'Fare clic per copiare', + 'close' => 'Chiudi', + 'collapse' => 'Comprimi', + 'collapse_all' => 'Comprimi tutto', + 'comment' => 'Commenta', + 'confirm' => 'Conferma', + 'connect' => 'Collega', + 'create' => 'Crea', + 'delete' => 'Elimina', + 'detach' => 'Scollega', + 'details' => 'Dettagli', + 'disable' => 'Disattiva', + 'discard' => 'Scarta', + 'done' => 'Fatto', + 'down' => 'Giù', + 'duplicate' => 'Duplica', + 'edit' => 'Modifica', + 'enable' => 'Abilita', + 'expand' => 'Espandi', + 'expand_all' => 'Espandi tutto', + 'explanation' => 'Spiegazione', + 'export' => 'Esporta', + 'file' => 'File', + 'files' => 'File', + 'go_home' => 'Torna alla Home', + 'hide' => 'Nascondi', + 'home' => 'Home', + 'image' => 'Immagine', + 'impersonate' => 'Impersona', + 'impersonation' => 'Impersonificazione', + 'import' => 'Importa', + 'introduction' => 'introduzione', + 'like' => 'Mi Piace', + 'load' => 'Carica', + 'localize' => 'Localizza', + 'log_in' => 'Login', + 'log_out' => 'Disconnettersi', + 'named' => [ + 'add' => 'Aggiungi :name', + 'choose' => 'Scegli :name', + 'create' => 'Crea :name', + 'delete' => 'Cancella :name', + 'duplicate' => 'Duplica: nome', + 'edit' => 'Modifica :name', + 'export' => 'Esporta :name', + 'hide' => 'Nascondi :name', + 'import' => 'Importa :name', + 'new' => 'Nuovo :name', + 'restore' => 'Ripristina :name', + 'save' => 'Salva :name', + 'search' => 'Cerca :name', + 'show' => 'Mostra :name', + 'update' => 'Aggiorna :name', + 'view' => 'Mostra :name', + ], + 'new' => 'Nuovo', + 'no' => 'NO', + 'open' => 'Aprire', + 'open_website' => 'Apri sul sito', + 'preview' => 'Anteprima', + 'price' => 'Prezzo', + 'record' => 'Documentazione', + 'restore' => 'Ripristina', + 'save' => 'Salva', + 'save_and_close' => 'Salva e chiudi', + 'save_and_return' => 'Salva e ritorna', + 'search' => 'Ricerca', + 'select' => 'Seleziona', + 'select_all' => 'Seleziona tutto', + 'send' => 'Invia', + 'settings' => 'Impostazioni', + 'show' => 'Mostra', + 'show_all' => 'Mostra tutto', + 'sign_in' => 'Accedi', + 'solve' => 'Risolvere', + 'start' => 'Avvia', + 'stop' => 'Ferma', + 'submit' => 'Invia', + 'subscribe' => 'Sottoscrivi', + 'switch' => 'Passa', + 'switch_to_role' => 'Passa al ruolo', + 'tag' => 'Etichetta', + 'tags' => 'Etichette', + 'target_link' => [ + 'blank' => 'Apri in una nuova finestra', + 'parent' => 'Apri in un frame principale', + 'self' => 'Apri in una finestra corrente', + 'top' => 'Apri nel riquadro più in alto', + ], + 'translate' => 'Traduci', + 'translate_it' => 'Traducilo', + 'unpack' => 'Decomprimi', + 'unsubscribe' => 'Annulla l\'iscrizione', + 'up' => 'Su', + 'update' => 'Aggiorna', + 'user' => 'Utente', + 'view' => 'Visualizza', + 'yes' => 'SI', +]; diff --git a/lang/it/auth.php b/lang/it/auth.php new file mode 100644 index 00000000..54a09678 --- /dev/null +++ b/lang/it/auth.php @@ -0,0 +1,9 @@ + 'Credenziali non valide.', + 'password' => 'Il campo :attribute non è corretto.', + 'throttle' => 'Troppi tentativi di accesso. Riprova tra :seconds secondi.', +]; diff --git a/lang/it/http-statuses.php b/lang/it/http-statuses.php new file mode 100644 index 00000000..72321c32 --- /dev/null +++ b/lang/it/http-statuses.php @@ -0,0 +1,84 @@ + 'Errore sconosciuto', + '100' => 'Continua', + '101' => 'Scambiando protocolli', + '102' => 'In processo', + '200' => 'OK', + '201' => 'Creato', + '202' => 'Accettato', + '203' => 'Informazione non autorevole', + '204' => 'Nessun contenuto', + '205' => 'Resetta il contenuto', + '206' => 'Contenuto parziale', + '207' => 'Stati multipli', + '208' => 'Già riportato', + '226' => 'IM utilizzati', + '300' => 'Scelte multiple', + '301' => 'Trasferito permanentemente', + '302' => 'Trovato', + '303' => 'Guarda altro', + '304' => 'Non modificata', + '305' => 'Usa un proxy', + '307' => 'Re-indirizzamento temporaneo', + '308' => 'Re-indirizzamento permanente', + '400' => 'Cattiva richiesta', + '401' => 'Non autorizzata', + '402' => 'Pagamento richiesto', + '403' => 'Accesso vietato', + '404' => 'Pagina non trovata', + '405' => 'Metodo non consentito', + '406' => 'Non accettabile', + '407' => 'Autenticazione al proxy richiesta', + '408' => 'Tempo scaduto per la richiesta', + '409' => 'Conflitto', + '410' => 'Andata', + '411' => 'Lunghezza necessaria', + '412' => 'Precondizione fallita', + '413' => 'Payload troppo grande', + '414' => 'URI troppo lungo', + '415' => 'Media Type non supportato', + '416' => 'intervallo non soddisfacibile', + '417' => 'Aspettativa fallita', + '418' => 'Sono una teiera', + '419' => 'Sessione scaduta', + '421' => 'Richiesta mal indirizzata', + '422' => 'Entità improcessabile', + '423' => 'Bloccata', + '424' => 'Dipendenza fallita', + '425' => 'Troppo presto', + '426' => 'Aggiornamento richiesto', + '428' => 'Precondizione necessaria', + '429' => 'Troppe richieste', + '431' => 'Campi header della richiesta troppo grandi', + '444' => 'Connessione chiusa senza risposta', + '449' => 'Riprova con', + '451' => 'Non disponibile per motivi legali', + '499' => 'Richiesta chiusa del cliente', + '500' => 'Errore interno al server', + '501' => 'Non implementato', + '502' => 'Gateway cattivo', + '503' => 'In manutenzione', + '504' => 'Tempo scaduto per il gateway', + '505' => 'Versione HTTP non supportata', + '506' => 'Variante anche negozia', + '507' => 'Spazio insufficiente', + '508' => 'Loop identificato', + '509' => 'Limita di banda superato', + '510' => 'Non esteso', + '511' => 'Autenticazione di rete necessaria', + '520' => 'Errore sconosciuto', + '521' => 'Web server spento', + '522' => 'Tempo scaduto per la connessione', + '523' => 'Origine non raggiungibile', + '524' => 'Un timeout è avvenuto', + '525' => 'Handshake SSL fallita', + '526' => 'Certificato SSL invalido', + '527' => 'Errore del cannone a rotaia', + '598' => 'Errore timeout lettura rete', + '599' => 'Errore di timeout della connessione di rete', + 'unknownError' => 'Errore sconosciuto', +]; diff --git a/lang/it/pagination.php b/lang/it/pagination.php new file mode 100644 index 00000000..64cdccc0 --- /dev/null +++ b/lang/it/pagination.php @@ -0,0 +1,8 @@ + 'Successivo »', + 'previous' => '« Precedente', +]; diff --git a/lang/it/passwords.php b/lang/it/passwords.php new file mode 100644 index 00000000..eb946bc4 --- /dev/null +++ b/lang/it/passwords.php @@ -0,0 +1,11 @@ + 'La password è stata reimpostata!', + 'sent' => 'Ti abbiamo inviato una email con il link per il reset della password!', + 'throttled' => 'Per favore, attendi prima di riprovare.', + 'token' => 'Questo token di reset della password non è valido.', + 'user' => 'Non riusciamo a trovare un utente con questo indirizzo email.', +]; diff --git a/lang/it/validation.php b/lang/it/validation.php new file mode 100644 index 00000000..9199e5ed --- /dev/null +++ b/lang/it/validation.php @@ -0,0 +1,286 @@ + ':Attribute deve essere accettato.', + 'accepted_if' => ':Attribute deve essere accettato quando :other è :value.', + 'active_url' => ':Attribute non è un URL valido.', + 'after' => ':Attribute deve essere una data successiva al :date.', + 'after_or_equal' => ':Attribute deve essere una data successiva o uguale al :date.', + 'alpha' => ':Attribute può contenere solo lettere.', + 'alpha_dash' => ':Attribute può contenere solo lettere, numeri e trattini.', + 'alpha_num' => ':Attribute può contenere solo lettere e numeri.', + 'any_of' => 'The :attribute field is invalid.', + 'array' => ':Attribute deve essere un array.', + 'ascii' => ':Attribute deve contenere solo caratteri alfanumerici single-byte e simboli.', + 'before' => ':Attribute deve essere una data precedente al :date.', + 'before_or_equal' => ':Attribute deve essere una data precedente o uguale al :date.', + 'between' => [ + 'array' => ':Attribute deve avere tra :min - :max elementi.', + 'file' => ':Attribute deve trovarsi tra :min - :max kilobyte.', + 'numeric' => ':Attribute deve trovarsi tra :min - :max.', + 'string' => ':Attribute deve trovarsi tra :min - :max caratteri.', + ], + 'boolean' => 'Il campo :attribute deve essere vero o falso.', + 'can' => 'Il campo :attribute contiene un valore non autorizzato.', + 'confirmed' => 'Il campo di conferma per :attribute non coincide.', + 'contains' => 'Il campo :attribute non contiene un valore richiesto.', + 'current_password' => 'Password non valida.', + 'date' => ':Attribute non è una data valida.', + 'date_equals' => ':Attribute deve essere una data e uguale a :date.', + 'date_format' => ':Attribute non coincide con il formato :format.', + 'decimal' => ':Attribute deve avere :decimal cifre decimali.', + 'declined' => ':Attribute deve essere rifiutato.', + 'declined_if' => ':Attribute deve essere rifiutato quando :other è :value.', + 'different' => ':Attribute e :other devono essere differenti.', + 'digits' => ':Attribute deve essere di :digits cifre.', + 'digits_between' => ':Attribute deve essere tra :min e :max cifre.', + 'dimensions' => 'Le dimensioni dell\'immagine di :attribute non sono valide.', + 'distinct' => ':Attribute contiene un valore duplicato.', + 'doesnt_end_with' => ':Attribute non può terminare con uno dei seguenti valori: :values.', + 'doesnt_start_with' => ':Attribute non può iniziare con uno dei seguenti valori: :values.', + 'email' => ':Attribute non è valido.', + 'ends_with' => ':Attribute deve finire con uno dei seguenti valori: :values', + 'enum' => 'Il campo :attribute non è valido.', + 'exists' => ':Attribute selezionato non è valido.', + 'extensions' => 'Il campo :attribute deve avere una delle seguenti estensioni: :values.', + 'file' => ':Attribute deve essere un file.', + 'filled' => 'Il campo :attribute deve contenere un valore.', + 'gt' => [ + 'array' => ':Attribute deve contenere più di :value elementi.', + 'file' => ':Attribute deve essere maggiore di :value kilobyte.', + 'numeric' => ':Attribute deve essere maggiore di :value.', + 'string' => ':Attribute deve contenere più di :value caratteri.', + ], + 'gte' => [ + 'array' => ':Attribute deve contenere un numero di elementi uguale o maggiore di :value.', + 'file' => ':Attribute deve essere uguale o maggiore di :value kilobyte.', + 'numeric' => ':Attribute deve essere uguale o maggiore di :value.', + 'string' => ':Attribute deve contenere un numero di caratteri uguale o maggiore di :value.', + ], + 'hex_color' => 'Il campo :attribute deve essere un colore esadecimale valido.', + 'image' => ':Attribute deve essere un\'immagine.', + 'in' => ':Attribute selezionato non è valido.', + 'in_array' => 'Il valore del campo :attribute non esiste in :other.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => ':Attribute deve essere un numero intero.', + 'ip' => ':Attribute deve essere un indirizzo IP valido.', + 'ipv4' => ':Attribute deve essere un indirizzo IPv4 valido.', + 'ipv6' => ':Attribute deve essere un indirizzo IPv6 valido.', + 'json' => ':Attribute deve essere una stringa JSON valida.', + 'list' => 'Il campo :attribute deve essere un elenco.', + 'lowercase' => ':Attribute deve contenere solo caratteri minuscoli.', + 'lt' => [ + 'array' => ':Attribute deve contenere meno di :value elementi.', + 'file' => ':Attribute deve essere minore di :value kilobyte.', + 'numeric' => ':Attribute deve essere minore di :value.', + 'string' => ':Attribute deve contenere meno di :value caratteri.', + ], + 'lte' => [ + 'array' => ':Attribute deve contenere un numero di elementi minore o uguale a :value.', + 'file' => ':Attribute deve essere minore o uguale a :value kilobyte.', + 'numeric' => ':Attribute deve essere minore o uguale a :value.', + 'string' => ':Attribute deve contenere un numero di caratteri minore o uguale a :value.', + ], + 'mac_address' => 'Il campo :attribute deve essere un indirizzo MAC valido .', + 'max' => [ + 'array' => ':Attribute non può avere più di :max elementi.', + 'file' => ':Attribute non può essere superiore a :max kilobyte.', + 'numeric' => ':Attribute non può essere superiore a :max.', + 'string' => ':Attribute non può contenere più di :max caratteri.', + ], + 'max_digits' => ':Attribute non può contenere più di :max cifre.', + 'mimes' => ':Attribute deve essere del tipo: :values.', + 'mimetypes' => ':Attribute deve essere del tipo: :values.', + 'min' => [ + 'array' => ':Attribute deve avere almeno :min elementi.', + 'file' => ':Attribute deve essere almeno di :min kilobyte.', + 'numeric' => ':Attribute deve essere almeno :min.', + 'string' => ':Attribute deve contenere almeno :min caratteri.', + ], + 'min_digits' => ':Attribute deve contenere almeno :min cifre.', + 'missing' => 'Il campo :attribute deve mancare.', + 'missing_if' => 'Il campo :attribute deve mancare quando :other è :value.', + 'missing_unless' => 'Il campo :attribute deve mancare a meno che :other non sia :value.', + 'missing_with' => 'Il campo :attribute deve mancare quando è presente :values.', + 'missing_with_all' => 'Il campo :attribute deve mancare quando sono presenti :values.', + 'multiple_of' => ':Attribute deve essere un multiplo di :value', + 'not_in' => 'Il valore selezionato per :attribute non è valido.', + 'not_regex' => 'Il formato di :attribute non è valido.', + 'numeric' => ':Attribute deve essere un numero.', + 'password' => [ + 'letters' => ':Attribute deve contenere almeno un carattere.', + 'mixed' => ':Attribute deve contenere almeno un carattere maiuscolo ed un carattere minuscolo.', + 'numbers' => ':Attribute deve contenere almeno un numero.', + 'symbols' => ':Attribute deve contenere almeno un simbolo.', + 'uncompromised' => ':Attribute è presente negli archivi dei dati trafugati. Per piacere scegli un valore differente per :attribute.', + ], + 'present' => 'Il campo :attribute deve essere presente.', + 'present_if' => 'Il campo :attribute deve essere presente quando :other è :value.', + 'present_unless' => 'Il campo :attribute deve essere presente a meno che :other non sia :value.', + 'present_with' => 'Il campo :attribute deve essere presente quando è presente :values.', + 'present_with_all' => 'Il campo :attribute deve essere presente quando sono presenti :values.', + 'prohibited' => ':Attribute non consentito.', + 'prohibited_if' => ':Attribute non consentito quando :other è :value.', + 'prohibited_if_accepted' => 'Il campo :attribute è vietato quando :other è accettato.', + 'prohibited_if_declined' => 'Il campo :attribute è vietato quando :other è rifiutato.', + 'prohibited_unless' => ':Attribute non consentito a meno che :other sia contenuto in :values.', + 'prohibits' => ':Attribute impedisce a :other di essere presente.', + 'regex' => 'Il formato del campo :attribute non è valido.', + 'required' => 'Il campo :attribute è richiesto.', + 'required_array_keys' => 'Il campo :attribute deve contenere voci per: :values.', + 'required_if' => 'Il campo :attribute è richiesto quando :other è :value.', + 'required_if_accepted' => ':Attribute è richiesto quando :other è accettato.', + 'required_if_declined' => 'Il campo :attribute è richiesto quando :other è rifiutato.', + 'required_unless' => 'Il campo :attribute è richiesto a meno che :other sia in :values.', + 'required_with' => 'Il campo :attribute è richiesto quando :values è presente.', + 'required_with_all' => 'Il campo :attribute è richiesto quando :values sono presenti.', + 'required_without' => 'Il campo :attribute è richiesto quando :values non è presente.', + 'required_without_all' => 'Il campo :attribute è richiesto quando nessuno di :values è presente.', + 'same' => ':Attribute e :other devono coincidere.', + 'size' => [ + 'array' => ':Attribute deve contenere :size elementi.', + 'file' => ':Attribute deve essere :size kilobyte.', + 'numeric' => ':Attribute deve essere :size.', + 'string' => ':Attribute deve contenere :size caratteri.', + ], + 'starts_with' => ':Attribute deve iniziare con uno dei seguenti: :values', + 'string' => ':Attribute deve essere una stringa.', + 'timezone' => ':Attribute deve essere una zona valida.', + 'ulid' => ':Attribute deve essere un ULID valido.', + 'unique' => ':Attribute è stato già utilizzato.', + 'uploaded' => ':Attribute non è stato caricato.', + 'uppercase' => ':Attribute deve contenere solo caratteri maiuscoli.', + 'url' => 'Il formato del campo :attribute non è valido.', + 'uuid' => ':Attribute deve essere un UUID valido.', + 'attributes' => [ + 'address' => 'indirizzo', + 'affiliate_url' => 'URL di affiliazione', + 'age' => 'età', + 'amount' => 'Quantità', + 'announcement' => 'annuncio', + 'area' => 'la zona', + 'audience_prize' => 'premio del pubblico', + 'audience_winner' => 'audience winner', + 'available' => 'disponibile', + 'birthday' => 'compleanno', + 'body' => 'corpo', + 'city' => 'città', + 'company' => 'company', + 'compilation' => 'compilazione', + 'concept' => 'concetto', + 'conditions' => 'condizioni', + 'content' => 'contenuto', + 'contest' => 'contest', + 'country' => 'paese', + 'cover' => 'copertina', + 'created_at' => 'creato il', + 'creator' => 'Creatore', + 'currency' => 'valuta', + 'current_password' => 'password attuale', + 'customer' => 'cliente', + 'date' => 'data', + 'date_of_birth' => 'data di nascita', + 'dates' => 'date', + 'day' => 'giorno', + 'deleted_at' => 'cancellato il', + 'description' => 'descrizione', + 'display_type' => 'tipo di visualizzazione', + 'district' => 'quartiere', + 'duration' => 'durata', + 'email' => 'e-mail', + 'excerpt' => 'estratto', + 'filter' => 'filtro', + 'finished_at' => 'finito alle', + 'first_name' => 'nome', + 'gender' => 'genere', + 'grand_prize' => 'grand prize', + 'group' => 'gruppo', + 'hour' => 'ora', + 'image' => 'Immagine', + 'image_desktop' => 'immagine del desktop', + 'image_main' => 'immagine principale', + 'image_mobile' => 'immagine mobile', + 'images' => 'immagini', + 'is_audience_winner' => 'è il vincitore del pubblico', + 'is_hidden' => 'è nascosto', + 'is_subscribed' => 'è iscritto', + 'is_visible' => 'è visibile', + 'is_winner' => 'è vincitore', + 'items' => 'elementi', + 'key' => 'chiave', + 'last_name' => 'cognome', + 'lesson' => 'lezione', + 'line_address_1' => 'indirizzo di linea 1', + 'line_address_2' => 'indirizzo di linea 2', + 'login' => 'login', + 'message' => 'Messaggio', + 'middle_name' => 'secondo nome', + 'minute' => 'minuto', + 'mobile' => 'cellulare', + 'month' => 'mese', + 'name' => 'nome', + 'national_code' => 'codice nazionale', + 'nickname' => 'soprannome', + 'number' => 'numero', + 'password' => 'password', + 'password_confirmation' => 'conferma password', + 'phone' => 'telefono', + 'photo' => 'foto', + 'portfolio' => 'portafoglio', + 'postal_code' => 'Codice Postale', + 'preview' => 'anteprima', + 'price' => 'prezzo', + 'product_id' => 'Codice prodotto', + 'product_uid' => 'ID del prodotto', + 'product_uuid' => 'UUID del prodotto', + 'promo_code' => 'codice promozionale', + 'province' => 'Provincia', + 'quantity' => 'quantità', + 'reason' => 'motivo', + 'recaptcha_response_field' => 'campo di risposta recaptcha', + 'referee' => 'arbitro', + 'referees' => 'arbitri', + 'reject_reason' => 'rifiutare la ragione', + 'remember' => 'ricordare', + 'restored_at' => 'ripristinato il', + 'result_text_under_image' => 'testo del risultato sotto l\'immagine', + 'role' => 'ruolo', + 'rule' => 'regola', + 'rules' => 'regole', + 'second' => 'secondo', + 'sex' => 'sesso', + 'shipment' => 'spedizione', + 'short_text' => 'testo breve', + 'size' => 'dimensione', + 'situation' => 'situazione', + 'skills' => 'competenze', + 'slug' => 'lumaca', + 'specialization' => 'specializzazione', + 'started_at' => 'iniziato alle', + 'state' => 'stato', + 'status' => 'stato', + 'street' => 'strada', + 'student' => 'alunno', + 'subject' => 'argomento', + 'tag' => 'etichetta', + 'tags' => 'tag', + 'teacher' => 'insegnante', + 'terms' => 'termini', + 'test_description' => 'descrizione del testo', + 'test_locale' => 'locale di prova', + 'test_name' => 'nome di prova', + 'text' => 'testo', + 'time' => 'ora', + 'title' => 'titolo', + 'type' => 'tipo', + 'updated_at' => 'aggiornato il', + 'user' => 'utente', + 'username' => 'nome utente', + 'value' => 'valore', + 'winner' => 'winner', + 'work' => 'work', + 'year' => 'anno', + ], +]; diff --git a/lang/pt_BR.json b/lang/pt_BR.json new file mode 100644 index 00000000..13aaa9ad --- /dev/null +++ b/lang/pt_BR.json @@ -0,0 +1,1044 @@ +{ + "(and :count more error)": "(e mais :count erro)", + "(and :count more errors)": "(e mais :count erro)|(e mais :count erros)|(e mais :count erros)", + "30 Days": "30 dias", + "60 Days": "60 dias", + "90 Days": "90 dias", + ":amount selected": ":Amount selecionados", + ":amount Total": "Total :amount", + ":days day trial": ":Days dias de teste", + ":resource Details": ":Resource detalhes", + ":resource Details: :title": ":Resource detalhes: :title", + "A decryption key is required.": "Uma chave para decriptografia é necessaria.", + "A fresh verification link has been sent to your email address.": "Um novo link de verificação foi enviado para seu endereço de e-mail.", + "A new verification link has been sent to the email address you provided during registration.": "Um novo link de verificação foi enviado para o endereço de e-mail que você forneceu durante o processo de cadastro.", + "A new verification link has been sent to the email address you provided in your profile settings.": "Um novo link de verificação foi enviado para o endereço de e-mail fornecido nas configurações do seu perfil.", + "A new verification link has been sent to your email address.": "Um novo link de verificação foi enviado para seu endereço de e-mail.", + "Accept Invitation": "Aceitar convite", + "Action": "Ação", + "Action Event": "Evento de ação", + "Action Events": "Eventos de ação", + "Action Happened At": "Aconteceu Em", + "Action Initiated By": "Ação iniciada por", + "Action Name": "Nome da ação", + "Action Status": "Status da ação", + "Action Target": "Destino da ação", + "Actions": "Ações", + "Add": "Adicionar", + "Add :resource": "Adicionar :resource", + "Add a new team member to your team, allowing them to collaborate with you.": "Adicionar um novo membro no seu time, permitindo que ele colabore com você.", + "Add additional security to your account using two factor authentication.": "Adicione mais segurança à sua conta usando autenticação em dois fatores.", + "Add Payment Method": "Adicionar método de pagamento", + "Add row": "Adicionar linha", + "Add Team Member": "Adicionar membro ao time", + "Add VAT Number": "Adicionar número de VAT", + "Added.": "Adicionado.", + "Additional billing information updated successfully.": "Informações de cobrança adicionais atualizadas com sucesso.", + "Address": "Endereço", + "Address Line 2": "Endereço linha 2", + "Administrator": "Administrador", + "Administrator users can perform any action.": "Usuários com privilégios de Administrador podem executar qualquer ação.", + "Afghanistan": "Afeganistão", + "Aland Islands": "Ilhas Åland", + "Albania": "Albânia", + "Algeria": "Argélia", + "All of the people that are part of this team.": "Todas as pessoas que fazem parte deste time.", + "All resources loaded.": "Todos os recursos carregados.", + "All rights reserved.": "Todos os direitos reservados.", + "Already registered?": "Já registrado?", + "American Samoa": "Samoa Americana", + "An error occurred while uploading the file.": "Ocorreu um erro ao carregar o arquivo.", + "An error occurred while uploading the file: :error": "Ocorreu um erro ao carregar o arquivo: :error", + "An unexpected error occurred and we have notified our support team. Please try again later.": "Ocorreu um erro inesperado e notificamos nosso time de suporte. Por favor, tente novamente mais tarde.", + "Andorra": "Andorra", + "Angola": "Angola", + "Anguilla": "Anguila", + "Another user has updated this resource since this page was loaded. Please refresh the page and try again.": "Outro usuário atualizou este recurso desde que esta página foi carregada. Por favor, refresque a página e tente novamente.", + "Antarctica": "Antártica", + "Antigua And Barbuda": "Antígua E Barbuda", + "Antigua and Barbuda": "Antígua e Barbuda", + "API Token": "Token da API", + "API Token Permissions": "Permissões do Token da API", + "API Tokens": "Tokens da API", + "API tokens allow third-party services to authenticate with our application on your behalf.": "Tokens da API permitem que serviços de terceiros se autentiquem em nossa aplicação em seu nome.", + "Apply": "Aplicar", + "Apply Coupon": "Aplicar Cupom", + "April": "Abril", + "Are you sure you want to attempt to pay :amount?": "Tem certeza de que deseja tentar pagar :amount?", + "Are you sure you want to cancel your subscription?": "Tem certeza que deseja cancelar sua assinatura?", + "Are you sure you want to delete all the notifications?": "Tem certeza de que deseja excluir todas as notificações?", + "Are you sure you want to delete the selected resources?": "Você tem certeza que deseja excluir os recursos selecionados?", + "Are you sure you want to delete this file?": "Você tem certeza que deseja excluir este arquivo?", + "Are you sure you want to delete this notification?": "Tem certeza de que deseja excluir esta notificação?", + "Are you sure you want to delete this payment method?": "Tem certeza de que deseja excluir esta forma de pagamento?", + "Are you sure you want to delete this resource?": "Você tem certeza que deseja excluir este recurso?", + "Are you sure you want to delete this team? Once a team is deleted, all of its resources and data will be permanently deleted.": "Tem certeza que quer excluir este time? Uma vez excluído, todos os dados e recursos relativos a ela serão excluídos permanentemente.", + "Are you sure you want to delete your account?": "Tem certeza que quer excluir a sua conta?", + "Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Tem certeza que quer excluir a sua conta? Uma vez excluída, todos os dados e recursos relativos a ela serão permanentemente excluídos. Por favor informe a sua senha para confirmar que você deseja excluir permanentemente a sua conta.", + "Are you sure you want to detach the selected resources?": "Você tem certeza que deseja liberar os recursos selecionados?", + "Are you sure you want to detach this resource?": "Você tem certeza que deseja liberar esse recurso?", + "Are you sure you want to force delete the selected resources?": "Você tem certeza que deseja forçar a exclusão dos recursos selecionados?", + "Are you sure you want to force delete this resource?": "Você tem certeza que deseja forçar a exclusão deste recurso?", + "Are you sure you want to log out?": "Tem certeza que deseja sair?", + "Are you sure you want to mark all notifications as read?": "Tem certeza de que deseja marcar todas as notificações como lidas?", + "Are you sure you want to remove this item?": "Tem certeza de que deseja remover este item?", + "Are you sure you want to restore the selected resources?": "Você tem certeza que deseja restaurar os recursos selecionados?", + "Are you sure you want to restore this resource?": "Você tem certeza que deseja restaurar esse recurso?", + "Are you sure you want to resume your subscription?": "Tem certeza de que deseja retomar sua assinatura?", + "Are you sure you want to run this action?": "Você tem certeza que deseja executar essa ação?", + "Are you sure you want to set this payment method as your default?": "Tem certeza de que deseja definir esta forma de pagamento como padrão?", + "Are you sure you want to stop impersonating?": "Tem certeza de que deseja parar de personificar?", + "Are you sure you would like to delete this API token?": "Tem certeza de que deseja excluir este token da API?", + "Are you sure you would like to leave this team?": "Tem certeza de que deseja sair deste time?", + "Are you sure you would like to remove this person from the team?": "Tem certeza de que deseja remover esta pessoa do time?", + "Are you sure you would like to switch billing plans?": "Tem certeza de que deseja mudar os planos de cobrança?", + "Argentina": "Argentina", + "Armenia": "Armênia", + "Aruba": "Aruba", + "Attach": "Anexar", + "Attach & Attach Another": "Anexar & Anexar outro", + "Attach :resource": "Anexar :resource", + "Attach files by dragging & dropping, selecting or pasting them.": "Anexe arquivos arrastando e soltando, selecionando ou colando.", + "August": "Agosto", + "Australia": "Austrália", + "Austria": "Áustria", + "Azerbaijan": "Azerbaijão", + "Bahamas": "Bahamas", + "Bahrain": "Barém", + "Bangladesh": "Bangladesh", + "Barbados": "Barbados", + "Before continuing, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.": "Antes de continuar, você pode verificar seu endereço de e-mail clicando no link que acabamos de enviar para você? Se você não recebeu o e-mail, teremos o prazer de lhe enviar outro.", + "Before proceeding, please check your email for a verification link.": "Antes de prosseguir, verifique seu e-mail para obter um link de verificação.", + "Belarus": "Bielorrússia", + "Belgium": "Bélgica", + "Belize": "Belize", + "Benin": "Benim", + "Bermuda": "Bermuda", + "Bhutan": "Butão", + "Billing Information": "Informações sobre faturamento", + "Billing Management": "Gestão de Faturamento", + "Bolivia": "Bolívia", + "Bolivia, Plurinational State of": "Estado Plurinacional da Bolívia", + "Bonaire, Sint Eustatius and Saba": "Bonaire, Santo Eustáquio e Saba", + "Bosnia And Herzegovina": "Bósnia E Herzegovina", + "Bosnia and Herzegovina": "Bósnia e Herzegovina", + "Botswana": "Botsuana", + "Bouvet Island": "Ilha Bouvet", + "Brazil": "Brasil", + "British Indian Ocean Territory": "Território Britânico do Oceano Índico", + "Browser Sessions": "Sessões do navegador", + "Brunei Darussalam": "Brunei", + "Bulgaria": "Bulgária", + "Burkina Faso": "Burquina Faso", + "Burundi": "Burundi", + "Cambodia": "Camboja", + "Cameroon": "Camarões", + "Canada": "Canadá", + "Cancel": "Cancelar", + "Cancel Subscription": "Cancelar a assinatura", + "Cape Verde": "Cabo Verde", + "Card": "Cartão", + "Cayman Islands": "Ilhas Cayman", + "Central African Republic": "República da África Central", + "Chad": "Chade", + "Change Subscription Plan": "Alterar plano de assinatura", + "Change the current payment method attached to your subscription": "Altere o método de pagamento atual de sua assinatura", + "Changes": "Alterações", + "Checkout": "Confira", + "Chile": "Chile", + "China": "China", + "Choose": "Escolha", + "Choose :field": "Escolha :field", + "Choose :resource": "Escolha :resource", + "Choose an option": "Escolha uma opção", + "Choose date": "Escolha uma data", + "Choose File": "Escolha o arquivo", + "Choose Files": "Escolha os arquivos", + "Choose Type": "Escolha o tipo", + "Christmas Island": "Ilha Do Natal", + "City": "Cidade", + "Click here to re-send the verification email.": "Clique aqui para reenviar o e-mail de verificação.", + "click here to request another": "clique aqui para solicitar outro", + "Click to choose": "Clique para escolher", + "Close": "Fechar", + "Cocos (Keeling) Islands": "Ilhas Cocos (Keeling)", + "Code": "Código", + "Colombia": "Colômbia", + "Comoros": "Comores", + "Confirm": "Confirmar", + "Confirm Billing Action": "Confirmar Ação de Cobrança", + "Confirm Password": "Confirmar senha", + "Confirm Payment": "Confirmar pagamento", + "Confirm your :amount payment": "Confirme seu pagamento de :amount", + "Congo": "Congo", + "Congo, Democratic Republic": "República Democrática do Congo", + "Congo, the Democratic Republic of the": "República Democrática do Congo", + "Constant": "Constante", + "Continue To Payment": "Continuar para pagamento", + "Cook Islands": "Ilhas Cook", + "Copy to clipboard": "Copiar para área de transferência", + "Costa Rica": "Costa Rica", + "Cote D'Ivoire": "Costa do Marfim", + "Country": "País", + "Coupon": "Cupom", + "Coupon applied successfully.": "Cupom aplicado com sucesso.", + "Create": "Criar", + "Create & Add Another": "Criar e Adicionar Outro", + "Create :resource": "Criar :resource", + "Create a new team to collaborate with others on projects.": "Crie um time para colaborar com outros em projetos.", + "Create Account": "Criar Conta", + "Create API Token": "Criar Token da API", + "Create New Team": "Criar Novo Time", + "Create Team": "Criar Time", + "Created.": "Criado.", + "Croatia": "Croácia", + "CSV (.csv)": "CSV (.csv)", + "Cuba": "Cuba", + "Curaçao": "Curaçao", + "Current Password": "Senha Atual", + "Current Subscription Plan": "Plano de assinatura atual", + "Currently Subscribed": "Atualmente Assinado", + "Customer Balance": "Saldo do Cliente", + "Customize": "Personalizar", + "Cyprus": "Chipre", + "Czech Republic": "República Checa", + "Côte d'Ivoire": "Costa do Marfim", + "Dark": "Escuro", + "Dashboard": "Painel", + "December": "Dezembro", + "Decrease": "Diminuir", + "Default": "Padrão", + "Delete": "Excluir", + "Delete :resource": "Excluir :resource", + "Delete Account": "Excluir Conta", + "Delete all notifications": "Excluir todas as notificações", + "Delete API Token": "Excluir Token da API", + "Delete File": "Excluir O Arquivo", + "Delete Notification": "Excluir Notificação", + "Delete Resource": "Excluir O Recurso", + "Delete Selected": "Excluir Os Selecionados", + "Delete Team": "Excluir Time", + "Denmark": "Dinamarca", + "Detach": "Desanexar", + "Detach Resource": "Separar o Recurso", + "Detach Selected": "Separar os Selecionados", + "Details": "Detalhes", + "Disable": "Desativar", + "Djibouti": "Jibuti", + "Do you really want to leave? You have unsaved changes.": "Quer mesmo sair? Você tem mudanças não salvas.", + "Dominica": "Dominica", + "Dominican Republic": "República Dominicana", + "Done.": "Feito.", + "Download": "Baixar", + "Download Invoice": "Baixar Fatura", + "Drop file or click to choose": "Solte o arquivo ou clique para escolher", + "Drop files or click to choose": "Solte os arquivos ou clique para escolher", + "Ecuador": "Equador", + "Edit": "Editar", + "Edit :resource": "Editar :resource", + "Edit Attached": "Editar Anexado", + "Edit Profile": "Editar Perfil", + "Editor": "Editor", + "Editor users have the ability to read, create, and update.": "Usuários com privilégios de Editor podem ler, criar e atualizar.", + "Egypt": "Egito", + "El Salvador": "El Salvador", + "Email": "E-mail", + "email": "e-mail", + "Email Address": "Endereço de E-mail", + "Email Addresses": "Endereços de e-mail", + "Email Password Reset Link": "Link de redefinição de senha", + "Email Verification": "verificação de Email", + "Enable": "Ativar", + "Encrypted environment file already exists.": "Um arquivo criptografado de ambiente já existe.", + "Encrypted environment file not found.": "Arquivo criptografado de ambiente não encontrado.", + "Ensure your account is using a long, random password to stay secure.": "Garanta que sua conta esteja usando uma senha longa e aleatória para se manter seguro.", + "Environment file already exists.": "Arquivo de ambiente já existe.", + "Environment file not found.": "Arquivo de ambiente não encontrado.", + "Equatorial Guinea": "Guiné Equatorial", + "Eritrea": "Eritreia", + "Error": "Erro", + "errors": "erros", + "Estonia": "Estônia", + "Ethiopia": "Etiópia", + "ex VAT": "sem VAT", + "Excel (.xlsx)": "Excel (.xlsx)", + "Expires :expiration": "Expira :expiration", + "Export As CSV": "Exportar Como CSV", + "Extra Billing Information": "Informações extras de faturamento", + "Extra confirmation is needed to process your payment. Please continue to the payment page by clicking on the button below.": "É necessária uma confirmação extra para processar o seu pagamento. Por favor, continue para a página de pagamento clicando no botão abaixo.", + "Failed Subscription Payment": "Falha no pagamento da assinatura", + "Failed to load :resource!": "Falha ao carregar :resource!", + "Falkland Islands (Malvinas)": "Ilhas Falkland (Malvinas)", + "Faroe Islands": "Ilhas Faroé", + "February": "Fevereiro", + "Fiji": "Fiji", + "Filename": "Nome do arquivo", + "Finish enabling two factor authentication.": "Termine de habilitar a autenticação de dois fatores.", + "Finland": "Finlândia", + "For your security, please confirm your password to continue.": "Para sua segurança, por favor confirme a sua senha antes de prosseguir.", + "Forbidden": "Proibido", + "Force Delete": "Forçar Exclusão", + "Force Delete :resource": "Forçar Exclusão :resource", + "Force Delete Resource": "Forçar Exclusão de Recurso", + "Force Delete Selected": "Forçar Exclusão de Selecionado", + "Forgot Password": "Esqueceu a senha", + "Forgot your password?": "Esqueceu a senha?", + "Forgot Your Password?": "Esqueceu a Senha?", + "Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.": "Esqueceu sua senha? Sem problemas. É só nos informar o seu e-mail que nós enviaremos para você um link para redefinição de senha que irá permitir que você escolha uma nova senha.", + "France": "França", + "French Guiana": "Guiana Francesa", + "French Polynesia": "Polinésia Francesa", + "French Southern Territories": "Territórios Austrais Franceses", + "From": "A partir de", + "Gabon": "Gabão", + "Gambia": "Gâmbia", + "Georgia": "Georgia", + "Germany": "Alemanha", + "Ghana": "Gana", + "Gibraltar": "Gibraltar", + "Go Home": "Ir para o início", + "Go to page :page": "Ir para página :page", + "Great! You have accepted the invitation to join the :team team.": "Muito bom! Você aceitou o convite para se juntar à equipa :team.", + "Greece": "Grécia", + "Greenland": "Groenlândia", + "Grenada": "Granada", + "Guadeloupe": "Guadalupe", + "Guam": "Guam", + "Guatemala": "Guatemala", + "Guernsey": "Guernsey", + "Guinea": "Guiné", + "Guinea-Bissau": "Guiné-Bissau", + "Guyana": "Guiana", + "Haiti": "Haiti", + "Having second thoughts about cancelling your subscription? You can instantly reactivate your subscription at any time until the end of your current billing cycle. After your current billing cycle ends, you may choose an entirely new subscription plan.": "Pensando melhor em cancelar sua assinatura? Você pode reativar instantaneamente sua assinatura a qualquer momento até o final do seu ciclo de cobrança atual. Após o término do seu ciclo de cobrança atual, você poderá escolher um plano de assinatura totalmente novo.", + "Having second thoughts about cancelling your subscription? You can instantly reactive your subscription at any time until the end of your current billing cycle. After your current billing cycle ends, you may choose an entirely new subscription plan.": "Pensando melhor em cancelar sua assinatura? Você pode reativar instantaneamente sua assinatura a qualquer momento até o final do seu ciclo de cobrança atual. Após o término do seu ciclo de cobrança atual, você poderá escolher um plano de assinatura totalmente novo.", + "Heard Island & Mcdonald Islands": "Ilhas Heard e McDonald", + "Heard Island and McDonald Islands": "Ilha Heard e Ilhas McDonald", + "Hello!": "Olá!", + "Hide Content": "Esconder o Conteúdo", + "Hold Up!": "Espera!", + "Holy See (Vatican City State)": "Santa Sé", + "Honduras": "Honduras", + "Hong Kong": "Hong Kong", + "Hungary": "Hungria", + "I agree to the :terms_of_service and :privacy_policy": "Concordo com os :terms_of_service e com as :privacy_policy", + "Iceland": "Islândia", + "ID": "ID", + "If necessary, you may log out of all of your other browser sessions across all of your devices. Some of your recent sessions are listed below; however, this list may not be exhaustive. If you feel your account has been compromised, you should also update your password.": "Se necessário, você pode sair de todas as suas outras sessões de navegador em todos os seus dispositivos. Algumas de suas sessões recentes estão listadas abaixo; no entanto, esta lista pode não ser exaustiva. Se você sentir que sua conta foi comprometida, Você também deve atualizar sua senha.", + "If you already have an account, you may accept this invitation by clicking the button below:": "Se já tiver uma conta, poderá aceitar este convite carregando no botão abaixo:", + "If you did not create an account, no further action is required.": "Se você não criou uma conta, ignore este e-mail.", + "If you did not expect to receive an invitation to this team, you may discard this email.": "Se você não esperava receber um convite para este time, você pode descartar este e-mail.", + "If you did not receive the email": "Se você não recebeu o e-mail", + "If you did not request a password reset, no further action is required.": "Se você não solicitou essa redefinição de senha, ignore este e-mail.", + "If you do not have an account, you may create one by clicking the button below. After creating an account, you may click the invitation acceptance button in this email to accept the team invitation:": "Se você não tem uma conta, você pode criar uma clicando no botão abaixo. Depois de criar uma conta, você pode clicar no botão aceitar o convite neste e-mail para aceitar o convite do time:", + "If you need to add specific contact or tax information to your invoices, like your full business name, VAT identification number, or address of record, you may add it here.": "Se você precisar adicionar informações específicas de contato ou fiscal às suas faturas, como seu nome comercial completo, número de identificação de VAT ou endereço de registro, poderá adicioná -lo aqui.", + "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Se você estiver tendo problemas para clicar no botão \":actionText\", copie e cole a URL abaixo\nem seu navegador:", + "Impersonate": "Personificar", + "Increase": "Aumentar", + "India": "Índia", + "Indonesia": "Indonésia", + "Invalid filename.": "Nome de arquivo inválido.", + "Invalid JSON was returned from the route.": "JSON inválido foi retornado da rota.", + "Invoice Email Addresses": "Endereços de e-mail da fatura", + "Invoice emails updated successfully.": "E-mails da fatura foram atualizados com sucesso.", + "Invoices": "Faturas", + "Iran, Islamic Republic Of": "República Islâmica do Irã", + "Iran, Islamic Republic of": "República Islâmica do Irã", + "Iraq": "Iraque", + "Ireland": "Irlanda", + "Isle Of Man": "Ilha de Man", + "Isle of Man": "Ilha de Man", + "Israel": "Israel", + "It looks like you do not have an active subscription. You may choose one of the subscription plans below to get started. Subscription plans may be changed or cancelled at your convenience.": "Parece que você não tem uma assinatura ativa. Você pode escolher um dos planos de assinatura abaixo para começar. Os planos de assinatura podem ser alterados ou cancelados conforme sua conveniência.", + "Italy": "Itália", + "Jamaica": "Jamaica", + "January": "Janeiro", + "Japan": "Japão", + "Jersey": "Jersey", + "Jordan": "Jordânia", + "July": "Julho", + "June": "Junho", + "Kazakhstan": "Cazaquistão", + "Kenya": "Quênia", + "Key": "Chave", + "Kiribati": "Quiribati", + "Korea": "Coreia", + "Korea, Democratic People's Republic of": "República Popular Democrática da Coreia", + "Korea, Republic of": "República da Coreia", + "Kosovo": "Kosovo", + "Kuwait": "Kuwait", + "Kyrgyzstan": "Quirguistão", + "Lao People's Democratic Republic": "República Democrática Popular do Lao", + "Last active": "Última atividade", + "Last used": "Usado por último", + "Latvia": "Letônia", + "Leave": "Sair", + "Leave Team": "Sair do Time", + "Lebanon": "Líbano", + "length": "comprimento", + "Lens": "Lens", + "Lesotho": "Lesoto", + "Liberia": "Libéria", + "Libyan Arab Jamahiriya": "Jamahiriya Árabe da Líbia", + "Liechtenstein": "Liechtenstein", + "Light": "Claro", + "Lithuania": "Lituânia", + "Load :perPage More": "Carregar mais :perPage", + "Loading": "Carregando", + "Location": "Localização", + "Log in": "Entrar", + "Log In": "Entrar", + "Log Out": "Sair", + "Log out": "Sair", + "Log Out Other Browser Sessions": "Desligar Outras Sessões do Navegador", + "Log Viewer": "Visualizador de Log", + "Login": "Entrar", + "Logout": "Sair", + "Logs": "Logs", + "Luxembourg": "Luxemburgo", + "Macao": "Macau", + "Macedonia": "Macedônia do Norte", + "Macedonia, the former Yugoslav Republic of": "Ex-República Iugoslava da Macedônia", + "Madagascar": "Madagascar", + "Malawi": "Malawi", + "Malaysia": "Malásia", + "Maldives": "Maldivas", + "Mali": "Mali", + "Malta": "Malta", + "Manage Account": "Gerenciar Conta", + "Manage and log out your active sessions on other browsers and devices.": "Gerenciar e registrar suas sessões ativas em outros navegadores e dispositivos.", + "Manage API Tokens": "Gerenciar Tokens de API", + "Manage Role": "Gerenciar Papel", + "Manage Team": "Gerenciar Time", + "Managing billing for :billableName": "Gerenciando o faturamento de :billableName", + "March": "Março", + "Mark all as Read": "Marcar tudo como lido", + "Mark all notifications as read": "Marcar todas as notificações como lidas", + "Mark Read": "Marque lido", + "Mark Unread": "Marcar não lido", + "Marshall Islands": "Ilhas Marshall", + "Martinique": "Mauritânia", + "Mauritania": "Mauritania", + "Mauritius": "Mauritania", + "May": "Maio", + "Mayotte": "Mayotte", + "Mexico": "México", + "Micronesia, Federated States Of": "Estados Federados da Micronésia", + "Micronesia, Federated States of": "Estados Federados da Micronésia", + "Moldova": "Moldávia", + "Moldova, Republic of": "República da Moldávia", + "Monaco": "Mônaco", + "Mongolia": "Mongólia", + "Montenegro": "Montenegro", + "Month To Date": "Mês até a Data", + "Monthly": "Mensal", + "monthly": "mensal", + "Montserrat": "Monserrate", + "Morocco": "Marrocos", + "Mozambique": "Moçambique", + "Myanmar": "Birmânia", + "Name": "Nome", + "name": "nome", + "Namibia": "Namíbia", + "Nauru": "Nauru", + "Nepal": "Nepal", + "Netherlands": "Países Baixos", + "Netherlands Antilles": "Antilhas Holandesas", + "Nevermind": "Não importa", + "Nevermind, I'll keep my old plan": "Esqueça, vou manter meu antigo plano", + "New": "Novo", + "New :resource": "Novo :resource", + "New Caledonia": "Nova Caledônia", + "New Password": "Nova Senha", + "New Zealand": "Nova Zelândia", + "Next": "Próximo", + "Next Payment": "Próximo Pagamento", + "Next Payment on": "Próximo pagamento em", + "Nicaragua": "Nicarágua", + "Niger": "Níger", + "Nigeria": "Nigéria", + "Niue": "Niue", + "No": "Não", + "No :resource matched the given criteria.": "Nenhum :resource corresponde aos critérios indicados.", + "No additional information...": "Nenhuma informação adicional...", + "No Current Data": "Sem Dados Atuais", + "No Data": "Sem Dados", + "no file selected": "nenhum arquivo selecionado", + "No Increase": "Sem Aumento", + "No payment methods on file.": "Nenhum método de pagamento registrado.", + "No payment scheduled.": "Nenhum pagamento agendado.", + "No Prior Data": "Sem Dados Anteriores", + "No Results Found.": "Não Foram Encontrados Resultados.", + "Norfolk Island": "Ilha Norfolk", + "Northern Mariana Islands": "Ilhas Marianas do Norte", + "Norway": "Noruega", + "Not Found": "Não Encontrado", + "Notifications": "Notificações", + "Nova": "Nova", + "Nova User": "Usuário Nova", + "November": "Novembro", + "October": "Outubro", + "of": "de", + "OK": "OK", + "Oman": "Omã", + "Once a team is deleted, all of its resources and data will be permanently deleted. Before deleting this team, please download any data or information regarding this team that you wish to retain.": "Uma vez excluído, o time e todos os seus dados e recursos serão excluídos permanentemente. Antes de excluir este time, faça download de todos os dados e informações sobre este time que você deseje manter.", + "Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.": "Uma vez que sua conta é excluída, todos os dados e recursos desta conta serão excluídos permanentemente. Antes de excluir a sua conta, faça download de todos os dados e informações que você deseje manter.", + "Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.": "Uma vez excluída, todos os dados e recursos relativos a ela serão permanentemente excluídos. Por favor informe a sua senha para confirmar que você deseja excluir permanentemente a sua conta.", + "Only Trashed": "Apenas Destruído", + "Open Invoices": "Faturas Abertas", + "Original": "Original", + "Our billing management portal allows you to conveniently manage your subscription plan, payment method, and download your recent invoices.": "Nosso portal de gerenciamento de cobrança permite que você gerencie convenientemente seu plano de assinatura, método de pagamento e baixe suas faturas recentes.", + "Our billing management portal allows you to conveniently manage your subscription plan, payment methods, and download your recent invoices.": "Nosso portal de gerenciamento de cobrança permite que você gerencie convenientemente seu plano de assinatura, métodos de pagamento e baixe suas faturas recentes.", + "Page Expired": "Página expirou", + "Pagination Navigation": "Navegação da Paginação", + "Paid": "Pago", + "Pakistan": "Paquistão", + "Palau": "Palau", + "Palestinian Territory, Occupied": "Territórios Palestinos", + "Panama": "Panamá", + "Papua New Guinea": "Papua Nova Guiné", + "Paraguay": "Paraguai", + "password": "senha", + "Password": "Senha", + "Payment Confirmation": "Confirmação do Pagamento", + "Payment Information": "Informação de pagamento", + "Payment information updated successfully.": "Informações de pagamento atualizadas com sucesso.", + "Payment Method": "Forma de pagamento", + "Payment Methods": "Métodos de Pagamento", + "Payment Required": "Pagamento Requerido", + "Payments": "Pagamentos", + "Pending Team Invitations": "Convites de Time Pendentes", + "Per Page": "Por Página", + "Permanently delete this team.": "Excluir este time permanentemente.", + "Permanently delete your account.": "Excluir esta conta permanentemente.", + "Permissions": "Permissões", + "Peru": "Peru", + "Philippines": "Filipinas", + "Photo": "Foto", + "Pitcairn": "Picárnia", + "Please accept the terms of service.": "Por favor, aceite os termos de serviço.", + "Please click the button below to verify your email address.": "Por favor, clique no botão abaixo para verificar seu endereço de e-mail.", + "Please confirm access to your account by entering one of your emergency recovery codes.": "Por favor confirme o acesso à sua conta inserindo um de seus códigos de recuperação de emergência.", + "Please confirm access to your account by entering the authentication code provided by your authenticator application.": "Por favor confirme o acesso à sua conta informando um código de autenticação fornecido por seu aplicativo autenticador.", + "Please confirm your password before continuing.": "Por favor, confirme sua senha antes de continuar.", + "Please copy your new API token. For your security, it won't be shown again.": "Por favor copie seu novo token da API. Para sua segurança, ele não será mostrado novamente.", + "Please enter your password to confirm you would like to log out of your other browser sessions across all of your devices.": "Introduza a sua senha para confirmar que deseja sair das suas outras sessões de navegação em todos os seus dispositivos.", + "Please provide a maximum of three invoice emails addresses.": "Forneça no máximo três endereços de e-mails da fatura.", + "Please provide the email address of the person you would like to add to this team.": "Por favor, forneça o endereço de E-mail da pessoa que você gostaria de adicionar a este time.", + "Please set a default payment method before retrying payments.": "Defina um método de pagamento padrão antes de tentar novamente os pagamentos.", + "Please set a default payment method before swapping plans.": "Defina um método de pagamento padrão antes de trocar de plano.", + "Poland": "Polônia", + "Portugal": "Portugal", + "Press / to search": "Pressione / para pesquisar", + "Preview": "Visualizar", + "Previewing": "Visualizando", + "Previous": "Anterior", + "Privacy Policy": "Política de Privacidade", + "Profile": "Perfil", + "Profile Information": "Informações do Perfil", + "Puerto Rico": "Porto Rico", + "Qatar": "Qatar", + "Quarter To Date": "Trimestre até a Data", + "Recovery Code": "Código de Recuperação", + "Refresh": "Atualizar", + "Regards,": "Atenciosamente,", + "Regenerate Recovery Codes": "Gerar novamente os Códigos de Recuperação", + "Register": "Registrar", + "Reload": "Recarregar", + "Remember me": "Lembre-se de mim", + "Remember Me": "Lembre-se de mim", + "Remove": "Remover", + "Remove Photo": "Remover Foto", + "Remove Team Member": "Remover Membro do Time", + "Replicate": "Replicar", + "Required fields": "Campos obrigatórios", + "Resend Verification Email": "Enviar novamente o e-mail de verificação", + "Reset Filters": "Repor os Filtros", + "Reset Password": "Redefinir senha", + "Reset Password Notification": "Notificação de redefinição de senha", + "resource": "recurso", + "Resource Row Dropdown": "Lista suspensa da linha de recursos", + "Resources": "Recursos", + "resources": "recursos", + "Restore": "Restaurar", + "Restore :resource": "Restaurar :resource", + "Restore Resource": "Repor o Recurso", + "Restore Selected": "Repor os Selecionados", + "results": "resultados", + "Resume Subscription": "Retomar assinatura", + "Retry Payment": "Tente Novamente o Pagamento", + "Return to :appName": "Voltar para :appName", + "Reunion": "Reunião", + "Role": "Papel", + "Romania": "Romênia", + "Run Action": "Executar a Ação", + "Russian Federation": "Federação Russa", + "Rwanda": "Ruanda", + "Réunion": "Reunião", + "Saint Barthelemy": "São Bartolomeu", + "Saint Barthélemy": "São Bartolomeu", + "Saint Helena": "Santa Helena", + "Saint Kitts And Nevis": "São Cristóvão e Nevis", + "Saint Kitts and Nevis": "São Cristóvão e Nevis", + "Saint Lucia": "Santa Lúcia", + "Saint Martin": "Ilha de São Martinho", + "Saint Martin (French part)": "Ilha de São Martinho (parte francesa)", + "Saint Pierre And Miquelon": "São Pedro e Miquelon", + "Saint Pierre and Miquelon": "São Pedro e Miquelon", + "Saint Vincent And Grenadines": "São Vicente e Granadinas", + "Saint Vincent and the Grenadines": "São Vicente e Granadinas", + "Samoa": "Samoa", + "San Marino": "São Marino", + "Sao Tome And Principe": "São Tomé E Príncipe", + "Sao Tome and Principe": "São Tomé e Príncipe", + "Saudi Arabia": "Arábia Saudita", + "Save": "Salvar", + "Saved.": "Salvo.", + "Scroll to bottom": "Role para baixo", + "Scroll to top": "Role para cima", + "Search": "Pesquisar", + "Secure Area": "Área Segura", + "Select": "Selecionar", + "Select a different plan": "Selecione um plano diferente", + "Select a log file...": "Selecione um arquivo de log...", + "Select A New Photo": "Selecione uma nova foto", + "Select Action": "Selecionar a Ação", + "Select all": "Selecionar Tudo", + "Select All Dropdown": "Selecionar Todas As Listas Suspensas", + "Select this page": "Selecionar esta página", + "Send Password Reset Link": "Enviar link de redefinição de senha", + "Senegal": "Senegal", + "September": "Setembro", + "Serbia": "Sérvia", + "Server Error": "Erro do servidor", + "Service Unavailable": "Serviço indisponível", + "Set as default": "Definir como padrão", + "Setup Key": "Chave de configuração", + "Seychelles": "Seicheles", + "Show All Fields": "Mostrar Todos Os Campos", + "Show Content": "Mostrar o Conteúdo", + "Show Recovery Codes": "Mostrar Códigos de Recuperação", + "Showing": "Mostrando", + "Sierra Leone": "Serra Leoa", + "Signed in as": "Logado como", + "Singapore": "Singapura", + "Sint Maarten (Dutch part)": "Ilha de São Martinho (Parte holandesa)", + "Slovakia": "Eslováquia", + "Slovenia": "Eslovênia", + "Soft Deleted": "Excluído temporariamente", + "Solomon Islands": "Ilhas Salomão", + "Somalia": "Somália", + "Something went wrong.": "Algo errado ocorreu.", + "Sorry! You are not authorized to perform this action.": "Desculpe! Você não está autorizado a realizar esta ação.", + "Sorry, your session has expired.": "Desculpe, a sua sessão expirou.", + "South Africa": "África do Sul", + "South Georgia And Sandwich Isl.": "Ilhas Geórgia do Sul e Sandwich do Sul", + "South Georgia and the South Sandwich Islands": "Ilhas Geórgia do Sul e Sandwich do Sul", + "South Sudan": "Sudão do Sul", + "Spain": "Espanha", + "Sri Lanka": "Sri Lanka", + "Standalone Actions": "Ações independentes", + "Start Polling": "Iniciar a Votação", + "Start polling": "Iniciar a votação", + "State / County": "Estado / Condado", + "Stop Impersonating": "Parar de personificar", + "Stop Polling": "Parar a Votação", + "Stop polling": "Parar a votação", + "Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.": "Guarde estes códigos de recuperação em um gerenciador de senhas seguro. Eles podem ser usados para recuperar o acesso à sua conta se o dispositivo de autenticação em dois fatores for perdido.", + "Subscribe": "Assinar", + "Subscription Information": "Informações de Assinatura", + "Subscription Pending": "Assinatura Pendente", + "Sudan": "Sudão", + "Suriname": "Suriname", + "Svalbard And Jan Mayen": "Svalbard e Jan Mayen", + "Svalbard and Jan Mayen": "Svalbard e Jan Mayen", + "Swaziland": "Suazilândia", + "Sweden": "Suécia", + "Switch Teams": "Mudar de Time", + "Switzerland": "Suíça", + "Syrian Arab Republic": "República Árabe Síria", + "System": "Sistema", + "Taiwan": "Taiwan", + "Taiwan, Province of China": "Taiwan, Província chinesa", + "Tajikistan": "Tajiquistão", + "Tanzania": "Tanzânia", + "Tanzania, United Republic of": "República Unida da Tanzânia", + "TAX": "IMPOSTO", + "Team Details": "Detalhes do Time", + "Team Invitation": "Convite de Time", + "Team Members": "Membros do Time", + "Team Name": "Nome do Time", + "Team Owner": "Dono do Time", + "Team Settings": "Configurações do Time", + "Terms of Service": "Termos de Serviço", + "Thailand": "Tailândia", + "Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn't receive the email, we will gladly send you another.": "Obrigado por se registar! Antes de começar, confirme o seu endereço de e-mail clicando no link presente no e-mail que acabamos de te enviar? Caso não tenha recebido o email, teremos o maior prazer em reenviar-lhe outro.", + "Thanks for your continued support. We've attached a copy of your invoice for your records. Please let us know if you have any questions or concerns.": "Obrigado por seu apoio contínuo. Anexamos uma cópia de sua fatura para seus registros. Por favor, deixe-nos saber se você tiver alguma dúvida ou preocupação.", + "Thanks,": "Obrigado,", + "The :attribute must be a valid role.": ":Attribute deve ser um papel válido.", + "The :attribute must be at least :length characters and contain at least one number.": "O campo :attribute deve possuir no mínimo :length caracteres e conter pelo menos um número.", + "The :attribute must be at least :length characters and contain at least one special character and one number.": "Os :attribute devem ter, pelo menos, :length caracteres e conter, pelo menos, um carácter especial e um número.", + "The :attribute must be at least :length characters and contain at least one special character.": "O campo :attribute deve possuir no mínimo :length caracteres e conter pelo menos um caractere especial.", + "The :attribute must be at least :length characters and contain at least one uppercase character and one number.": "O campo :attribute deve possuir no mínimo :length caracteres e conter pelo menos uma letra maiúscula e um número.", + "The :attribute must be at least :length characters and contain at least one uppercase character and one special character.": "O campo :attribute deve possuir no mínimo :length caracteres e conter pelo menos uma letra maiúscula e um caractere especial.", + "The :attribute must be at least :length characters and contain at least one uppercase character, one number, and one special character.": "O campo :attribute deve possuir no mínimo :length caracteres e conter pelo menos uma letra maiúscula, um número, e um caractere especial.", + "The :attribute must be at least :length characters and contain at least one uppercase character.": "O campo :attribute deve possuir no mínimo :length caracteres e conter pelo menos uma letra maiúscula.", + "The :attribute must be at least :length characters.": "O campo :attribute deve possuir no mínimo :length caracteres.", + "The :attribute must contain at least one letter.": "O campo :attribute deve conter pelo menos uma letra", + "The :attribute must contain at least one number.": "O campo :attribute deve conter pelo menos um número.", + "The :attribute must contain at least one symbol.": "O campo :attribute deve conter pelo menos um símbolo.", + "The :attribute must contain at least one uppercase and one lowercase letter.": "O campo :attribute deve conter pelo menos uma letra maiúscula e uma minúscula.", + "The :resource was created!": "O :resource foi criado!", + "The :resource was deleted!": "O :resource foi excluido!", + "The :resource was restored!": "O :resource foi restaurado!", + "The :resource was updated!": "O :resource foi atualizado!", + "The action was executed successfully.": "A ação foi executada com sucesso.", + "The default payment method cannot be removed.": "O método de pagamento padrão não pode ser removido.", + "The file was deleted!": "O arquivo foi excluido!", + "The given :attribute has appeared in a data leak. Please choose a different :attribute.": "O :attribute informado apareceu em um vazamento de dados. Por favor escolha uma :attribute diferente.", + "The given data was invalid.": "Os dados fornecidos eram inválidos.", + "The government won't let us show you what's behind these doors": "O governo não nos deixa mostrar-lhe o que está atrás destas portas.", + "The HasOne relationship has already been filled.": "A relação HasOne já foi preenchida.", + "The image could not be loaded": "A imagem não pôde ser carregada", + "The image could not be loaded.": "A imagem não pôde ser carregada.", + "The invoice emails must be valid email addresses.": "Os e-mails da fatura devem ser endereços de e-mail válidos.", + "The password is incorrect.": "A senha está incorreta.", + "The provided coupon code is invalid.": "O código de cupom fornecido é inválido.", + "The provided password does not match your current password.": "A senha informada não corresponde à sua senha atual.", + "The provided password was incorrect.": "A senha informada está incorreta.", + "The provided two factor authentication code was invalid.": "O código de autenticação em dois fatores informado não é válido.", + "The provided two factor recovery code was invalid.": "O código de recuperação de dois fatores fornecido era inválido.", + "The provided VAT number is invalid.": "O número de VAT fornecido é inválido.", + "The resource was attached!": "O recurso foi anexado!", + "The resource was prevented from being saved!": "O recurso foi impedido de ser salvo!", + "The resource was updated!": "O recurso foi atualizado!", + "The response is not a streamed response.": "A resposta não é uma resposta transmitida.", + "The response is not a view.": "A resposta não é uma visualização.", + "The selected country is invalid.": "O país selecionado é inválido.", + "The selected plan is invalid.": "O plano selecionado é inválido.", + "The selected resources have been :action!": "Os recursos selecionados foram :action!", + "The team's name and owner information.": "Nome do time e informações do dono.", + "There are no available options for this resource.": "Não existem opções disponíveis para este recurso.", + "There are no fields to display.": "Não há campos para exibir.", + "There are no new notifications.": "Não há novas notificações.", + "There was a problem executing the action.": "Houve um problema em executar a ação.", + "There was a problem fetching the resource.": "Houve um problema ao buscar o recurso.", + "There was a problem submitting the form.": "Houve um problema ao enviar o formulário.", + "These people have been invited to your team and have been sent an invitation email. They may join the team by accepting the email invitation.": "Estas pessoas foram convidadas para a sua equipa e receberam um convite por e-mail. Eles podem se juntar ao time aceitando o convite por e-mail.", + "This account does not have an active subscription.": "Esta conta não tem uma assinatura ativa.", + "This action is unauthorized.": "Esta ação não é autorizada.", + "This copy of Nova is unlicensed.": "Esta cópia do Nova não é licenciada.", + "This coupon code can only be used by new customers.": "Este código de cupom só pode ser usado por novos clientes.", + "This device": "Este dispositivo", + "This file field is read-only.": "Este campo de arquivo é apenas para leitura.", + "This invoice is no longer open.": "Essa fatura não está mais aberta.", + "This is a secure area of the application. Please confirm your password before continuing.": "Esta é uma área segura da aplicação. Por favor, confirme a sua senha antes de continuar.", + "This password does not match our records.": "Esta senha não corresponde aos nossos registros.", + "This password reset link will expire in :count minutes.": "O link de redefinição de senha irá expirar em :count minutos.", + "This payment was initiated, but the funds have not been received yet. This can take up to 14 days.": "Esse pagamento foi iniciado, mas os fundos ainda não foram recebidos. Isso pode levar até 14 dias.", + "This resource no longer exists": "Este recurso já não existe", + "This subscription has expired and cannot be resumed. Please create a new subscription.": "Esta assinatura expirou e não pode ser retomada. Por favor, crie uma nova assinatura.", + "This user already belongs to the team.": "Este usuário já pertence a um time.", + "This user has already been invited to the team.": "Este usuário já foi convidado para o time.", + "Timor-Leste": "Timor-Leste", + "to": "até", + "To": "Até", + "To finish enabling two factor authentication, scan the following QR code using your phone's authenticator application or enter the setup key and provide the generated OTP code.": "Para concluir a ativação da autenticação de dois fatores, digitalize o código QR a seguir usando o aplicativo autenticador do seu telefone ou insira a chave de configuração e forneça o código OTP gerado.", + "Today": "Hoje", + "Toggle navigation": "Alternar navegação", + "Togo": "Togo", + "Tokelau": "Toquelau", + "Token Name": "Nome do Token", + "Tonga": "Tonga", + "Too Many Requests": "Muitas solicitações", + "total": "total", + "Total:": "Total:", + "Trashed": "Destruído", + "Trinidad And Tobago": "Trindade e Tobago", + "Trinidad and Tobago": "Trindade e Tobago", + "Tunisia": "Tunísia", + "Turkey": "Turquia", + "Turkmenistan": "Turcomenistão", + "Turks And Caicos Islands": "Ilhas Turcas e Caicos", + "Turks and Caicos Islands": "Ilhas Turcas e Caicos", + "Tuvalu": "Tuvalu", + "Two Factor Authentication": "Autenticação em dois fatores", + "Two factor authentication is now enabled. Scan the following QR code using your phone's authenticator application or enter the setup key.": "A autenticação de dois fatores agora está habilitada. Digitalize o código QR a seguir usando o aplicativo autenticador do seu telefone ou digite a chave de configuração.", + "Type": "Tipo", + "Uganda": "Uganda", + "Ukraine": "Ucrânia", + "Unauthorized": "Não autorizado", + "United Arab Emirates": "Emirados Árabes Unidos", + "United Kingdom": "Reino Unido", + "United States": "Estados Unidos", + "United States Minor Outlying Islands": "Ilhas Menores Distantes dos Estados Unidos", + "United States Outlying Islands": "Ilhas Distantes dos Estados Unidos", + "Unknown": "Desconhecido", + "Unpaid": "Não Pago", + "Update": "Atualizar", + "Update & Continue Editing": "Atualizar e Continuar a Edição", + "Update :resource": "Atualizar :resource", + "Update :resource: :title": "Atualizar :resource: :title", + "Update attached :resource: :title": "Atualizar anexo :resource: :title", + "Update Password": "Atualizar senha", + "Update Payment Information": "Atualizar informações de pagamento", + "Update Payment Method": "Atualizar forma de pagamento", + "Update your account's profile information and email address.": "Atualize as informações do seu perfil e endereço de e-mail.", + "Uploading": "Enviando", + "Uploading files... (:current/:total)": "Carregando arquivos... (:current/:total)", + "Uruguay": "Uruguai", + "Use a recovery code": "Use um código de recuperação", + "Use an authentication code": "Use um código de autenticação", + "User Actions": "Ações do usuário", + "User Security": "Segurança do usuário", + "Username": "Nome de usuário", + "Uzbekistan": "Uzbequistão", + "Value": "Valor", + "Vanuatu": "Vanuatu", + "VAT Number": "Numero do VAT", + "Venezuela": "Venezuela", + "Venezuela, Bolivarian Republic of": "República Bolivariana da Venezuela", + "Verify Email Address": "Verifique o endereço de e-mail", + "Verify Your Email Address": "Verifique seu endereço de e-mail", + "Viet Nam": "Vietnam", + "View": "Visualizar", + "Virgin Islands, British": "Ilhas Virgens Britânicas", + "Virgin Islands, U.S.": "Ilhas Virgens Americanas", + "Wallis And Futuna": "Wallis e Futuna", + "Wallis and Futuna": "Wallis e Futuna", + "We are processing your subscription. Once the subscription has successfully processed, this page will update automatically. Typically, this process should only take a few seconds.": "Estamos processando sua assinatura. Assim que a assinatura for processada com sucesso, esta página será atualizada automaticamente. Normalmente, esse processo deve levar apenas alguns segundos.", + "We are unable to process your payment. Please contact customer support.": "Não podemos processar seu pagamento. Entre em contato com o suporte ao cliente.", + "We have emailed your password reset link!": "Enviamos o link de redefinição de senha por e-mail!", + "We were unable to find a registered user with this email address.": "Não pudemos encontrar um usuário com esse endereço de e-mail.", + "We will send an invoice download link to the email addresses that you specify below. You may separate multiple email addresses using commas.": "Enviaremos um link para download de fatura para os endereços de e-mail que você especificar abaixo. Você pode separar vários endereços de e-mail usando vírgulas.", + "We're lost in space. The page you were trying to view does not exist.": "Estamos perdidos no espaço. A página que você estava tentando ver não existe.", + "Welcome Back!": "Bem-vindo de Volta!", + "Western Sahara": "Saara Ocidental", + "When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone's Google Authenticator application.": "Quando a autenticação em dois fatores está ativa, um token seguro e aleatório será solicitado durante a autenticação. Você deve obter este token em seu aplicativo Google Authenticator em seu telefone.", + "Whoops": "Ops", + "Whoops!": "Ops!", + "Whoops! Something went wrong.": "Ops! Alguma coisa deu errado.", + "With Trashed": "Com Destruídos", + "Write": "Escrever", + "Year To Date": "Ano até a data", + "Yearly": "Anual", + "Yemen": "Iêmen", + "Yes": "Sim", + "You are already subscribed.": "Você já esta inscrito.", + "You are currently within your free trial period. Your trial will expire on :date.": "Você atualmente está no período de teste. Seu teste irá expirar em :date.", + "You are currently within your free trial period. Your trial will expire on :date. Starting a new subscription will end your trial.": "Você atualmente está no período de teste. Seu teste irá expirar em :date. Iniciar uma nova assinatura encerrará sua avaliação.", + "You are logged in!": "Você está logado!", + "You are receiving this email because we received a password reset request for your account.": "Você recebeu esse e-mail porque foi solicitado uma redefinição de senha na sua conta.", + "You have been invited to join the :team team!": "Foi convidado para se juntar ao time :team!", + "You have enabled two factor authentication.": "Você ativou a autenticação em dois fatores.", + "You have not enabled two factor authentication.": "Você não ativou a autenticação em dois fatores.", + "You have some unpaid invoices. After updating your default payment method, you may retry the payments via the invoice list below.": "Você tem algumas faturas não pagas. Depois de atualizar seu método de pagamento padrão, você pode tentar novamente os pagamentos por meio da lista de faturas abaixo.", + "You may accept this invitation by clicking the button below:": "Você pode aceitar o convite clicando no botão abaixo:", + "You may cancel your subscription at any time. Once your subscription has been cancelled, you will have the option to resume the subscription until the end of your current billing cycle.": "Você pode cancelar sua assinatura a qualquer momento. Assim que sua assinatura for cancelada, você terá a opção de retomá-la até o final do seu ciclo de faturamento atual.", + "You may delete any of your existing tokens if they are no longer needed.": "Você pode excluir seus tokens existentes se eles não forem mais necessários.", + "You may not delete your personal team.": "Você não pode excluir o seu time pessoal.", + "You may not leave a team that you created.": "Você não pode sair de um time que você criou.", + "You will receive an invoice and payment link via email for each billing period.": "Você receberá uma fatura e um link de pagamento por e-mail para cada período de cobrança.", + "You're logged in!": "Você está logado!", + "Your :invoiceName invoice is now available!": "Sua fatura :invoiceName já está disponível!", + "Your billing address is :address :address2 :postal_code :city :state :country": "Seu endereço de cobrança é :address :address2 :postal_code :city :state :country", + "Your card was declined. Please contact your card issuer for more information.": "Seu cartão foi recusado. Entre em contato com o emissor do cartão para obter mais informações.", + "Your current payment method is a credit card ending in :lastFour that expires on :expiration.": "Seu método de pagamento atual é um cartão de crédito com final :lastFour que expira em :expiration.", + "Your email address is unverified.": "Seu endereço de e-mail não foi verificado.", + "Your last payment of :amount failed. Please update your payment method to retry the failed payment.": "Seu último pagamento de :amount falhou. Atualize sua forma de pagamento para tentar novamente o pagamento com falha.", + "Your last payment of :amount on :date failed. Please update your payment method to retry the failed payment.": "Seu último pagamento de :amount em :date falhou. Atualize sua forma de pagamento para tentar novamente o pagamento com falha.", + "Your next payment of :amount will be processed on :date.": "Seu próximo pagamento de :amount será em :date.", + "Your payment method has been added successfully.": "Sua forma de pagamento foi adicionada com sucesso.", + "Your payment method will be charged automatically for each billing period.": "Seu método de pagamento será cobrado automaticamente para cada período de cobrança.", + "Your registered VAT Number is :vatNumber.": "Seu número de IVA registrado é :vatNumber.", + "Your subscription has been started successfully.": "Sua assinatura foi iniciada com sucesso.", + "Your subscription has been successfully cancelled.": "Sua assinatura foi cancelada com sucesso.", + "Your subscription has been successfully cancelled. You will still have access until the end of your billing period.": "Sua assinatura foi cancelada. Seu acesso continuará liberado até o encerramento do seu ciclo de cobrança.", + "Your subscription was successfully resumed.": "Sua assinatura foi retomada com sucesso.", + "Your subscription was successfully updated.": "Sua assinatura foi atualizada com sucesso.", + "Zambia": "Zâmbia", + "Zimbabwe": "Zimbábue", + "Zip / Postal Code": "CEP / Código Postal", + "Åland Islands": "Ilhas Aland", + "A reset link will be sent if the account exists.": "Um link de redefinição será enviado se a conta existir.", + "A Timeout Occurred": "Ocorreu Um Tempo Limite", + "Accept": "Aceitar", + "Accepted": "Aceito", + "ACTIVE": "ATIVO", + "Active": "Ativo", + "Add :name": "Adicione :name", + "Admin": "Administrador", + "Agree": "Concordar", + "Already Reported": "Já Reportado", + "ANALISYS": "ANÁLISE", + "APPROVED": "APROVADO", + "Archive": "Arquivo", + "Assign": "Atribuir", + "Associate": "Associado", + "Bad Gateway": "Gateway Inválido", + "Bad Request": "Requisição Inválida", + "Bandwidth Limit Exceeded": "Limite de Banda Excedido", + "BLOCKED": "BLOQUEADO", + "Browse": "Navegar", + "CANCELED": "CANCELADO", + "Choose :name": "Escolha :name", + "Choose Image": "Escolha a imagem", + "Click to copy": "Clique para copiar", + "Client Closed Request": "Solicitação fechada do cliente", + "Collapse": "Colapso", + "Collapse All": "Recolher todos", + "Comment": "Comente", + "Conflict": "Conflito", + "Connect": "Conectar", + "Connection Closed Without Response": "Conexão Fechada Sem Resposta", + "Connection Timed Out": "Tempo Limite Da Conexão", + "Continue": "Continuar", + "Create :name": "Crie :name", + "Created": "Criado", + "Delete :name": "Excluir :name", + "Discard": "Descartar", + "Done": "Feito", + "Don't have an account?": "Não tem uma conta?", + "Down": "Abaixo", + "Duplicate": "Duplicado", + "Duplicate :name": "Duplicado: nome", + "Edit :name": "Editar :name", + "Expand": "Expandir", + "Expand All": "Expandir todos", + "Expectation Failed": "Falha Na Expectativa", + "Explanation": "Explicação", + "Export": "Exportar", + "Export :name": "Exportar :name", + "Failed Dependency": "Dependência Com Falha", + "File": "Arquivo", + "Files": "arquivos", + "Found": "Encontrado", + "Gateway Timeout": "Tempo Limite Do Gateway", + "Gone": "Perdido", + "Hide": "Esconder", + "Hide :name": "Ocultar :name", + "Home": "Lar", + "HTTP Version Not Supported": "Versão HTTP Não Suportada", + "I'm a teapot": "Eu Sou Um Bule De Chá", + "IM Used": "Estou Usando", + "Image": "Imagem", + "Impersonation": "Representação", + "Import": "Importar", + "Import :name": "Importar :name", + "INACTIVE": "INATIVO", + "Inactive": "Inativo", + "Insufficient Storage": "Armazenamento Insuficiente", + "Internal Server Error": "Erro Interno Do Servidor", + "Introduction": "Introdução", + "Invalid SSL Certificate": "Certificado SSL Inválido", + "Length Required": "Comprimento Necessário", + "Like": "Como", + "Load": "Carregar", + "Localize": "Localizar", + "Locked": "Fechado", + "Loop Detected": "Loop Detectado", + "Maintenance Mode": "Modo De Manutenção", + "Method Not Allowed": "Método Não Permitido", + "Misdirected Request": "Solicitação Mal Direcionada", + "Moved Permanently": "Movido Permanentemente", + "Multi-Status": "Vários status", + "Multiple Choices": "Múltiplas Escolhas", + "Network Authentication Required": "Autenticação De Rede Necessária", + "Network Connect Timeout Error": "Erro de tempo limite de conexão de rede", + "Network Read Timeout Error": "Erro de tempo limite de leitura da rede", + "New :name": "Novo :name", + "No Content": "Nenhum Conteúdo", + "Non-Authoritative Information": "Informações Não Autorizadas", + "Not Acceptable": "Não Aceitável", + "Not Extended": "Não Estendido", + "Not Implemented": "Não Implementado", + "Not Modified": "Não Modificado", + "Open": "Abrir", + "Open in a current window": "Abrir em uma janela atual", + "Open in a new window": "Abrir em uma nova janela", + "Open in a parent frame": "Abrir em um quadro pai", + "Open in the topmost frame": "Abra no quadro superior", + "Open on the website": "Aberto no site", + "Origin Is Unreachable": "Origem É Inacessível", + "Partial Content": "Contéudo Parcial", + "Payload Too Large": "Carga Muito Grande", + "Permanent Redirect": "Redirecionamento Permanente", + "Precondition Failed": "Pré-Condição Falhou", + "Precondition Required": "Pré-Condição Necessária", + "Price": "Preço", + "Processing": "Processamento", + "Proxy Authentication Required": "Autenticação De Proxy Necessária", + "Railgun Error": "Erro do Canhão Elétrico", + "Range Not Satisfiable": "Faixa Não Satisfatória", + "Record": "Registro", + "Request Header Fields Too Large": "Campos De Cabeçalho De Solicitação Muito Grandes", + "Request Timeout": "Tempo Limite De Requisição", + "Reset Content": "Redefinir Conteúdo", + "Restore :name": "Restaurar :name", + "Retry With": "Repetir Com", + "Save & Close": "Salvar fechar", + "Save & Return": "Salvar e retornar", + "Save :name": "Economize :name", + "Search :name": "Pesquisar :name", + "See Other": "Ver Outros", + "Select All": "Selecionar tudo", + "Send": "Enviar", + "Session Has Expired": "Sessão Expirou", + "Settings": "Configurações", + "Show": "Mostrar", + "Show :name": "Mostrar :name", + "Show All": "Mostre tudo", + "Sign In": "Entrar", + "Sign up": "Inscrever-se", + "Solve": "Resolver", + "SSL Handshake Failed": "Falha No Handshake SSL", + "Start": "Começar", + "status": "Estado", + "Stop": "Parar", + "Submit": "Enviar", + "Switch": "Trocar", + "Switch To Role": "Mudar para função", + "Switching Protocols": "Mudando Protocolos", + "Tag": "Marcação", + "Tags": "Tag", + "Temporary Redirect": "Redirecionamento Temporário", + "Too Early": "Muito cedo", + "Translate": "Traduzir", + "Translate It": "Traduza isso", + "UNAPPROVED": "NÃO APROVADO", + "Unavailable For Legal Reasons": "Indisponível Por Motivos Legais", + "Unknown Error": "Erro Desconhecido", + "Unpack": "Descompacte", + "Unprocessable Entity": "Entidade Improcessável", + "Unsubscribe": "Cancelar subscrição", + "Unsupported Media Type": "Tipo De Mídia Não Suportado", + "Up": "Acima", + "Update :name": "Atualização :name", + "Upgrade Required": "Atualização Necessária", + "URI Too Long": "URI Muito Grande", + "Use Proxy": "Usar proxy", + "User": "Do utilizador", + "Variant Also Negotiates": "Variante Também Negocia", + "View :name": "Ver :name", + "Web Server is Down": "Servidor Web Está Inativo", + "Nickname": "Apelido", + "Status": "Estado", + "Roles": "Funções", + "Situation": "Situação", + "Updated": "Alterado", + "Deleted": "Excluído", + "Show deleted only": "Mostrar apenas excluídos", + "Show active only": "Mostrar apenas ativos", + "Show all": "Mostrar tudo", + "Search by": "Pesquisar por", + "Enter part or all of the text to search": "Digite parte ou todo o texto para pesquisar", + "Confirm Deletion": "Confirmar Exclusão", + "Are you sure you want to delete": "Você tem certeza de que deseja excluir", + "Confirm Restore": "Confirmar Restauração", + "Are you sure you want to restore": "Você tem certeza de que deseja restaurar", + "Are you sure you want to detach": "Você tem certeza de que deseja desanexar", + "Are you sure you want to attach": "Você tem certeza de que deseja anexar", + "Are you sure you want to assign": "Você tem certeza de que deseja atribuir", + "Confirm Permanent Deletion": "Confirmar Exclusão Permanente", + "Are you sure you want to permanently delete": "Você tem certeza de que deseja excluir permanentemente" +} diff --git a/lang/pt_BR/actions.php b/lang/pt_BR/actions.php new file mode 100644 index 00000000..467bd14f --- /dev/null +++ b/lang/pt_BR/actions.php @@ -0,0 +1,120 @@ + 'Aceitar', + 'action' => 'Ação', + 'actions' => 'Ações', + 'add' => 'Adicionar', + 'admin' => 'Administrador', + 'agree' => 'Concordar', + 'archive' => 'Arquivo', + 'assign' => 'Atribuir', + 'associate' => 'Associado', + 'attach' => 'Anexar', + 'browse' => 'Navegar', + 'cancel' => 'Cancelar', + 'choose' => 'Escolher', + 'choose_file' => 'Escolher arquivo', + 'choose_image' => 'Escolha a imagem', + 'click_to_copy' => 'Clique para copiar', + 'close' => 'Fechar', + 'collapse' => 'Colapso', + 'collapse_all' => 'Recolher todos', + 'comment' => 'Comente', + 'confirm' => 'Confirme', + 'connect' => 'Conectar', + 'create' => 'Criar', + 'delete' => 'Excluir', + 'delete_permanently' => 'Excluir Permanente', + 'detach' => 'Desanexar', + 'details' => 'Detalhes', + 'disable' => 'Desativar', + 'discard' => 'Descartar', + 'done' => 'Feito', + 'down' => 'Abaixo', + 'duplicate' => 'Duplicado', + 'edit' => 'Editar', + 'enable' => 'Habilitar', + 'expand' => 'Expandir', + 'expand_all' => 'Expandir todos', + 'explanation' => 'Explicação', + 'export' => 'Exportar', + 'file' => 'Arquivo', + 'files' => 'arquivos', + 'go_home' => 'Ir para casa', + 'hide' => 'Esconder', + 'home' => 'Lar', + 'image' => 'Imagem', + 'impersonate' => 'Personificar', + 'impersonation' => 'Representação', + 'import' => 'Importar', + 'introduction' => 'Introdução', + 'like' => 'Como', + 'load' => 'Carregar', + 'localize' => 'Localizar', + 'log_in' => 'Conecte-se', + 'log_out' => 'Sair', + 'named' => [ + 'add' => 'Adicione :name', + 'choose' => 'Escolha :name', + 'create' => 'Crie :name', + 'delete' => 'Excluir :name', + 'duplicate' => 'Duplicado: nome', + 'edit' => 'Editar :name', + 'export' => 'Exportar :name', + 'hide' => 'Ocultar :name', + 'import' => 'Importar :name', + 'new' => 'Novo :name', + 'restore' => 'Restaurar :name', + 'save' => 'Economize :name', + 'search' => 'Pesquisar :name', + 'show' => 'Mostrar :name', + 'update' => 'Atualização :name', + 'view' => 'Ver :name', + ], + 'new' => 'Novo', + 'no' => 'Não', + 'open' => 'Abrir', + 'open_website' => 'Aberto no site', + 'preview' => 'Visualização', + 'price' => 'Preço', + 'record' => 'Registro', + 'restore' => 'Restaurar', + 'save' => 'Salvar', + 'save_and_close' => 'Salvar fechar', + 'save_and_return' => 'Salvar e retornar', + 'search' => 'Procurar', + 'select' => 'Selecione', + 'select_all' => 'Selecionar tudo', + 'send' => 'Enviar', + 'settings' => 'Configurações', + 'show' => 'Mostrar', + 'show_all' => 'Mostre tudo', + 'sign_in' => 'Entrar', + 'solve' => 'Resolver', + 'start' => 'Começar', + 'stop' => 'Parar', + 'submit' => 'Enviar', + 'subscribe' => 'Se inscrever', + 'switch' => 'Trocar', + 'switch_to_role' => 'Mudar para função', + 'tag' => 'Marcação', + 'tags' => 'Tag', + 'target_link' => [ + 'blank' => 'Abrir em uma nova janela', + 'parent' => 'Abrir em um quadro pai', + 'self' => 'Abrir em uma janela atual', + 'top' => 'Abra no quadro superior', + ], + 'translate' => 'Traduzir', + 'translate_it' => 'Traduza isso', + 'unpack' => 'Descompacte', + 'unsubscribe' => 'Cancelar subscrição', + 'up' => 'Acima', + 'update' => 'Atualizar', + 'user' => 'Do utilizador', + 'view' => 'Visualizar', + 'yes' => 'Sim', +]; diff --git a/lang/pt_BR/auth.php b/lang/pt_BR/auth.php new file mode 100644 index 00000000..c0dcdd79 --- /dev/null +++ b/lang/pt_BR/auth.php @@ -0,0 +1,9 @@ + 'Credenciais informadas não correspondem com nossos registros.', + 'password' => 'A senha está incorreta.', + 'throttle' => 'Você realizou muitas tentativas de login. Por favor, tente novamente em :seconds segundos.', +]; diff --git a/lang/pt_BR/http-statuses.php b/lang/pt_BR/http-statuses.php new file mode 100644 index 00000000..73200696 --- /dev/null +++ b/lang/pt_BR/http-statuses.php @@ -0,0 +1,84 @@ + 'Erro Desconhecido', + '100' => 'Continuar', + '101' => 'Mudando Protocolos', + '102' => 'Processamento', + '200' => 'OK', + '201' => 'Criado', + '202' => 'Aceito', + '203' => 'Informações Não Autorizadas', + '204' => 'Nenhum Conteúdo', + '205' => 'Redefinir Conteúdo', + '206' => 'Contéudo Parcial', + '207' => 'Vários status', + '208' => 'Já Reportado', + '226' => 'Estou Usando', + '300' => 'Múltiplas Escolhas', + '301' => 'Movido Permanentemente', + '302' => 'Encontrado', + '303' => 'Ver Outros', + '304' => 'Não Modificado', + '305' => 'Usar proxy', + '307' => 'Redirecionamento Temporário', + '308' => 'Redirecionamento Permanente', + '400' => 'Requisição Inválida', + '401' => 'Não Autorizado', + '402' => 'Pagamento Requerido', + '403' => 'Proibido', + '404' => 'Página Não Encontrada', + '405' => 'Método Não Permitido', + '406' => 'Não Aceitável', + '407' => 'Autenticação De Proxy Necessária', + '408' => 'Tempo Limite De Requisição', + '409' => 'Conflito', + '410' => 'Perdido', + '411' => 'Comprimento Necessário', + '412' => 'Pré-Condição Falhou', + '413' => 'Carga Muito Grande', + '414' => 'URI Muito Grande', + '415' => 'Tipo De Mídia Não Suportado', + '416' => 'Faixa Não Satisfatória', + '417' => 'Falha Na Expectativa', + '418' => 'Eu Sou Um Bule De Chá', + '419' => 'Sessão Expirou', + '421' => 'Solicitação Mal Direcionada', + '422' => 'Entidade Improcessável', + '423' => 'Fechado', + '424' => 'Dependência Com Falha', + '425' => 'Muito cedo', + '426' => 'Atualização Necessária', + '428' => 'Pré-Condição Necessária', + '429' => 'Muitas Requisições', + '431' => 'Campos De Cabeçalho De Solicitação Muito Grandes', + '444' => 'Conexão Fechada Sem Resposta', + '449' => 'Repetir Com', + '451' => 'Indisponível Por Motivos Legais', + '499' => 'Solicitação fechada do cliente', + '500' => 'Erro Interno Do Servidor', + '501' => 'Não Implementado', + '502' => 'Gateway Inválido', + '503' => 'Modo De Manutenção', + '504' => 'Tempo Limite Do Gateway', + '505' => 'Versão HTTP Não Suportada', + '506' => 'Variante Também Negocia', + '507' => 'Armazenamento Insuficiente', + '508' => 'Loop Detectado', + '509' => 'Limite de Banda Excedido', + '510' => 'Não Estendido', + '511' => 'Autenticação De Rede Necessária', + '520' => 'Erro Desconhecido', + '521' => 'Servidor Web Está Inativo', + '522' => 'Tempo Limite Da Conexão', + '523' => 'Origem É Inacessível', + '524' => 'Ocorreu Um Tempo Limite', + '525' => 'Falha No Handshake SSL', + '526' => 'Certificado SSL Inválido', + '527' => 'Erro do Canhão Elétrico', + '598' => 'Erro de tempo limite de leitura da rede', + '599' => 'Erro de tempo limite de conexão de rede', + 'unknownError' => 'Erro Desconhecido', +]; diff --git a/lang/pt_BR/pagination.php b/lang/pt_BR/pagination.php new file mode 100644 index 00000000..729322ba --- /dev/null +++ b/lang/pt_BR/pagination.php @@ -0,0 +1,8 @@ + '»', + 'previous' => '« ', +]; diff --git a/lang/pt_BR/passwords.php b/lang/pt_BR/passwords.php new file mode 100644 index 00000000..c62873d4 --- /dev/null +++ b/lang/pt_BR/passwords.php @@ -0,0 +1,11 @@ + 'Sua senha foi redefinida!', + 'sent' => 'Enviamos um link para redefinir a sua senha por e-mail.', + 'throttled' => 'Por favor espere antes de tentar novamente.', + 'token' => 'Esse código de redefinição de senha é inválido.', + 'user' => 'Não conseguimos encontrar nenhum usuário com o endereço de e-mail informado.', +]; diff --git a/lang/pt_BR/validation.php b/lang/pt_BR/validation.php new file mode 100644 index 00000000..bf83cbe8 --- /dev/null +++ b/lang/pt_BR/validation.php @@ -0,0 +1,286 @@ + 'O campo :attribute deve ser aceito.', + 'accepted_if' => 'O :attribute deve ser aceito quando :other for :value.', + 'active_url' => 'O campo :attribute deve conter uma URL válida.', + 'after' => 'O campo :attribute deve conter uma data posterior a :date.', + 'after_or_equal' => 'O campo :attribute deve conter uma data superior ou igual a :date.', + 'alpha' => 'O campo :attribute deve conter apenas letras.', + 'alpha_dash' => 'O campo :attribute deve conter apenas letras, números e traços.', + 'alpha_num' => 'O campo :attribute deve conter apenas letras e números .', + 'any_of' => 'O campo :attribute é inválido.', + 'array' => 'O campo :attribute deve conter um array.', + 'ascii' => 'O :attribute deve conter apenas caracteres alfanuméricos de byte único e símbolos.', + 'before' => 'O campo :attribute deve conter uma data anterior a :date.', + 'before_or_equal' => 'O campo :attribute deve conter uma data inferior ou igual a :date.', + 'between' => [ + 'array' => 'O campo :attribute deve conter de :min a :max itens.', + 'file' => 'O campo :attribute deve conter um arquivo de :min a :max kilobytes.', + 'numeric' => 'O campo :attribute deve conter um número entre :min e :max.', + 'string' => 'O campo :attribute deve conter entre :min a :max caracteres.', + ], + 'boolean' => 'O campo :attribute deve conter o valor verdadeiro ou falso.', + 'can' => 'O campo :attribute contém um valor não autorizado.', + 'confirmed' => 'A confirmação para o campo :attribute não coincide.', + 'contains' => 'O campo :attribute não contém um valor obrigatório.', + 'current_password' => 'A senha está incorreta.', + 'date' => 'O campo :attribute não contém uma data válida.', + 'date_equals' => 'O campo :attribute deve ser uma data igual a :date.', + 'date_format' => 'A data informada para o campo :attribute não respeita o formato :format.', + 'decimal' => 'O :attribute deve ter :decimal casas decimais.', + 'declined' => 'O :attribute deve ser recusado.', + 'declined_if' => 'O :attribute deve ser recusado quando :other for :value.', + 'different' => 'Os campos :attribute e :other devem conter valores diferentes.', + 'digits' => 'O campo :attribute deve conter :digits dígitos.', + 'digits_between' => 'O campo :attribute deve conter entre :min a :max dígitos.', + 'dimensions' => 'O valor informado para o campo :attribute não é uma dimensão de imagem válida.', + 'distinct' => 'O campo :attribute contém um valor duplicado.', + 'doesnt_end_with' => 'O :attribute não pode terminar com um dos seguintes: :values.', + 'doesnt_start_with' => 'O :attribute não pode começar com um dos seguintes: :values.', + 'email' => 'O campo :attribute não contém um endereço de email válido.', + 'ends_with' => 'O campo :attribute deve terminar com um dos seguintes valores: :values', + 'enum' => 'O :attribute selecionado é inválido.', + 'exists' => 'O valor selecionado para o campo :attribute é inválido.', + 'extensions' => 'O campo :attribute deve ter uma das seguintes extensões: :values.', + 'file' => 'O campo :attribute deve conter um arquivo.', + 'filled' => 'O campo :attribute é obrigatório.', + 'gt' => [ + 'array' => 'O campo :attribute deve ter mais que :value itens.', + 'file' => 'O arquivo :attribute deve ser maior que :value kilobytes.', + 'numeric' => 'O campo :attribute deve ser maior que :value.', + 'string' => 'O campo :attribute deve ser maior que :value caracteres.', + ], + 'gte' => [ + 'array' => 'O campo :attribute deve ter :value itens ou mais.', + 'file' => 'O arquivo :attribute deve ser maior ou igual a :value kilobytes.', + 'numeric' => 'O campo :attribute deve ser maior ou igual a :value.', + 'string' => 'O campo :attribute deve ser maior ou igual a :value caracteres.', + ], + 'hex_color' => 'O campo :attribute deve ter uma cor hexadecimal válida.', + 'image' => 'O campo :attribute deve conter uma imagem.', + 'in' => 'O campo :attribute não contém um valor válido.', + 'in_array' => 'O campo :attribute não existe em :other.', + 'in_array_keys' => 'The :attribute field must contain at least one of the following keys: :values.', + 'integer' => 'O campo :attribute deve conter um número inteiro.', + 'ip' => 'O campo :attribute deve conter um IP válido.', + 'ipv4' => 'O campo :attribute deve conter um IPv4 válido.', + 'ipv6' => 'O campo :attribute deve conter um IPv6 válido.', + 'json' => 'O campo :attribute deve conter uma string JSON válida.', + 'list' => 'O campo :attribute deve ser uma lista.', + 'lowercase' => 'O :attribute deve ser minúsculo.', + 'lt' => [ + 'array' => 'O campo :attribute deve ter menos que :value itens.', + 'file' => 'O arquivo :attribute ser menor que :value kilobytes.', + 'numeric' => 'O campo :attribute deve ser menor que :value.', + 'string' => 'O campo :attribute deve ser menor que :value caracteres.', + ], + 'lte' => [ + 'array' => 'O campo :attribute não deve ter mais que :value itens.', + 'file' => 'O arquivo :attribute ser menor ou igual a :value kilobytes.', + 'numeric' => 'O campo :attribute deve ser menor ou igual a :value.', + 'string' => 'O campo :attribute deve ser menor ou igual a :value caracteres.', + ], + 'mac_address' => 'O :attribute deve ser um endereço MAC válido.', + 'max' => [ + 'array' => 'O campo :attribute deve conter no máximo :max itens.', + 'file' => 'O campo :attribute não pode conter um arquivo com mais de :max kilobytes.', + 'numeric' => 'O campo :attribute não pode conter um valor superior a :max.', + 'string' => 'O campo :attribute não pode conter mais de :max caracteres.', + ], + 'max_digits' => 'O :attribute não deve ter mais que :max dígitos.', + 'mimes' => 'O campo :attribute deve conter um arquivo do tipo: :values.', + 'mimetypes' => 'O campo :attribute deve conter um arquivo do tipo: :values.', + 'min' => [ + 'array' => 'O campo :attribute deve conter no mínimo :min itens.', + 'file' => 'O campo :attribute deve conter um arquivo com no mínimo :min kilobytes.', + 'numeric' => 'O campo :attribute deve conter um número superior ou igual a :min.', + 'string' => 'O campo :attribute deve conter no mínimo :min caracteres.', + ], + 'min_digits' => 'O :attribute deve ter pelo menos :min dígitos.', + 'missing' => 'O campo :attribute deve estar ausente.', + 'missing_if' => 'O campo :attribute deve estar ausente quando :other for :value.', + 'missing_unless' => 'O campo :attribute deve estar ausente, a menos que :other seja :value.', + 'missing_with' => 'O campo :attribute deve estar ausente quando :values estiver presente.', + 'missing_with_all' => 'O campo :attribute deve estar ausente quando :values estiverem presentes.', + 'multiple_of' => 'O :attribute deve ser um múltiplo de :value', + 'not_in' => 'O campo :attribute contém um valor inválido.', + 'not_regex' => 'O formato do valor :attribute é inválido.', + 'numeric' => 'O campo :attribute deve conter um valor numérico.', + 'password' => [ + 'letters' => 'O :attribute deve conter pelo menos uma letra.', + 'mixed' => 'O :attribute deve conter pelo menos uma letra maiúscula e uma minúscula.', + 'numbers' => 'O :attribute deve conter pelo menos um número.', + 'symbols' => 'O :attribute deve conter pelo menos um símbolo.', + 'uncompromised' => 'O dado :attribute apareceu em um vazamento de dados. Por favor, escolha um :attribute diferente.', + ], + 'present' => 'O campo :attribute deve estar presente.', + 'present_if' => 'O campo :attribute deve estar presente quando :other for :value.', + 'present_unless' => 'O campo :attribute deve estar presente, a menos que :other seja :value.', + 'present_with' => 'O campo :attribute deve estar presente quando :values estiver presente.', + 'present_with_all' => 'O campo :attribute deve estar presente quando :values estiverem presentes.', + 'prohibited' => 'O campo :attribute é proibido.', + 'prohibited_if' => 'O campo :attribute é proibido quando :other é :value.', + 'prohibited_if_accepted' => 'O campo :attribute é proibido quando :other é aceito.', + 'prohibited_if_declined' => 'O campo :attribute é proibido quando :other é recusado.', + 'prohibited_unless' => 'O campo :attribute é proibido a menos que :other esteja em :values.', + 'prohibits' => 'O campo :attribute proíbe :other de estar presente.', + 'regex' => 'O formato do valor informado no campo :attribute é inválido.', + 'required' => 'O campo :attribute é obrigatório.', + 'required_array_keys' => 'O campo :attribute deve conter entradas para: :values', + 'required_if' => 'O campo :attribute é obrigatório quando o valor do campo :other é igual a :value.', + 'required_if_accepted' => 'O campo :attribute é obrigatório quando :other é aceito.', + 'required_if_declined' => 'O campo :attribute é obrigatório quando :other não for informado.', + 'required_unless' => 'O campo :attribute é obrigatório a menos que :other esteja presente em :values.', + 'required_with' => 'O campo :attribute é obrigatório quando :values está presente.', + 'required_with_all' => 'O campo :attribute é obrigatório quando um dos :values está presente.', + 'required_without' => 'O campo :attribute é obrigatório quando :values não está presente.', + 'required_without_all' => 'O campo :attribute é obrigatório quando nenhum dos :values está presente.', + 'same' => 'Os campos :attribute e :other devem conter valores iguais.', + 'size' => [ + 'array' => 'O campo :attribute deve conter :size itens.', + 'file' => 'O campo :attribute deve conter um arquivo com o tamanho de :size kilobytes.', + 'numeric' => 'O campo :attribute deve conter o número :size.', + 'string' => 'O campo :attribute deve conter :size caracteres.', + ], + 'starts_with' => 'O campo :attribute deve começar com um dos seguintes valores: :values', + 'string' => 'O campo :attribute deve ser uma string.', + 'timezone' => 'O campo :attribute deve conter um fuso horário válido.', + 'ulid' => 'O :attribute deve ser um ULID válido.', + 'unique' => 'O valor informado para o campo :attribute já está em uso.', + 'uploaded' => 'Falha no Upload do arquivo :attribute.', + 'uppercase' => 'O :attribute deve ser maiúsculo.', + 'url' => 'O formato da URL informada para o campo :attribute é inválido.', + 'uuid' => 'O campo :attribute deve ser um UUID válido.', + 'attributes' => [ + 'address' => 'endereço', + 'affiliate_url' => 'URL de afiliado', + 'age' => 'idade', + 'amount' => 'motante', + 'announcement' => 'anúncio', + 'area' => 'área', + 'audience_prize' => 'prêmio do público', + 'audience_winner' => 'vencedor do público', + 'available' => 'disponível', + 'birthday' => 'aniversário', + 'body' => 'conteúdo', + 'city' => 'cidade', + 'company' => 'empresa', + 'compilation' => 'compilação', + 'concept' => 'conceito', + 'conditions' => 'condições', + 'content' => 'conteúdo', + 'contest' => 'contestar', + 'country' => 'país', + 'cover' => 'cobrir', + 'created_at' => 'criado em', + 'creator' => 'criador', + 'currency' => 'moeda', + 'current_password' => 'senha atual', + 'customer' => 'cliente', + 'date' => 'data', + 'date_of_birth' => 'data de nascimento', + 'dates' => 'datas', + 'day' => 'dia', + 'deleted_at' => 'excluído em', + 'description' => 'descrição', + 'display_type' => 'Tipo de exibição', + 'district' => 'distrito', + 'duration' => 'duração', + 'email' => 'e-mail', + 'excerpt' => 'resumo', + 'filter' => 'filtro', + 'finished_at' => 'terminou em', + 'first_name' => 'primeiro nome', + 'gender' => 'gênero', + 'grand_prize' => 'grande Prêmio', + 'group' => 'grupo', + 'hour' => 'hora', + 'image' => 'imagem', + 'image_desktop' => 'imagem da área de trabalho', + 'image_main' => 'imagem principal', + 'image_mobile' => 'imagem móvel', + 'images' => 'imagens', + 'is_audience_winner' => 'é vencedor de audiência', + 'is_hidden' => 'está escondido', + 'is_subscribed' => 'está inscrito', + 'is_visible' => 'é visível', + 'is_winner' => 'é vencedor', + 'items' => 'Unid', + 'key' => 'chave', + 'last_name' => 'sobrenome', + 'lesson' => 'lição', + 'line_address_1' => 'endereço de linha 1', + 'line_address_2' => 'endereço de linha 2', + 'login' => 'Conecte-se', + 'message' => 'mensagem', + 'middle_name' => 'nome do meio', + 'minute' => 'minuto', + 'mobile' => 'celular', + 'month' => 'mês', + 'name' => 'nome', + 'national_code' => 'código nacional', + 'nickname' => 'apelido', + 'number' => 'número', + 'password' => 'senha', + 'password_confirmation' => 'confirmação da senha', + 'phone' => 'telefone', + 'photo' => 'foto', + 'portfolio' => 'portfólio', + 'postal_code' => 'código postal', + 'preview' => 'visualização', + 'price' => 'preço', + 'product_id' => 'ID do produto', + 'product_uid' => 'UID do produto', + 'product_uuid' => 'UUID do produto', + 'promo_code' => 'Código promocional', + 'province' => 'província', + 'quantity' => 'quantidade', + 'reason' => 'razão', + 'recaptcha_response_field' => 'campo de resposta recaptcha', + 'referee' => 'juiz', + 'referees' => 'árbitros', + 'reject_reason' => 'rejeitar a razão', + 'remember' => 'lembrar-me', + 'restored_at' => 'restaurado em', + 'result_text_under_image' => 'texto do resultado sob a imagem', + 'role' => 'função', + 'rule' => 'regra', + 'rules' => 'regras', + 'second' => 'segundo', + 'sex' => 'sexo', + 'shipment' => 'envio', + 'short_text' => 'texto pequeno', + 'size' => 'tamanho', + 'situation' => 'situação', + 'skills' => 'habilidades', + 'slug' => 'lesma', + 'specialization' => 'especialização', + 'started_at' => 'começou às', + 'state' => 'estado', + 'status' => 'estado', + 'street' => 'rua', + 'student' => 'estudante', + 'subject' => 'assunto', + 'tag' => 'marcação', + 'tags' => 'Tag', + 'teacher' => 'professor', + 'terms' => 'termos', + 'test_description' => 'descrição de teste', + 'test_locale' => 'local de teste', + 'test_name' => 'nome de teste', + 'text' => 'texto', + 'time' => 'hora', + 'title' => 'título', + 'type' => 'tipo', + 'updated_at' => 'atualizado em', + 'user' => 'do utilizador', + 'username' => 'usuário', + 'value' => 'valor', + 'winner' => 'ganhador', + 'work' => 'trabalho', + 'year' => 'ano', + ], +]; diff --git a/lang/scribe.php b/lang/scribe.php new file mode 100644 index 00000000..fc402bbd --- /dev/null +++ b/lang/scribe.php @@ -0,0 +1,77 @@ + [ + "search" => "Search", + "base_url" => "Base URL", + ], + + "auth" => [ + "none" => "This API is not authenticated.", + "instruction" => [ + "query" => << << << << << << << [ + "introduction" => "Introduction", + "auth" => "Authenticating requests", + ], + + "endpoint" => [ + "request" => "Request", + "headers" => "Headers", + "url_parameters" => "URL Parameters", + "body_parameters" => "Body Parameters", + "query_parameters" => "Query Parameters", + "response" => "Response", + "response_fields" => "Response Fields", + "example_request" => "Example request", + "example_response" => "Example response", + "responses" => [ + "binary" => "Binary data", + "empty" => "Empty response", + ], + ], + + "try_it_out" => [ + "open" => "Try it out ⚡", + "cancel" => "Cancel 🛑", + "send" => "Send Request 💥", + "loading" => "⏱ Sending...", + "received_response" => "Received response", + "request_failed" => "Request failed with error", + "error_help" => << [ + "postman" => "View Postman collection", + "openapi" => "View OpenAPI spec", + ], +]; diff --git a/package-lock.json b/package-lock.json index 9e59fcc7..117faae8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,38 +1,52 @@ { - "name": "vue-starter-kit", + "name": "tall-vs", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { "@inertiajs/vue3": "^2.0.0", - "@tailwindcss/vite": "^4.1.1", + "@tailwindcss/vite": "^4.1.10", + "@tanstack/vue-table": "^8.21.3", + "@types/lodash": "^4.17.17", + "@types/lodash-es": "^4.17.12", + "@vee-validate/zod": "^4.15.1", "@vitejs/plugin-vue": "^5.2.1", "@vueuse/core": "^12.8.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "concurrently": "^9.0.1", "laravel-vite-plugin": "^1.0", + "laravel-vue-i18n": "^2.8.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "lucide-vue-next": "^0.468.0", - "reka-ui": "^2.2.0", - "tailwind-merge": "^3.2.0", - "tailwindcss": "^4.1.1", - "tw-animate-css": "^1.2.5", + "reka-ui": "^2.3.1", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.10", + "tw-animate-css": "^1.3.4", "typescript": "^5.2.2", + "v-click-outside": "^3.2.0", + "vee-validate": "^4.15.1", "vite": "^6.2.0", "vue": "^3.5.13", - "ziggy-js": "^2.4.2" + "vue-sonner": "^2.0.0", + "ziggy-js": "^2.4.2", + "zod": "^3.25.64" }, "devDependencies": { "@eslint/js": "^9.19.0", + "@laravel/echo-vue": "^2.1.5", "@types/node": "^22.13.5", "@vue/eslint-config-typescript": "^14.3.0", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.1", "eslint-plugin-vue": "^9.32.0", + "laravel-echo": "^2.1.5", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-tailwindcss": "^0.6.11", + "pusher-js": "^8.4.0", "typescript-eslint": "^8.23.0", "vue-tsc": "^2.2.4" }, @@ -907,6 +921,21 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@laravel/echo-vue": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@laravel/echo-vue/-/echo-vue-2.1.5.tgz", + "integrity": "sha512-7GONR0WB89SNuPQJqikXy/bGA+PkGACUXwSvD7Os6/w/D8waBKj6dBU4rpYP2zbIZCLEJprK+giz28VTT3ARgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "pusher-js": "*", + "socket.io-client": "*", + "vue": "^3.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1205,6 +1234,14 @@ "win32" ] }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@swc/helpers": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", @@ -1215,9 +1252,9 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz", - "integrity": "sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz", + "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -1226,13 +1263,13 @@ "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.8" + "tailwindcss": "4.1.10" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz", - "integrity": "sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz", + "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -1243,24 +1280,24 @@ "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.8", - "@tailwindcss/oxide-darwin-arm64": "4.1.8", - "@tailwindcss/oxide-darwin-x64": "4.1.8", - "@tailwindcss/oxide-freebsd-x64": "4.1.8", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.8", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.8", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.8", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.8", - "@tailwindcss/oxide-linux-x64-musl": "4.1.8", - "@tailwindcss/oxide-wasm32-wasi": "4.1.8", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.8", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.8" + "@tailwindcss/oxide-android-arm64": "4.1.10", + "@tailwindcss/oxide-darwin-arm64": "4.1.10", + "@tailwindcss/oxide-darwin-x64": "4.1.10", + "@tailwindcss/oxide-freebsd-x64": "4.1.10", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.10", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.10", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.10", + "@tailwindcss/oxide-linux-x64-musl": "4.1.10", + "@tailwindcss/oxide-wasm32-wasi": "4.1.10", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.10", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.10" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz", - "integrity": "sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz", + "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", "cpu": [ "arm64" ], @@ -1274,9 +1311,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz", - "integrity": "sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz", + "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", "cpu": [ "arm64" ], @@ -1290,9 +1327,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz", - "integrity": "sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz", + "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", "cpu": [ "x64" ], @@ -1306,9 +1343,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz", - "integrity": "sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz", + "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", "cpu": [ "x64" ], @@ -1322,9 +1359,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz", - "integrity": "sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz", + "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", "cpu": [ "arm" ], @@ -1338,9 +1375,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz", - "integrity": "sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz", + "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", "cpu": [ "arm64" ], @@ -1354,9 +1391,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz", - "integrity": "sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz", + "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", "cpu": [ "arm64" ], @@ -1370,9 +1407,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz", - "integrity": "sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz", + "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", "cpu": [ "x64" ], @@ -1386,9 +1423,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz", - "integrity": "sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz", + "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", "cpu": [ "x64" ], @@ -1402,9 +1439,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz", - "integrity": "sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz", + "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1431,9 +1468,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz", - "integrity": "sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz", + "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", "cpu": [ "arm64" ], @@ -1447,9 +1484,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz", - "integrity": "sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz", + "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", "cpu": [ "x64" ], @@ -1463,19 +1500,32 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.8.tgz", - "integrity": "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.10.tgz", + "integrity": "sha512-QWnD5HDY2IADv+vYR82lOhqOlS1jSCUUAmfem52cXAhRTKxpDh3ARX8TTXJTCCO7Rv7cD2Nlekabv02bwP3a2A==", "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.8", - "@tailwindcss/oxide": "4.1.8", - "tailwindcss": "4.1.8" + "@tailwindcss/node": "4.1.10", + "@tailwindcss/oxide": "4.1.10", + "tailwindcss": "4.1.10" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/virtual-core": { "version": "3.13.9", "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.9.tgz", @@ -1486,6 +1536,25 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/vue-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/vue-table/-/vue-table-8.21.3.tgz", + "integrity": "sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": ">=3.2" + } + }, "node_modules/@tanstack/vue-virtual": { "version": "3.13.9", "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.9.tgz", @@ -1515,6 +1584,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "22.15.30", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", @@ -1781,6 +1865,31 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@vee-validate/zod": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@vee-validate/zod/-/zod-4.15.1.tgz", + "integrity": "sha512-329Z4TDBE5Vx0FdbA8S4eR9iGCFFUNGbxjpQ20ff5b5wGueScjocUIx9JHPa79LTG06RnlUR4XogQsjN4tecKA==", + "license": "MIT", + "dependencies": { + "type-fest": "^4.8.3", + "vee-validate": "4.15.1" + }, + "peerDependencies": { + "zod": "^3.24.0" + } + }, + "node_modules/@vee-validate/zod/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", @@ -1884,6 +1993,39 @@ "he": "^1.2.0" } }, + "node_modules/@vue/devtools-api": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.6.tgz", + "integrity": "sha512-b2Xx0KvXZObePpXPYHvBRRJLDQn5nhKjXh7vUhMEtWxz1AYNFOVIsh5+HLP8xDGL7sy+Q7hXeUxPHB/KgbtsPw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.6" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.6.tgz", + "integrity": "sha512-geu7ds7tem2Y7Wz+WgbnbZ6T5eadOvozHZ23Atk/8tksHMFOFylKi1xgGlQlVn0wlkEf4hu+vd5ctj1G4kFtwA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.6", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.6.tgz", + "integrity": "sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, "node_modules/@vue/eslint-config-typescript": { "version": "14.5.0", "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.5.0.tgz", @@ -2135,6 +2277,15 @@ "dev": true, "license": "MIT" }, + "node_modules/birpc": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.4.0.tgz", + "integrity": "sha512-5IdNxTyhXHv2UlgnPHQ0h+5ypVmkrYHzL8QT+DwFZ//2N/oNV8Ch+BCRmTJ3x6/z9Axo/cXYBc9eprsUVK/Jsg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2338,6 +2489,21 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2448,6 +2614,51 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -3255,6 +3466,12 @@ "he": "bin/he" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3334,6 +3551,18 @@ "node": ">=0.12.0" } }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3394,6 +3623,20 @@ "json-buffer": "3.0.1" } }, + "node_modules/laravel-echo": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-2.1.5.tgz", + "integrity": "sha512-xIlV7AYjfIXv9KGiDa3qqc7JOEJUqNl+6Nx/I6bdxnSAMqnNZT5Nc1rwjOYfoYEI6030QkKF8BhPuU6Roakebw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "pusher-js": "*", + "socket.io-client": "*" + } + }, "node_modules/laravel-vite-plugin": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.3.0.tgz", @@ -3413,6 +3656,16 @@ "vite": "^5.0.0 || ^6.0.0" } }, + "node_modules/laravel-vue-i18n": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/laravel-vue-i18n/-/laravel-vue-i18n-2.8.0.tgz", + "integrity": "sha512-5D4GvITMZaLVwnirMU8NeQBCSfhEqDyRHiFshfP9ycdczB6e2oYZl5ow95M2sLOViPCuroYzMXqybfG9yFhoCw==", + "license": "MIT", + "dependencies": { + "php-parser": "3.2.2", + "vue": "^3.5.13" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3677,6 +3930,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3793,6 +4052,12 @@ "node": ">= 18" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", @@ -3968,6 +4233,18 @@ "node": ">=8" } }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/php-parser": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.2.2.tgz", + "integrity": "sha512-voj3rzCJmEbwHwH3QteON28wA6K+JbcaJEofyUZkUXmcViiXofjbSbcE5PtqtjX6nstnnAEYCFoRq0mkjP5/cg==", + "license": "BSD-3-Clause" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4166,6 +4443,16 @@ "node": ">=6" } }, + "node_modules/pusher-js": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.4.0.tgz", + "integrity": "sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tweetnacl": "^1.0.3" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -4203,9 +4490,9 @@ "license": "MIT" }, "node_modules/reka-ui": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.3.0.tgz", - "integrity": "sha512-HKvJej9Sc0KYEvTAbsGHgOxpEWL4FWSR70Q6Ld+bVNuaCxK6LP3jyTtyTWS+A44hHA9/aYfOBZ1Q8WkgZsGZpA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.3.1.tgz", + "integrity": "sha512-2SjGeybd7jvD8EQUkzjgg7GdOQdf4cTwdVMq/lDNTMqneUFNnryGO43dg8WaM/jaG9QpSCZBvstfBFWlDdb2Zg==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.6.13", @@ -4253,6 +4540,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, "node_modules/rollup": { "version": "4.41.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", @@ -4458,6 +4751,76 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4467,6 +4830,15 @@ "node": ">=0.10.0" } }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4506,6 +4878,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superjson": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", + "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -4522,9 +4906,9 @@ } }, "node_modules/tailwind-merge": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.0.tgz", - "integrity": "sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", "license": "MIT", "funding": { "type": "github", @@ -4532,9 +4916,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz", - "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz", + "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==", "license": "MIT" }, "node_modules/tapable": { @@ -4655,6 +5039,13 @@ "url": "https://github.com/sponsors/Wombosvideo" } }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true, + "license": "Unlicense" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4741,6 +5132,40 @@ "dev": true, "license": "MIT" }, + "node_modules/v-click-outside": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v-click-outside/-/v-click-outside-3.2.0.tgz", + "integrity": "sha512-QD0bDy38SHJXQBjgnllmkI/rbdiwmq9RC+/+pvrFjYJKTn8dtp7Penf9q1lLBta280fYG2q53mgLhQ+3l3z74w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/vee-validate": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.15.1.tgz", + "integrity": "sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.5.2", + "type-fest": "^4.8.3" + }, + "peerDependencies": { + "vue": "^3.4.26" + } + }, + "node_modules/vee-validate/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/vite": { "version": "6.3.5", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", @@ -4917,6 +5342,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/vue-sonner": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vue-sonner/-/vue-sonner-2.0.0.tgz", + "integrity": "sha512-nvlqGGWvxEv9UnKcZxsGdKpHrODEdv3CXAJF3er+1pLC03caJt2+v9HuWtRqlBQwUr1SFttsYuwVbpbEl05n4A==", + "license": "MIT" + }, "node_modules/vue-tsc": { "version": "2.2.10", "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.10.tgz", @@ -4977,6 +5408,29 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xml-name-validator": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", @@ -4987,6 +5441,16 @@ "node": ">=12" } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -5066,6 +5530,15 @@ "funding": { "url": "https://github.com/sponsors/ljharb" } + }, + "node_modules/zod": { + "version": "3.25.64", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.64.tgz", + "integrity": "sha512-hbP9FpSZf7pkS7hRVUrOjhwKJNyampPgtXKc3AN6DsWtoHsg2Sb4SQaS4Tcay380zSwd2VPo9G9180emBACp5g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 1b90179b..7e2c40e6 100644 --- a/package.json +++ b/package.json @@ -11,35 +11,49 @@ }, "devDependencies": { "@eslint/js": "^9.19.0", + "@laravel/echo-vue": "^2.1.5", "@types/node": "^22.13.5", "@vue/eslint-config-typescript": "^14.3.0", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.1", "eslint-plugin-vue": "^9.32.0", + "laravel-echo": "^2.1.5", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-tailwindcss": "^0.6.11", + "pusher-js": "^8.4.0", "typescript-eslint": "^8.23.0", "vue-tsc": "^2.2.4" }, "dependencies": { "@inertiajs/vue3": "^2.0.0", - "@tailwindcss/vite": "^4.1.1", + "@tailwindcss/vite": "^4.1.10", + "@tanstack/vue-table": "^8.21.3", + "@types/lodash": "^4.17.17", + "@types/lodash-es": "^4.17.12", + "@vee-validate/zod": "^4.15.1", "@vitejs/plugin-vue": "^5.2.1", "@vueuse/core": "^12.8.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "concurrently": "^9.0.1", "laravel-vite-plugin": "^1.0", + "laravel-vue-i18n": "^2.8.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", "lucide-vue-next": "^0.468.0", - "reka-ui": "^2.2.0", - "tailwind-merge": "^3.2.0", - "tailwindcss": "^4.1.1", - "tw-animate-css": "^1.2.5", + "reka-ui": "^2.3.1", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.10", + "tw-animate-css": "^1.3.4", "typescript": "^5.2.2", + "v-click-outside": "^3.2.0", + "vee-validate": "^4.15.1", "vite": "^6.2.0", "vue": "^3.5.13", - "ziggy-js": "^2.4.2" + "vue-sonner": "^2.0.0", + "ziggy-js": "^2.4.2", + "zod": "^3.25.64" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.9.5", diff --git a/resources/css/app.css b/resources/css/app.css index 1a7ee31e..be8ae360 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -7,48 +7,107 @@ @custom-variant dark (&:is(.dark *)); -@theme inline { - --font-sans: Instrument Sans, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} - --radius-lg: var(--radius); - --radius-md: calc(var(--radius) - 2px); - --radius-sm: calc(var(--radius) - 4px); +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} +@theme inline { --color-background: var(--background); --color-foreground: var(--foreground); - --color-card: var(--card); --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); - --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); - --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); - - --color-sidebar: var(--sidebar-background); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); @@ -56,34 +115,31 @@ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); -} -/* - The default border color has changed to `currentColor` in Tailwind CSS v4, - so we've added these compatibility styles to make sure everything still - looks the same as it did with Tailwind CSS v3. + --animate-accordion-down: accordion-down 0.2s ease-out; + --animate-accordion-up: accordion-up 0.2s ease-out; - If we ever want to remove these styles, we need to add an explicit border - color utility to any element that depends on these defaults. -*/ -@layer base { - *, - ::after, - ::before, - ::backdrop, - ::file-selector-button { - border-color: var(--color-gray-200, currentColor); + @keyframes accordion-down { + from { + height: 0; + } + to { + height: var(--reka-accordion-content-height); + } } -} -@layer utilities { - body, - html { - --font-sans: - 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + @keyframes accordion-up { + from { + height: var(--reka-accordion-content-height); + } + to { + height: 0; + } } } +<<<<<<< HEAD +======= :root { --background: hsl(0 0% 100%); --foreground: hsl(0 0% 3.9%); @@ -157,6 +213,7 @@ --sidebar: hsl(240 5.9% 10%); } +>>>>>>> fbae2a4df2eec7e4f7c857ffe50db2b78473ce3f @layer base { * { @apply border-border outline-ring/50; diff --git a/resources/js/app.ts b/resources/js/app.ts index 792a46cf..11b96ce5 100644 --- a/resources/js/app.ts +++ b/resources/js/app.ts @@ -1,11 +1,16 @@ import '../css/app.css'; import { createInertiaApp } from '@inertiajs/vue3'; +import { configureEcho } from '@laravel/echo-vue'; import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; +import { i18nVue } from 'laravel-vue-i18n'; import type { DefineComponent } from 'vue'; import { createApp, h } from 'vue'; import { ZiggyVue } from 'ziggy-js'; import { initializeTheme } from './composables/useAppearance'; +configureEcho({ + broadcaster: 'reverb', +}); const appName = import.meta.env.VITE_APP_NAME || 'Laravel'; @@ -16,6 +21,12 @@ createInertiaApp({ createApp({ render: () => h(App, props) }) .use(plugin) .use(ZiggyVue) + .use(i18nVue, { + resolve: async (lang: string) => { + const langs = import.meta.glob('../../lang/*.json'); + return await langs[`../../lang/${lang}.json`](); + }, + }) .mount(el); }, progress: { diff --git a/resources/js/components/AppLogo.vue b/resources/js/components/AppLogo.vue index 01723b42..d204a1ca 100644 --- a/resources/js/components/AppLogo.vue +++ b/resources/js/components/AppLogo.vue @@ -3,10 +3,11 @@ import AppLogoIcon from '@/components/AppLogoIcon.vue'; diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index 98442720..de89f5f2 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -5,8 +5,76 @@ import NavUser from '@/components/NavUser.vue'; import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar'; import { type NavItem } from '@/types'; import { Link } from '@inertiajs/vue3'; -import { BookOpen, Folder, LayoutGrid } from 'lucide-vue-next'; +import { BookOpen, BookOpenIcon, Folder, LayoutGrid, User2 } from 'lucide-vue-next'; import AppLogo from './AppLogo.vue'; +import { useNavFilter } from '@/composables/useNavFilter' +import { computed } from 'vue' + +const developmentNavItems: NavItem[] = [ + + { + title: 'System Development', + icon: Folder, + permission: '', + children: [ + { + title: 'Models Generated', + href: '/models-generate', + icon: BookOpenIcon, + permission: 'system.models.list' + }, + { + title: 'Settings', + href: 'system-settings', + icon: LayoutGrid, + permission: 'system.settings' + }, + ], + }, + { + title: 'Roles & Permissions', + icon: Folder, + permission: 'roles.permissions', + children: [ + { + title: 'Permissions', + // href: '/login', + icon: BookOpenIcon, + children: [ + { + title: 'Nivel 1', + icon: BookOpenIcon, + children: [ + { + title: 'Create', + href: '/01create', + icon: BookOpenIcon, + + }, + { + title: 'Show', + href: '/01show', + icon: LayoutGrid, + }, + ], + + }, + { + title: 'Nível 2', + href: '/02show', + icon: LayoutGrid, + }, + ], + }, + { + title: 'Roles', + href: '/roles', + icon: LayoutGrid, + }, + ], + }, +]; + const mainNavItems: NavItem[] = [ { @@ -14,8 +82,50 @@ const mainNavItems: NavItem[] = [ href: '/dashboard', icon: LayoutGrid, }, + { + title: 'Gestão', + icon: Folder, + children: [ + { + title: 'Logs', + icon: BookOpen, + children: [ + { + title: 'Activities', + href: '/activityLogs', + icon: BookOpen, + permission: 'activityLogs.list', + + }, + + ], + }, + { + title: 'Parameters', + icon: BookOpen, + children: [ + { + title: 'Genders', + href: '/genders', + icon: BookOpen, + permission: 'genders.list', + + }, + + ], + }, + { + title: 'Usuários', + href: '/users', + icon: User2, + permission: 'users.list', + }, + + ], + }, ]; + const footerNavItems: NavItem[] = [ { title: 'Github Repo', @@ -28,6 +138,10 @@ const footerNavItems: NavItem[] = [ icon: BookOpen, }, ]; + +const { filterNavItems } = useNavFilter() +const filteredDevelopmentNavItems = computed(() => filterNavItems(developmentNavItems)) +const filteredMainNavItems = computed(() => filterNavItems(mainNavItems))