From ea50b7bfb5303c2e3d9de9deba7f5ebcb5581c3a Mon Sep 17 00:00:00 2001 From: Roardom Date: Wed, 25 Jun 2025 04:37:45 +0000 Subject: [PATCH 1/6] refactor: use laravel-data for typed form requests and dtos The developer experience is much improved with the typed form requests, and matches behaviour common in other type-safe languages. It allows accessing properties directly off the dto that came from the form request with ide autocomplete, and it validates that the properties exist and are not null. It might also be the solution to fixing the livewire type errors where a user supplies a string to an int variable as well. --- composer.json | 1 + composer.lock | 1804 +++++++++++++++++++++++++++++++++++++++-------- config/data.php | 199 ++++++ 3 files changed, 1710 insertions(+), 294 deletions(-) create mode 100644 config/data.php diff --git a/composer.json b/composer.json index 9581fe4f2e..29a95ec1cb 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,7 @@ "paragonie/constant_time_encoding": "^2.7.0", "spatie/laravel-backup": "^9.3.4", "spatie/laravel-cookie-consent": "^3.3.3", + "spatie/laravel-data": "^4.17", "spatie/laravel-image-optimizer": "^1.8.2", "spatie/ssl-certificate": "^2.6.10", "symfony/dom-crawler": "^6.4.25", diff --git a/composer.lock b/composer.lock index deb582aa90..e5d1553636 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,816 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fa6748cb945c26750567cab9a26bb2d3", + "content-hash": "ac30d95d3b38fc9b881965d8e5b0ee87", "packages": [ + { + "name": "amphp/amp", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/fa0ab33a6f47a82929c38d03ca47ebb71086a93f", + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Future/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-08-27T21:42:00+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v2.1.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2.3" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.22.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v2.1.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-03-16T17:10:27+00:00" + }, + { + "name": "amphp/cache", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/cache.git", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Cache\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A fiber-aware cache API based on Amp and Revolt.", + "homepage": "https://amphp.org/cache", + "support": { + "issues": "https://github.com/amphp/cache/issues", + "source": "https://github.com/amphp/cache/tree/v2.0.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:38:06+00:00" + }, + { + "name": "amphp/dns", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/dns.git", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/process": "^2", + "daverandom/libdns": "^2.0.2", + "ext-filter": "*", + "ext-json": "*", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Dns\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Wright", + "email": "addr@daverandom.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Async DNS resolution for Amp.", + "homepage": "https://github.com/amphp/dns", + "keywords": [ + "amp", + "amphp", + "async", + "client", + "dns", + "resolve" + ], + "support": { + "issues": "https://github.com/amphp/dns/issues", + "source": "https://github.com/amphp/dns/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-01-19T15:43:40+00:00" + }, + { + "name": "amphp/parallel", + "version": "v2.3.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/parallel.git", + "reference": "321b45ae771d9c33a068186b24117e3cd1c48dce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parallel/zipball/321b45ae771d9c33a068186b24117e3cd1c48dce", + "reference": "321b45ae771d9c33a068186b24117e3cd1c48dce", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/pipeline": "^1", + "amphp/process": "^2", + "amphp/serialization": "^1", + "amphp/socket": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "files": [ + "src/Context/functions.php", + "src/Context/Internal/functions.php", + "src/Ipc/functions.php", + "src/Worker/functions.php" + ], + "psr-4": { + "Amp\\Parallel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Parallel processing component for Amp.", + "homepage": "https://github.com/amphp/parallel", + "keywords": [ + "async", + "asynchronous", + "concurrent", + "multi-processing", + "multi-threading" + ], + "support": { + "issues": "https://github.com/amphp/parallel/issues", + "source": "https://github.com/amphp/parallel/tree/v2.3.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-08-27T21:55:40+00:00" + }, + { + "name": "amphp/parser", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/parser.git", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/parser/issues", + "source": "https://github.com/amphp/parser/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:16:53+00:00" + }, + { + "name": "amphp/pipeline", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/pipeline.git", + "reference": "7b52598c2e9105ebcddf247fc523161581930367" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/7b52598c2e9105ebcddf247fc523161581930367", + "reference": "7b52598c2e9105ebcddf247fc523161581930367", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Asynchronous iterators and operators.", + "homepage": "https://amphp.org/pipeline", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "iterator", + "non-blocking" + ], + "support": { + "issues": "https://github.com/amphp/pipeline/issues", + "source": "https://github.com/amphp/pipeline/tree/v1.2.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-03-16T16:33:53+00:00" + }, + { + "name": "amphp/process", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Process\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A fiber-aware process manager based on Amp and Revolt.", + "homepage": "https://amphp.org/process", + "support": { + "issues": "https://github.com/amphp/process/issues", + "source": "https://github.com/amphp/process/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:13:44+00:00" + }, + { + "name": "amphp/serialization", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/serialization.git", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "phpunit/phpunit": "^9 || ^8 || ^7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Serialization\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Serialization tools for IPC and data storage in PHP.", + "homepage": "https://github.com/amphp/serialization", + "keywords": [ + "async", + "asynchronous", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/amphp/serialization/issues", + "source": "https://github.com/amphp/serialization/tree/master" + }, + "time": "2020-03-25T21:39:07+00:00" + }, + { + "name": "amphp/socket", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/socket.git", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/dns": "^2", + "ext-openssl": "*", + "kelunik/certificate": "^1.1", + "league/uri": "^6.5 | ^7", + "league/uri-interfaces": "^2.3 | ^7", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php", + "src/SocketAddress/functions.php" + ], + "psr-4": { + "Amp\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@gmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", + "homepage": "https://github.com/amphp/socket", + "keywords": [ + "amp", + "async", + "encryption", + "non-blocking", + "sockets", + "tcp", + "tls" + ], + "support": { + "issues": "https://github.com/amphp/socket/issues", + "source": "https://github.com/amphp/socket/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T14:33:03+00:00" + }, + { + "name": "amphp/sync", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/217097b785130d77cfcc58ff583cf26cd1770bf1", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Sync\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "support": { + "issues": "https://github.com/amphp/sync/issues", + "source": "https://github.com/amphp/sync/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-08-03T19:31:26+00:00" + }, { "name": "assada/laravel-achievements", "version": "v2.8.0", @@ -354,6 +1162,50 @@ }, "time": "2024-08-09T14:30:48+00:00" }, + { + "name": "daverandom/libdns", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/DaveRandom/LibDNS.git", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "Required for IDN support" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "LibDNS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "DNS protocol implementation written in pure PHP", + "keywords": [ + "dns" + ], + "support": { + "issues": "https://github.com/DaveRandom/LibDNS/issues", + "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" + }, + "time": "2024-04-12T12:12:48+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.3", @@ -1957,24 +2809,82 @@ "license": [ "(CC-BY-4.0 and MIT)" ], - "description": "JoyPixels is a complete set of emoji designed for the web. The emoji-toolkit includes libraries to easily convert unicode characters to shortnames (:smile:) and shortnames to JoyPixels emoji images. PNG formats provided for the emoji images.", - "homepage": "http://www.joypixels.com", + "description": "JoyPixels is a complete set of emoji designed for the web. The emoji-toolkit includes libraries to easily convert unicode characters to shortnames (:smile:) and shortnames to JoyPixels emoji images. PNG formats provided for the emoji images.", + "homepage": "http://www.joypixels.com", + "keywords": [ + "JoyPixels", + "emoji", + "emoji-toolkit", + "emojione", + "emojis", + "emoticons", + "smileys", + "smilies", + "unicode" + ], + "support": { + "issues": "https://github.com/joypixels/emoji-toolkit/issues", + "source": "https://github.com/joypixels/emoji-toolkit/tree/6.6.0" + }, + "time": "2021-07-08T22:11:29+00:00" + }, + { + "name": "kelunik/certificate", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/kelunik/certificate.git", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=7.0" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^6 | 7 | ^8 | ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Kelunik\\Certificate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Access certificate details and transform between different formats.", "keywords": [ - "JoyPixels", - "emoji", - "emoji-toolkit", - "emojione", - "emojis", - "emoticons", - "smileys", - "smilies", - "unicode" + "DER", + "certificate", + "certificates", + "openssl", + "pem", + "x509" ], "support": { - "issues": "https://github.com/joypixels/emoji-toolkit/issues", - "source": "https://github.com/joypixels/emoji-toolkit/tree/6.6.0" + "issues": "https://github.com/kelunik/certificate/issues", + "source": "https://github.com/kelunik/certificate/tree/v1.1.3" }, - "time": "2021-07-08T22:11:29+00:00" + "time": "2023-02-03T21:26:53+00:00" }, { "name": "laminas/laminas-diactoros", @@ -4196,41 +5106,299 @@ "shasum": "" }, "require": { - "composer-plugin-api": "^1.0|^2.0", - "php": "^7.1 || ^8.0" - }, - "conflict": { - "nyholm/psr7": "<1.0", - "zendframework/zend-diactoros": "*" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "*", - "psr/http-factory-implementation": "*", - "psr/http-message-implementation": "*" + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0", + "zendframework/zend-diactoros": "*" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "sebastian/comparator": "^3.0.5 || ^4.0.8", + "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + }, + "exclude-from-classmap": [ + "src/Composer/Plugin.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.20.0" + }, + "time": "2024-10-02T11:20:13+00:00" + }, + { + "name": "phpdocumentor/reflection", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/Reflection.git", + "reference": "d91b3270832785602adcc24ae2d0974ba99a8ff8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/d91b3270832785602adcc24ae2d0974ba99a8ff8", + "reference": "d91b3270832785602adcc24ae2d0974ba99a8ff8", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "nikic/php-parser": "~4.18 || ^5.0", + "php": "8.1.*|8.2.*|8.3.*|8.4.*", + "phpdocumentor/reflection-common": "^2.1", + "phpdocumentor/reflection-docblock": "^5", + "phpdocumentor/type-resolver": "^1.2", + "symfony/polyfill-php80": "^1.28", + "webmozart/assert": "^1.7" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "doctrine/coding-standard": "^13.0", + "eliashaeussler/phpunit-attributes": "^1.7", + "mikey179/vfsstream": "~1.2", + "mockery/mockery": "~1.6.0", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^10.0", + "psalm/phar": "^6.0", + "rector/rector": "^1.0.0", + "squizlabs/php_codesniffer": "^3.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-5.x": "5.3.x-dev", + "dev-6.x": "6.0.x-dev" + } + }, + "autoload": { + "files": [ + "src/php-parser/Modifiers.php" + ], + "psr-4": { + "phpDocumentor\\": "src/phpDocumentor" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Reflection library to do Static Analysis for PHP Projects", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/Reflection/issues", + "source": "https://github.com/phpDocumentor/Reflection/tree/6.3.0" + }, + "time": "2025-06-06T13:39:18+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.6.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", + "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5 || ~1.6.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "psalm/phar": "^5.26" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" + }, + "time": "2025-08-01T19:43:32+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" }, "require-dev": { - "composer/composer": "^1.0.2|^2.0", - "graham-campbell/phpspec-skip-example-extension": "^5.0", - "php-http/httplug": "^1.0 || ^2.0", - "php-http/message-factory": "^1.0", - "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", - "sebastian/comparator": "^3.0.5 || ^4.0.8", - "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, - "type": "composer-plugin", + "type": "library", "extra": { - "class": "Http\\Discovery\\Composer\\Plugin", - "plugin-optional": true + "branch-alias": { + "dev-1.x": "1.x-dev" + } }, "autoload": { "psr-4": { - "Http\\Discovery\\": "src/" - }, - "exclude-from-classmap": [ - "src/Composer/Plugin.php" - ] + "phpDocumentor\\Reflection\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4238,27 +5406,16 @@ ], "authors": [ { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", - "homepage": "http://php-http.org", - "keywords": [ - "adapter", - "client", - "discovery", - "factory", - "http", - "message", - "psr17", - "psr7" - ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { - "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.20.0" + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" }, - "time": "2024-10-02T11:20:13+00:00" + "time": "2024-11-09T15:12:26+00:00" }, { "name": "phpoption/phpoption", @@ -4335,6 +5492,53 @@ ], "time": "2025-08-21T11:53:16+00:00" }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" + }, + "time": "2025-07-13T07:04:09+00:00" + }, { "name": "pragmarx/google2fa", "version": "v8.0.3", @@ -5124,6 +6328,78 @@ }, "time": "2025-06-25T14:20:11+00:00" }, + { + "name": "revolt/event-loop", + "version": "v1.0.7", + "source": { + "type": "git", + "url": "https://github.com/revoltphp/event-loop.git", + "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/09bf1bf7f7f574453efe43044b06fafe12216eb3", + "reference": "09bf1bf7f7f574453efe43044b06fafe12216eb3", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Revolt\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.7" + }, + "time": "2025-01-25T19:27:39+00:00" + }, { "name": "spatie/db-dumper", "version": "3.8.0", @@ -5420,6 +6696,89 @@ ], "time": "2025-02-21T13:11:14+00:00" }, + { + "name": "spatie/laravel-data", + "version": "4.17.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-data.git", + "reference": "6ec15bb6798128f01aecb67dcd18a937251a27a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/6ec15bb6798128f01aecb67dcd18a937251a27a5", + "reference": "6ec15bb6798128f01aecb67dcd18a937251a27a5", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^10.0|^11.0|^12.0", + "php": "^8.1", + "phpdocumentor/reflection": "^6.0", + "spatie/laravel-package-tools": "^1.9.0", + "spatie/php-structure-discoverer": "^2.0" + }, + "require-dev": { + "fakerphp/faker": "^1.14", + "friendsofphp/php-cs-fixer": "^3.0", + "inertiajs/inertia-laravel": "^2.0", + "livewire/livewire": "^3.0", + "mockery/mockery": "^1.6", + "nesbot/carbon": "^2.63|^3.0", + "orchestra/testbench": "^8.0|^9.0|^10.0", + "pestphp/pest": "^2.31|^3.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0", + "pestphp/pest-plugin-livewire": "^2.1|^3.0", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpunit/phpunit": "^10.0|^11.0|^12.0", + "spatie/invade": "^1.0", + "spatie/laravel-typescript-transformer": "^2.5", + "spatie/pest-plugin-snapshots": "^2.1", + "spatie/test-time": "^1.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelData\\LaravelDataServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "role": "Developer" + } + ], + "description": "Create unified resources and data transfer objects", + "homepage": "https://github.com/spatie/laravel-data", + "keywords": [ + "laravel", + "laravel-data", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-data/issues", + "source": "https://github.com/spatie/laravel-data/tree/4.17.1" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-09-04T08:30:23+00:00" + }, { "name": "spatie/laravel-image-optimizer", "version": "1.8.2", @@ -5642,12 +7001,84 @@ "php": "^8.0" }, "require-dev": { - "phpunit/phpunit": "^8.0|^9.3" + "phpunit/phpunit": "^8.0|^9.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Macroable\\": "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 trait to dynamically add methods to a class", + "homepage": "https://github.com/spatie/macroable", + "keywords": [ + "macroable", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/macroable/issues", + "source": "https://github.com/spatie/macroable/tree/2.0.0" + }, + "time": "2021-03-26T22:39:02+00:00" + }, + { + "name": "spatie/php-structure-discoverer", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/php-structure-discoverer.git", + "reference": "42f4d731d3dd4b3b85732e05a8c1928fcfa2f4bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/php-structure-discoverer/zipball/42f4d731d3dd4b3b85732e05a8c1928fcfa2f4bc", + "reference": "42f4d731d3dd4b3b85732e05a8c1928fcfa2f4bc", + "shasum": "" + }, + "require": { + "amphp/amp": "^v3.0", + "amphp/parallel": "^2.2", + "illuminate/collections": "^10.0|^11.0|^12.0", + "php": "^8.1", + "spatie/laravel-package-tools": "^1.4.3", + "symfony/finder": "^6.0|^7.0" + }, + "require-dev": { + "illuminate/console": "^10.0|^11.0|^12.0", + "laravel/pint": "^1.0", + "nunomaduro/collision": "^7.0|^8.0", + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "pestphp/pest": "^2.0|^3.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5|^10.0|^11.5.3", + "spatie/laravel-ray": "^1.26" }, "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\StructureDiscoverer\\StructureDiscovererServiceProvider" + ] + } + }, "autoload": { "psr-4": { - "Spatie\\Macroable\\": "src" + "Spatie\\StructureDiscoverer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -5656,23 +7087,30 @@ ], "authors": [ { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://spatie.be", + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", "role": "Developer" } ], - "description": "A trait to dynamically add methods to a class", - "homepage": "https://github.com/spatie/macroable", + "description": "Automatically discover structures within your PHP application", + "homepage": "https://github.com/spatie/php-structure-discoverer", "keywords": [ - "macroable", - "spatie" + "discover", + "laravel", + "php", + "php-structure-discoverer" ], "support": { - "issues": "https://github.com/spatie/macroable/issues", - "source": "https://github.com/spatie/macroable/tree/2.0.0" + "issues": "https://github.com/spatie/php-structure-discoverer/issues", + "source": "https://github.com/spatie/php-structure-discoverer/tree/2.3.1" }, - "time": "2021-03-26T22:39:02+00:00" + "funding": [ + { + "url": "https://github.com/LaravelAutoDiscoverer", + "type": "github" + } + ], + "time": "2025-02-14T10:18:38+00:00" }, { "name": "spatie/ssl-certificate", @@ -10677,181 +12115,6 @@ }, "time": "2025-07-22T14:01:30+00:00" }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.6.3", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94f8051919d1b0369a6bcc7931d679a511c03fe9", - "reference": "94f8051919d1b0369a6bcc7931d679a511c03fe9", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.1", - "ext-filter": "*", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.5 || ~1.6.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "psalm/phar": "^5.26" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.3" - }, - "time": "2025-08-01T19:43:32+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18|^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" - }, - "time": "2024-11-09T15:12:26+00:00" - }, { "name": "phpmyadmin/sql-parser", "version": "5.11.1", @@ -10941,53 +12204,6 @@ ], "time": "2025-07-20T15:49:56+00:00" }, - { - "name": "phpstan/phpdoc-parser", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8", - "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0" - }, - "time": "2025-07-13T07:04:09+00:00" - }, { "name": "phpstan/phpstan", "version": "2.1.22", diff --git a/config/data.php b/config/data.php new file mode 100644 index 0000000000..1c992865c6 --- /dev/null +++ b/config/data.php @@ -0,0 +1,199 @@ + DATE_ATOM, + + /* + * When transforming or casting dates, the following timezone will be used to + * convert the date to the correct timezone. If set to null no timezone will + * be passed. + */ + 'date_timezone' => null, + + /* + * It is possible to enable certain features of the package, these would otherwise + * be breaking changes, and thus they are disabled by default. In the next major + * version of the package, these features will be enabled by default. + */ + 'features' => [ + 'cast_and_transform_iterables' => false, + + /* + * When trying to set a computed property value, the package will throw an exception. + * You can disable this behavior by setting this option to true, which will then just + * ignore the value being passed into the computed property and recalculate it. + */ + 'ignore_exception_when_trying_to_set_computed_property_value' => false, + ], + + /* + * Global transformers will take complex types and transform them into simple + * types. + */ + 'transformers' => [ + DateTimeInterface::class => Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer::class, + Illuminate\Contracts\Support\Arrayable::class => Spatie\LaravelData\Transformers\ArrayableTransformer::class, + BackedEnum::class => Spatie\LaravelData\Transformers\EnumTransformer::class, + ], + + /* + * Global casts will cast values into complex types when creating a data + * object from simple types. + */ + 'casts' => [ + DateTimeInterface::class => Spatie\LaravelData\Casts\DateTimeInterfaceCast::class, + BackedEnum::class => Spatie\LaravelData\Casts\EnumCast::class, + // Enumerable::class => Spatie\LaravelData\Casts\EnumerableCast::class, + ], + + /* + * Rule inferrers can be configured here. They will automatically add + * validation rules to properties of a data object based upon + * the type of the property. + */ + 'rule_inferrers' => [ + Spatie\LaravelData\RuleInferrers\SometimesRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\NullableRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\RequiredRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\BuiltInTypesRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\AttributesRuleInferrer::class, + ], + + /* + * Normalizers return an array representation of the payload, or null if + * it cannot normalize the payload. The normalizers below are used for + * every data object, unless overridden in a specific data object class. + */ + 'normalizers' => [ + Spatie\LaravelData\Normalizers\ModelNormalizer::class, + // Spatie\LaravelData\Normalizers\FormRequestNormalizer::class, + Spatie\LaravelData\Normalizers\ArrayableNormalizer::class, + Spatie\LaravelData\Normalizers\ObjectNormalizer::class, + Spatie\LaravelData\Normalizers\ArrayNormalizer::class, + Spatie\LaravelData\Normalizers\JsonNormalizer::class, + ], + + /* + * Data objects can be wrapped into a key like 'data' when used as a resource, + * this key can be set globally here for all data objects. You can pass in + * `null` if you want to disable wrapping. + */ + 'wrap' => null, + + /* + * Adds a specific caster to the Symphony VarDumper component which hides + * some properties from data objects and collections when being dumped + * by `dump` or `dd`. Can be 'enabled', 'disabled' or 'development' + * which will only enable the caster locally. + */ + 'var_dumper_caster_mode' => 'development', + + /* + * It is possible to skip the PHP reflection analysis of data objects + * when running in production. This will speed up the package. You + * can configure where data objects are stored and which cache + * store should be used. + * + * Structures are cached forever as they'll become stale when your + * application is deployed with changes. You can set a duration + * in seconds if you want the cache to clear after a certain + * timeframe. + */ + 'structure_caching' => [ + 'enabled' => true, + 'directories' => [app_path('Data')], + 'cache' => [ + 'store' => env('CACHE_STORE', env('CACHE_DRIVER', 'file')), + 'prefix' => 'laravel-data', + 'duration' => null, + ], + 'reflection_discovery' => [ + 'enabled' => true, + 'base_path' => base_path(), + 'root_namespace' => null, + ], + ], + + /* + * A data object can be validated when created using a factory or when calling the from + * method. By default, only when a request is passed the data is being validated. This + * behavior can be changed to always validate or to completely disable validation. + */ + 'validation_strategy' => Spatie\LaravelData\Support\Creation\ValidationStrategy::OnlyRequests->value, + + /* + * A data object can map the names of its properties when transforming (output) or when + * creating (input). By default, the package will not map any names. You can set a + * global strategy here, or override it on a specific data object. + */ + 'name_mapping_strategy' => [ + 'input' => SnakeCaseMapper::class, + 'output' => SnakeCaseMapper::class, + ], + + /* + * When using an invalid include, exclude, only or except partial, the package will + * throw an exception. You can disable this behavior by setting this option to true. + */ + 'ignore_invalid_partials' => false, + + /* + * When transforming a nested chain of data objects, the package can end up in an infinite + * loop when including a recursive relationship. The max transformation depth can be + * set as a safety measure to prevent this from happening. When set to null, the + * package will not enforce a maximum depth. + */ + 'max_transformation_depth' => null, + + /* + * When the maximum transformation depth is reached, the package will throw an exception. + * You can disable this behavior by setting this option to true which will return an + * empty array. + */ + 'throw_when_max_transformation_depth_reached' => true, + + /* + * When using the `make:data` command, the package will use these settings to generate + * the data classes. You can override these settings by passing options to the command. + */ + 'commands' => [ + /* + * Provides default configuration for the `make:data` command. These settings can be overridden with options + * passed directly to the `make:data` command for generating single Data classes, or if not set they will + * automatically fall back to these defaults. See `php artisan make:data --help` for more information + */ + 'make' => [ + /* + * The default namespace for generated Data classes. This exists under the application's root namespace, + * so the default 'Data` will end up as '\App\Data', and generated Data classes will be placed in the + * app/Data/ folder. Data classes can live anywhere, but this is where `make:data` will put them. + */ + 'namespace' => 'Data', + + /* + * This suffix will be appended to all data classes generated by make:data, so that they are less likely + * to conflict with other related classes, controllers or models with a similar name without resorting + * to adding an alias for the Data object. Set to a blank string (not null) to disable. + */ + 'suffix' => 'Data', + ], + ], + + /* + * When using Livewire, the package allows you to enable or disable the synths + * these synths will automatically handle the data objects and their + * properties when used in a Livewire component. + */ + 'livewire' => [ + 'enable_synths' => false, + ], +]; From 35f5842303c58d8fcfc8d15ab1f3deaee9911473 Mon Sep 17 00:00:00 2001 From: Roardom Date: Wed, 25 Jun 2025 04:38:47 +0000 Subject: [PATCH 2/6] refactor: use laravel-data for Type form requests --- app/Data/Staff/TypeData.php | 28 +++++++++++ app/Http/Controllers/Staff/TypeController.php | 11 ++--- app/Http/Requests/Staff/StoreTypeRequest.php | 47 ------------------- app/Http/Requests/Staff/UpdateTypeRequest.php | 47 ------------------- .../Controllers/Staff/TypeControllerTest.php | 19 -------- .../Requests/Staff/StoreTypeRequestTest.php | 40 ---------------- .../Requests/Staff/UpdateTypeRequestTest.php | 40 ---------------- 7 files changed, 33 insertions(+), 199 deletions(-) create mode 100644 app/Data/Staff/TypeData.php delete mode 100644 app/Http/Requests/Staff/StoreTypeRequest.php delete mode 100644 app/Http/Requests/Staff/UpdateTypeRequest.php delete mode 100644 tests/Unit/Http/Requests/Staff/StoreTypeRequestTest.php delete mode 100644 tests/Unit/Http/Requests/Staff/UpdateTypeRequestTest.php diff --git a/app/Data/Staff/TypeData.php b/app/Data/Staff/TypeData.php new file mode 100644 index 0000000000..ae52f407fe --- /dev/null +++ b/app/Data/Staff/TypeData.php @@ -0,0 +1,28 @@ + + * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 + */ + +namespace App\Data\Staff; + +use Spatie\LaravelData\Data; + +class TypeData extends Data +{ + public function __construct( + public string $name, + public int $position, + ) { + } +} diff --git a/app/Http/Controllers/Staff/TypeController.php b/app/Http/Controllers/Staff/TypeController.php index b2b35d08c3..f63a478680 100644 --- a/app/Http/Controllers/Staff/TypeController.php +++ b/app/Http/Controllers/Staff/TypeController.php @@ -16,9 +16,8 @@ namespace App\Http\Controllers\Staff; +use App\Data\Staff\TypeData; use App\Http\Controllers\Controller; -use App\Http\Requests\Staff\StoreTypeRequest; -use App\Http\Requests\Staff\UpdateTypeRequest; use App\Models\Type; use Exception; @@ -48,9 +47,9 @@ public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\Vi /** * Store A New Type. */ - public function store(StoreTypeRequest $request): \Illuminate\Http\RedirectResponse + public function store(TypeData $typeData): \Illuminate\Http\RedirectResponse { - Type::create($request->validated()); + Type::create($typeData->toArray()); return to_route('staff.types.index') ->with('success', 'Type Successfully Added'); @@ -69,9 +68,9 @@ public function edit(Type $type): \Illuminate\Contracts\View\Factory|\Illuminate /** * Edit A Type. */ - public function update(UpdateTypeRequest $request, Type $type): \Illuminate\Http\RedirectResponse + public function update(TypeData $typeData, Type $type): \Illuminate\Http\RedirectResponse { - $type->update($request->validated()); + $type->update($typeData->toArray()); return to_route('staff.types.index') ->with('success', 'Type Successfully Modified'); diff --git a/app/Http/Requests/Staff/StoreTypeRequest.php b/app/Http/Requests/Staff/StoreTypeRequest.php deleted file mode 100644 index f881ae4fcd..0000000000 --- a/app/Http/Requests/Staff/StoreTypeRequest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; - -class StoreTypeRequest extends FormRequest -{ - /** - * Determine if the user is authorized to make this request. - */ - public function authorize(): bool - { - return true; - } - - /** - * Get the validation rules that apply to the request. - * - * @return array|string> - */ - public function rules(): array - { - return [ - 'name' => [ - 'required', - ], - 'position' => [ - 'required', - ], - ]; - } -} diff --git a/app/Http/Requests/Staff/UpdateTypeRequest.php b/app/Http/Requests/Staff/UpdateTypeRequest.php deleted file mode 100644 index a81fc01eb0..0000000000 --- a/app/Http/Requests/Staff/UpdateTypeRequest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; - -class UpdateTypeRequest extends FormRequest -{ - /** - * Determine if the user is authorized to make this request. - */ - public function authorize(): bool - { - return true; - } - - /** - * Get the validation rules that apply to the request. - * - * @return array|string> - */ - public function rules(): array - { - return [ - 'name' => [ - 'required', - ], - 'position' => [ - 'required', - ], - ]; - } -} diff --git a/tests/Feature/Http/Controllers/Staff/TypeControllerTest.php b/tests/Feature/Http/Controllers/Staff/TypeControllerTest.php index 8eba238519..add2e0ac3f 100644 --- a/tests/Feature/Http/Controllers/Staff/TypeControllerTest.php +++ b/tests/Feature/Http/Controllers/Staff/TypeControllerTest.php @@ -14,9 +14,6 @@ * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 */ -use App\Http\Controllers\Staff\TypeController; -use App\Http\Requests\Staff\StoreTypeRequest; -use App\Http\Requests\Staff\UpdateTypeRequest; use App\Models\Type; use function Pest\Laravel\assertDatabaseHas; @@ -55,14 +52,6 @@ ->assertViewHas('types'); }); -test('store validates with a form request', function (): void { - $this->assertActionUsesFormRequest( - TypeController::class, - 'store', - StoreTypeRequest::class - ); -}); - test('store returns an ok response', function (): void { $type = Type::factory()->make(); @@ -79,14 +68,6 @@ ]); }); -test('update validates with a form request', function (): void { - $this->assertActionUsesFormRequest( - TypeController::class, - 'update', - UpdateTypeRequest::class - ); -}); - test('update returns an ok response', function (): void { $type = Type::factory()->create(); diff --git a/tests/Unit/Http/Requests/Staff/StoreTypeRequestTest.php b/tests/Unit/Http/Requests/Staff/StoreTypeRequestTest.php deleted file mode 100644 index 38ceaecea6..0000000000 --- a/tests/Unit/Http/Requests/Staff/StoreTypeRequestTest.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -use App\Http\Requests\Staff\StoreTypeRequest; - -beforeEach(function (): void { - $this->subject = new StoreTypeRequest(); -}); - -test('authorize', function (): void { - $actual = $this->subject->authorize(); - - expect($actual)->toBeTrue(); -}); - -test('rules', function (): void { - $actual = $this->subject->rules(); - - $this->assertValidationRules([ - 'name' => [ - 'required', - ], - 'position' => [ - 'required', - ], - ], $actual); -}); diff --git a/tests/Unit/Http/Requests/Staff/UpdateTypeRequestTest.php b/tests/Unit/Http/Requests/Staff/UpdateTypeRequestTest.php deleted file mode 100644 index af2baec9c1..0000000000 --- a/tests/Unit/Http/Requests/Staff/UpdateTypeRequestTest.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -use App\Http\Requests\Staff\UpdateTypeRequest; - -beforeEach(function (): void { - $this->subject = new UpdateTypeRequest(); -}); - -test('authorize', function (): void { - $actual = $this->subject->authorize(); - - expect($actual)->toBeTrue(); -}); - -test('rules', function (): void { - $actual = $this->subject->rules(); - - $this->assertValidationRules([ - 'name' => [ - 'required', - ], - 'position' => [ - 'required', - ], - ], $actual); -}); From 7529300646ad2e1a2264953e9b57be5c202bdc6c Mon Sep 17 00:00:00 2001 From: Roardom Date: Sun, 21 Sep 2025 05:13:30 +0000 Subject: [PATCH 3/6] add: FromCurrentUserId Attribute for laravel-data --- app/Attributes/FromCurrentUserId.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 app/Attributes/FromCurrentUserId.php diff --git a/app/Attributes/FromCurrentUserId.php b/app/Attributes/FromCurrentUserId.php new file mode 100644 index 0000000000..bfb361f688 --- /dev/null +++ b/app/Attributes/FromCurrentUserId.php @@ -0,0 +1,14 @@ + Date: Wed, 25 Jun 2025 07:28:51 +0000 Subject: [PATCH 4/6] refactor: use laravel-data for Article form requests --- app/Data/Staff/ArticleData.php | 37 +++++++++++++ .../Controllers/Staff/ArticleController.php | 31 ++++------- .../Requests/Staff/StoreArticleRequest.php | 54 ------------------- .../Requests/Staff/UpdateArticleRequest.php | 54 ------------------- .../Staff/StoreArticleRequestTest.php | 47 ---------------- .../Staff/UpdateArticleRequestTest.php | 47 ---------------- 6 files changed, 48 insertions(+), 222 deletions(-) create mode 100644 app/Data/Staff/ArticleData.php delete mode 100644 app/Http/Requests/Staff/StoreArticleRequest.php delete mode 100644 app/Http/Requests/Staff/UpdateArticleRequest.php delete mode 100644 tests/Unit/Http/Requests/Staff/StoreArticleRequestTest.php delete mode 100644 tests/Unit/Http/Requests/Staff/UpdateArticleRequestTest.php diff --git a/app/Data/Staff/ArticleData.php b/app/Data/Staff/ArticleData.php new file mode 100644 index 0000000000..bd3be07ccd --- /dev/null +++ b/app/Data/Staff/ArticleData.php @@ -0,0 +1,37 @@ + + * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 + */ + +namespace App\Data\Staff; + +use Illuminate\Http\UploadedFile; +use App\Attributes\FromCurrentUserId; +use Spatie\LaravelData\Attributes\Validation\Max; +use Spatie\LaravelData\Data; + +class ArticleData extends Data +{ + public function __construct( + #[Max(255)] + public string $title, + #[Max(65535)] + public string $content, + #[Max(10240)] + public ?UploadedFile $image, + #[FromCurrentUserId] + public int $userId, + ) { + } +} diff --git a/app/Http/Controllers/Staff/ArticleController.php b/app/Http/Controllers/Staff/ArticleController.php index 81e2ae2e25..70e204cfb3 100644 --- a/app/Http/Controllers/Staff/ArticleController.php +++ b/app/Http/Controllers/Staff/ArticleController.php @@ -16,9 +16,8 @@ namespace App\Http\Controllers\Staff; +use App\Data\Staff\ArticleData; use App\Http\Controllers\Controller; -use App\Http\Requests\Staff\StoreArticleRequest; -use App\Http\Requests\Staff\UpdateArticleRequest; use App\Models\Article; use App\Models\UnreadArticle; use App\Models\User; @@ -55,19 +54,15 @@ public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\Vi /** * Store A New Article. */ - public function store(StoreArticleRequest $request): \Illuminate\Http\RedirectResponse + public function store(ArticleData $data): \Illuminate\Http\RedirectResponse { - if ($request->hasFile('image')) { - $image = $request->file('image'); - - abort_if(\is_array($image), 400); - - $filename = 'article-'.uniqid('', true).'.'.$image->getClientOriginalExtension(); + if ($data->image !== null) { + $filename = 'article-'.uniqid('', true).'.'.$data->image->getClientOriginalExtension(); $path = Storage::disk('article-images')->path($filename); - Image::make($image->getRealPath())->fit(75, 75)->encode('png', 100)->save($path); + Image::make($data->image->getRealPath())->fit(75, 75)->encode('png', 100)->save($path); } - $article = Article::create(['user_id' => $request->user()->id, 'image' => $filename ?? null] + $request->validated()); + $article = Article::create(['image' => $filename ?? null] + $data->toArray()); UnreadArticle::query()->insertUsing( ['article_id', 'user_id'], @@ -94,23 +89,19 @@ public function edit(Article $article): \Illuminate\Contracts\View\Factory|\Illu /** * Edit A Article. */ - public function update(UpdateArticleRequest $request, Article $article): \Illuminate\Http\RedirectResponse + public function update(ArticleData $data, Article $article): \Illuminate\Http\RedirectResponse { - if ($request->hasFile('image')) { - $image = $request->file('image'); - - abort_if(\is_array($image), 400); - - $filename = 'article-'.uniqid('', true).'.'.$image->getClientOriginalExtension(); + if ($data->image !== null) { + $filename = 'article-'.uniqid('', true).'.'.$data->image->getClientOriginalExtension(); $path = Storage::disk('article-images')->path($filename); - Image::make($image->getRealPath())->fit(75, 75)->encode('png', 100)->save($path); + Image::make($data->image->getRealPath())->fit(75, 75)->encode('png', 100)->save($path); if ($article->image !== null) { Storage::disk('article-images')->delete($article->image); } } - $article->update(['image' => $filename ?? null,] + $request->validated()); + $article->update(['image' => $filename ?? null,] + $data->toArray()); return to_route('staff.articles.index') ->with('success', 'Your article changes have successfully published!'); diff --git a/app/Http/Requests/Staff/StoreArticleRequest.php b/app/Http/Requests/Staff/StoreArticleRequest.php deleted file mode 100644 index a9e794786d..0000000000 --- a/app/Http/Requests/Staff/StoreArticleRequest.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; - -class StoreArticleRequest extends FormRequest -{ - /** - * Determine if the user is authorized to make this request. - */ - public function authorize(): bool - { - return true; - } - - /** - * Get the validation rules that apply to the request. - * - * @return array|string> - */ - public function rules(): array - { - return [ - 'title' => [ - 'required', - 'string', - 'max:255', - ], - 'content' => [ - 'required', - 'string', - 'max:65536', - ], - 'image' => [ - 'max:10240', - ], - ]; - } -} diff --git a/app/Http/Requests/Staff/UpdateArticleRequest.php b/app/Http/Requests/Staff/UpdateArticleRequest.php deleted file mode 100644 index e92a4f7e0d..0000000000 --- a/app/Http/Requests/Staff/UpdateArticleRequest.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; - -class UpdateArticleRequest extends FormRequest -{ - /** - * Determine if the user is authorized to make this request. - */ - public function authorize(): bool - { - return true; - } - - /** - * Get the validation rules that apply to the request. - * - * @return array|string> - */ - public function rules(): array - { - return [ - 'title' => [ - 'required', - 'string', - 'max:255', - ], - 'content' => [ - 'required', - 'string', - 'max:65536', - ], - 'image' => [ - 'max:10240', - ], - ]; - } -} diff --git a/tests/Unit/Http/Requests/Staff/StoreArticleRequestTest.php b/tests/Unit/Http/Requests/Staff/StoreArticleRequestTest.php deleted file mode 100644 index 25e8cfc66b..0000000000 --- a/tests/Unit/Http/Requests/Staff/StoreArticleRequestTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -use App\Http\Requests\Staff\StoreArticleRequest; - -beforeEach(function (): void { - $this->subject = new StoreArticleRequest(); -}); - -test('authorize', function (): void { - $actual = $this->subject->authorize(); - - expect($actual)->toBeTrue(); -}); - -test('rules', function (): void { - $actual = $this->subject->rules(); - - $this->assertValidationRules([ - 'title' => [ - 'required', - 'string', - 'max:255', - ], - 'content' => [ - 'required', - 'string', - 'max:65536', - ], - 'image' => [ - 'max:10240', - ], - ], $actual); -}); diff --git a/tests/Unit/Http/Requests/Staff/UpdateArticleRequestTest.php b/tests/Unit/Http/Requests/Staff/UpdateArticleRequestTest.php deleted file mode 100644 index b52c37d8a3..0000000000 --- a/tests/Unit/Http/Requests/Staff/UpdateArticleRequestTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -use App\Http\Requests\Staff\UpdateArticleRequest; - -beforeEach(function (): void { - $this->subject = new UpdateArticleRequest(); -}); - -test('authorize', function (): void { - $actual = $this->subject->authorize(); - - expect($actual)->toBeTrue(); -}); - -test('rules', function (): void { - $actual = $this->subject->rules(); - - $this->assertValidationRules([ - 'title' => [ - 'required', - 'string', - 'max:255', - ], - 'content' => [ - 'required', - 'string', - 'max:65536', - ], - 'image' => [ - 'max:10240', - ], - ], $actual); -}); From 4d4dbc08220a21f4bad4c20df186388a75225304 Mon Sep 17 00:00:00 2001 From: Roardom Date: Mon, 30 Jun 2025 08:21:28 +0000 Subject: [PATCH 5/6] refactor: use laravel-data for AutomaticTorrentFreeleech form requests --- .../Staff/AutomaticTorrentFreeleechData.php | 64 +++++++++++++++++++ .../AutomaticTorrentFreeleechController.php | 11 ++-- .../StoreAutomaticTorrentFreeleechRequest.php | 48 -------------- ...UpdateAutomaticTorrentFreeleechRequest.php | 48 -------------- phpstan-baseline.neon | 12 ---- 5 files changed, 69 insertions(+), 114 deletions(-) create mode 100644 app/Data/Staff/AutomaticTorrentFreeleechData.php delete mode 100644 app/Http/Requests/Staff/StoreAutomaticTorrentFreeleechRequest.php delete mode 100644 app/Http/Requests/Staff/UpdateAutomaticTorrentFreeleechRequest.php diff --git a/app/Data/Staff/AutomaticTorrentFreeleechData.php b/app/Data/Staff/AutomaticTorrentFreeleechData.php new file mode 100644 index 0000000000..9bdc752b72 --- /dev/null +++ b/app/Data/Staff/AutomaticTorrentFreeleechData.php @@ -0,0 +1,64 @@ + + * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 + */ + +namespace App\Data\Staff; + +use App\Models\Category; +use App\Models\Resolution; +use App\Models\Type; +use Closure; +use Spatie\LaravelData\Attributes\MergeValidationRules; +use Spatie\LaravelData\Attributes\Validation\Exists; +use Spatie\LaravelData\Attributes\Validation\Max; +use Spatie\LaravelData\Attributes\Validation\Min; +use Spatie\LaravelData\Data; + +#[MergeValidationRules] +class AutomaticTorrentFreeleechData extends Data +{ + public function __construct( + public ?string $nameRegex, + #[Min(0)] + public ?int $position, + #[Min(0)] + public ?int $size, + #[Exists(Category::class)] + public ?int $categoryId, + #[Exists(Type::class)] + public ?int $typeId, + #[Exists(Resolution::class)] + public ?int $resolutionId, + #[Min(0), Max(100)] + public int $freeleechPercentage, + ) { + } + + /** + * @return array> + */ + public static function rules(): array + { + return [ + 'name_regex' => [ + function (string $attribute, mixed $value, Closure $fail): void { + if (@preg_match($value, 'Validate regex') === false) { + $fail('Regex syntax error.'); + } + }, + ], + ]; + } +} diff --git a/app/Http/Controllers/Staff/AutomaticTorrentFreeleechController.php b/app/Http/Controllers/Staff/AutomaticTorrentFreeleechController.php index 54302809af..c628511be4 100644 --- a/app/Http/Controllers/Staff/AutomaticTorrentFreeleechController.php +++ b/app/Http/Controllers/Staff/AutomaticTorrentFreeleechController.php @@ -16,9 +16,8 @@ namespace App\Http\Controllers\Staff; +use App\Data\Staff\AutomaticTorrentFreeleechData; use App\Http\Controllers\Controller; -use App\Http\Requests\Staff\StoreAutomaticTorrentFreeleechRequest; -use App\Http\Requests\Staff\UpdateAutomaticTorrentFreeleechRequest; use App\Models\AutomaticTorrentFreeleech; use App\Models\Category; use App\Models\Resolution; @@ -42,9 +41,9 @@ public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\Vi ]); } - public function store(StoreAutomaticTorrentFreeleechRequest $request): \Illuminate\Http\RedirectResponse + public function store(AutomaticTorrentFreeleechData $data): \Illuminate\Http\RedirectResponse { - AutomaticTorrentFreeleech::create($request->validated()); + AutomaticTorrentFreeleech::create($data->toArray()); return to_route('staff.automatic_torrent_freeleeches.index') ->with('success', 'Resolution Successfully Added'); @@ -60,9 +59,9 @@ public function edit(AutomaticTorrentFreeleech $automaticTorrentFreeleech): \Ill ]); } - public function update(UpdateAutomaticTorrentFreeleechRequest $request, AutomaticTorrentFreeleech $automaticTorrentFreeleech): \Illuminate\Http\RedirectResponse + public function update(AutomaticTorrentFreeleechData $data, AutomaticTorrentFreeleech $automaticTorrentFreeleech): \Illuminate\Http\RedirectResponse { - $automaticTorrentFreeleech->update($request->validated()); + $automaticTorrentFreeleech->update($data->toArray()); return to_route('staff.automatic_torrent_freeleeches.index') ->with('success', 'Resolution Successfully Modified'); diff --git a/app/Http/Requests/Staff/StoreAutomaticTorrentFreeleechRequest.php b/app/Http/Requests/Staff/StoreAutomaticTorrentFreeleechRequest.php deleted file mode 100644 index fd8b606b6c..0000000000 --- a/app/Http/Requests/Staff/StoreAutomaticTorrentFreeleechRequest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; -use Closure; - -class StoreAutomaticTorrentFreeleechRequest extends FormRequest -{ - /** - * Get the validation rules that apply to the request. - * - * @return array> - */ - public function rules(): array - { - return [ - 'name_regex' => [ - 'nullable', - function (string $attribute, mixed $value, Closure $fail): void { - if (@preg_match($value, 'Validate regex') === false) { - $fail('Regex syntax error.'); - } - }, - ], - 'position' => ['required', 'integer', 'min:0'], - 'size' => ['nullable', 'integer', 'min:0'], - 'category_id' => ['nullable', 'integer', 'exists:categories,id'], - 'type_id' => ['nullable', 'integer', 'exists:types,id'], - 'resolution_id' => ['nullable', 'integer', 'exists:resolutions,id'], - 'freeleech_percentage' => ['required', 'integer', 'max:100', 'min:0'], - ]; - } -} diff --git a/app/Http/Requests/Staff/UpdateAutomaticTorrentFreeleechRequest.php b/app/Http/Requests/Staff/UpdateAutomaticTorrentFreeleechRequest.php deleted file mode 100644 index 9ed13b791a..0000000000 --- a/app/Http/Requests/Staff/UpdateAutomaticTorrentFreeleechRequest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; -use Closure; - -class UpdateAutomaticTorrentFreeleechRequest extends FormRequest -{ - /** - * Get the validation rules that apply to the request. - * - * @return array>. - */ - public function rules(): array - { - return [ - 'name_regex' => [ - 'nullable', - function (string $attribute, mixed $value, Closure $fail): void { - if (@preg_match($value, 'Validate regex') === false) { - $fail('Regex syntax error.'); - } - }, - ], - 'position' => ['required', 'integer', 'min:0'], - 'size' => ['nullable', 'integer', 'min:0'], - 'category_id' => ['nullable', 'integer', 'exists:categories,id'], - 'type_id' => ['nullable', 'integer', 'exists:types,id'], - 'resolution_id' => ['nullable', 'integer', 'exists:resolutions,id'], - 'freeleech_percentage' => ['required', 'integer', 'max:100', 'min:0'], - ]; - } -} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 060c9f4146..d0c8c39fd3 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -552,18 +552,6 @@ parameters: count: 1 path: app/Http/Middleware/SetLanguage.php - - - message: '#^Method App\\Http\\Requests\\Staff\\UpdateAutomaticTorrentFreeleechRequest\:\:rules\(\) return type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: app/Http/Requests/Staff/UpdateAutomaticTorrentFreeleechRequest.php - - - - message: '#^PHPDoc tag @return has invalid value \(array\\>\.\)\: Unexpected token "\.", expected TOKEN_HORIZONTAL_WS at offset 128 on line 4$#' - identifier: phpDoc.parseError - count: 1 - path: app/Http/Requests/Staff/UpdateAutomaticTorrentFreeleechRequest.php - - message: '#^Method App\\Http\\Requests\\StoreRequestFillRequest\:\:rules\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue From f6f106afc9a14fe8d0ccbe2d0ace67cdb77465ef Mon Sep 17 00:00:00 2001 From: Roardom Date: Sun, 21 Sep 2025 05:33:30 +0000 Subject: [PATCH 6/6] refactpr: use laravel-data for Ban form requests --- app/Data/Staff/BanData.php | 36 ++++++++++++++ app/Http/Controllers/Staff/BanController.php | 9 ++-- app/Http/Requests/Staff/StoreBanRequest.php | 50 -------------------- 3 files changed, 41 insertions(+), 54 deletions(-) create mode 100644 app/Data/Staff/BanData.php delete mode 100644 app/Http/Requests/Staff/StoreBanRequest.php diff --git a/app/Data/Staff/BanData.php b/app/Data/Staff/BanData.php new file mode 100644 index 0000000000..5776ffaa13 --- /dev/null +++ b/app/Data/Staff/BanData.php @@ -0,0 +1,36 @@ + + * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 + */ + +namespace App\Data\Staff; + +use App\Attributes\FromCurrentUserId; +use App\Models\User; +use Spatie\LaravelData\Attributes\Validation\Exists; +use Spatie\LaravelData\Attributes\Validation\Max; +use Spatie\LaravelData\Data; + +class BanData extends Data +{ + public function __construct( + #[Max(65535)] + public string $banReason, + #[Exists(User::class, 'id')] + public int $ownedBy, + #[FromCurrentUserId] + public int $createdBy, + ) { + } +} diff --git a/app/Http/Controllers/Staff/BanController.php b/app/Http/Controllers/Staff/BanController.php index 1de340407e..b3a2d6e0f4 100644 --- a/app/Http/Controllers/Staff/BanController.php +++ b/app/Http/Controllers/Staff/BanController.php @@ -16,6 +16,7 @@ namespace App\Http\Controllers\Staff; +use App\Data\Staff\BanData; use App\Http\Controllers\Controller; use App\Http\Requests\Staff\StoreBanRequest; use App\Models\Ban; @@ -24,6 +25,7 @@ use App\Notifications\UserBan; use App\Services\Unit3dAnnounce; use Exception; +use Illuminate\Container\Attributes\CurrentUser; /** * @see \Tests\Todo\Feature\Http\Controllers\Staff\BanControllerTest @@ -45,10 +47,9 @@ public function index(): \Illuminate\Contracts\View\Factory|\Illuminate\View\Vie * * @throws Exception */ - public function store(StoreBanRequest $request): \Illuminate\Http\RedirectResponse + public function store(BanData $data, #[CurrentUser] User $staff): \Illuminate\Http\RedirectResponse { - $user = User::findOrFail($request->string('owned_by')); - $staff = $request->user(); + $user = User::findOrFail($data->ownedBy); abort_if($user->group->is_modo || $staff->is($user), 403); @@ -57,7 +58,7 @@ public function store(StoreBanRequest $request): \Illuminate\Http\RedirectRespon 'can_download' => 0, ]); - $ban = Ban::create(['created_by' => $staff->id] + $request->validated()); + $ban = Ban::create($data->toArray()); cache()->forget('user:'.$user->passkey); diff --git a/app/Http/Requests/Staff/StoreBanRequest.php b/app/Http/Requests/Staff/StoreBanRequest.php deleted file mode 100644 index ec732c7587..0000000000 --- a/app/Http/Requests/Staff/StoreBanRequest.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 - */ - -namespace App\Http\Requests\Staff; - -use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Validation\Rule; - -class StoreBanRequest extends FormRequest -{ - /** - * Determine if the user is authorized to make this request. - */ - public function authorize(): bool - { - return true; - } - - /** - * Get the validation rules that apply to the request. - * - * @return array> - */ - public function rules(): array - { - return [ - 'owned_by' => [ - Rule::exists('users', 'id') - ], - 'ban_reason' => [ - 'required', - 'string', - 'max:65536', - ], - ]; - } -}