From f009b31a68196520f21e5cc1a71d94da77026b4b Mon Sep 17 00:00:00 2001 From: Bubka <858858+Bubka@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:28:45 +0200 Subject: [PATCH] Add Store icons to database feature --- _ide_helper.php | 1445 +++++++++++------ app/Api/v1/Controllers/IconController.php | 25 +- .../v1/Controllers/TwoFAccountController.php | 3 + .../Resources/TwoFAccountExportResource.php | 5 +- .../v1/Resources/TwoFAccountReadResource.php | 2 +- .../v1/Resources/TwoFAccountStoreResource.php | 3 +- .../{IconGenerator.php => DemoIcons.php} | 9 +- app/Console/Commands/Utils/ResetTrait.php | 29 +- .../storeIconsInDatabaseSettingChanged.php | 27 + ...iledIconStoreDatabaseTogglingException.php | 12 + app/Exceptions/Handler.php | 6 + app/Facades/IconStore.php | 17 + app/Facades/Icons.php | 17 + app/Helpers/Helpers.php | 10 + app/Listeners/CleanIconStorage.php | 5 +- .../ToggleIconReplicationToDatabase.php | 24 + app/Models/AuthLog.php | 16 +- app/Models/Group.php | 3 +- app/Models/Icon.php | 111 ++ app/Models/Option.php | 2 - app/Models/Traits/CanEncryptField.php | 35 + app/Models/TwoFAccount.php | 60 +- app/Models/User.php | 4 +- app/Observers/UserObserver.php | 6 +- app/Providers/EventServiceProvider.php | 6 + app/Providers/TwoFAuthServiceProvider.php | 11 +- app/Services/IconService.php | 60 +- app/Services/IconStoreService.php | 276 ++++ app/Services/LogoService.php | 31 +- app/Services/SettingService.php | 46 +- config/2fauth.php | 1 + config/filesystems.php | 13 + database/factories/IconFactory.php | 86 + ..._change_nullable_in_twofaccounts_table.php | 7 +- ...3136_encrypt_twofaccount_service_field.php | 5 +- .../2024_09_30_110610_create_icons_table.php | 28 + database/seeders/TestingSeeder.php | 2 - resources/js/icons.js | 2 +- resources/js/views/admin/AppSetup.vue | 5 +- resources/js/views/twofaccounts/Accounts.vue | 3 +- resources/lang/en/admin.php | 9 +- resources/lang/en/errors.php | 1 + .../Api/v1/Controllers/IconControllerTest.php | 47 +- .../Controllers/TwoFAccountControllerTest.php | 56 +- tests/Data/HttpRequestTestData.php | 45 +- tests/Data/OtpTestData.php | 18 +- .../Feature/Console/CheckDbConnectionTest.php | 1 - tests/Feature/Models/TwoFAccountModelTest.php | 37 +- tests/Feature/Models/UserModelTest.php | 10 +- tests/Feature/Services/IconServiceTest.php | 275 +++- .../Feature/Services/IconStoreServiceTest.php | 743 +++++++++ tests/Feature/Services/LogoServiceTest.php | 67 +- tests/Feature/Services/SettingServiceTest.php | 102 +- ...storeIconsInDatabaseSettingChangedTest.php | 24 + tests/Unit/IconModelTest.php | 118 ++ tests/Unit/Listeners/CleanIconStorageTest.php | 35 +- .../ToggleIconReplicationToDatabaseTest.php | 28 + tests/Unit/MigratorTest.php | 22 +- tests/Unit/TwoFAccountModelTest.php | 11 + 59 files changed, 3268 insertions(+), 839 deletions(-) rename app/Console/Commands/Utils/{IconGenerator.php => DemoIcons.php} (99%) create mode 100644 app/Events/storeIconsInDatabaseSettingChanged.php create mode 100644 app/Exceptions/FailedIconStoreDatabaseTogglingException.php create mode 100644 app/Facades/IconStore.php create mode 100644 app/Facades/Icons.php create mode 100644 app/Listeners/ToggleIconReplicationToDatabase.php create mode 100644 app/Models/Icon.php create mode 100644 app/Models/Traits/CanEncryptField.php create mode 100644 app/Services/IconStoreService.php create mode 100644 database/factories/IconFactory.php create mode 100644 database/migrations/2024_09_30_110610_create_icons_table.php create mode 100644 tests/Feature/Services/IconStoreServiceTest.php create mode 100644 tests/Unit/Events/storeIconsInDatabaseSettingChangedTest.php create mode 100644 tests/Unit/IconModelTest.php create mode 100644 tests/Unit/Listeners/ToggleIconReplicationToDatabaseTest.php diff --git a/_ide_helper.php b/_ide_helper.php index 903ffca7..b8e66d7e 100644 --- a/_ide_helper.php +++ b/_ide_helper.php @@ -5,7 +5,7 @@ /** * A helper file for Laravel, to provide autocomplete information to your IDE - * Generated for Laravel 11.11.1. + * Generated for Laravel 11.23.5. * * This file should not be included in your code, only analyzed by your IDE! * @@ -566,6 +566,7 @@ * @param string $abstract * @param array $parameters * @return mixed + * @throws \Illuminate\Contracts\Container\BindingResolutionException * @static */ public static function make($abstract, $parameters = []) { @@ -1013,6 +1014,18 @@ { //Method inherited from \Illuminate\Container\Container /** @var \Illuminate\Foundation\Application $instance */ return $instance->when($concrete); + } + /** + * Define a contextual binding based on an attribute. + * + * @param string $attribute + * @param \Closure $handler + * @return void + * @static + */ public static function whenHasAttribute($attribute, $handler) + { //Method inherited from \Illuminate\Container\Container + /** @var \Illuminate\Foundation\Application $instance */ + $instance->whenHasAttribute($attribute, $handler); } /** * Returns true if the container can return an entry for the given identifier. @@ -1349,6 +1362,17 @@ { //Method inherited from \Illuminate\Container\Container /** @var \Illuminate\Foundation\Application $instance */ return $instance->build($concrete); + } + /** + * Resolve a dependency based on an attribute. + * + * @param \ReflectionAttribute $attribute + * @return mixed + * @static + */ public static function resolveFromAttribute($attribute) + { //Method inherited from \Illuminate\Container\Container + /** @var \Illuminate\Foundation\Application $instance */ + return $instance->resolveFromAttribute($attribute); } /** * Register a new before resolving callback for all types. @@ -1385,6 +1409,30 @@ { //Method inherited from \Illuminate\Container\Container /** @var \Illuminate\Foundation\Application $instance */ $instance->afterResolving($abstract, $callback); + } + /** + * Register a new after resolving attribute callback for all types. + * + * @param string $attribute + * @param \Closure $callback + * @return void + * @static + */ public static function afterResolvingAttribute($attribute, $callback) + { //Method inherited from \Illuminate\Container\Container + /** @var \Illuminate\Foundation\Application $instance */ + $instance->afterResolvingAttribute($attribute, $callback); + } + /** + * Fire all of the after resolving attribute callbacks. + * + * @param \ReflectionAttribute[] $abstract + * @param mixed $object + * @return void + * @static + */ public static function fireAfterResolvingAttributeCallbacks($attributes, $object) + { //Method inherited from \Illuminate\Container\Container + /** @var \Illuminate\Foundation\Application $instance */ + $instance->fireAfterResolvingAttributeCallbacks($attributes, $object); } /** * Get the container's bindings. @@ -3532,13 +3580,23 @@ { /** @var \Illuminate\Support\Testing\Fakes\BusFake $instance */ return $instance->serializeAndRestore($serializeAndRestore); + } + /** + * Get the batches that have been dispatched. + * + * @return array + * @static + */ public static function dispatchedBatches() + { + /** @var \Illuminate\Support\Testing\Fakes\BusFake $instance */ + return $instance->dispatchedBatches(); } } /** * * * @see \Illuminate\Cache\CacheManager - * @mixin \Illuminate\Cache\Repository + * @see \Illuminate\Cache\Repository */ class Cache { /** * Get a cache store instance by name, wrapped in a repository. @@ -3888,6 +3946,21 @@ { /** @var \Illuminate\Cache\Repository $instance */ return $instance->rememberForever($key, $callback); + } + /** + * Retrieve an item from the cache by key, refreshing it in the background if it is stale. + * + * @template TCacheValue + * @param string $key + * @param \Illuminate\Cache\array{ 0: int, 1: int } $ttl + * @param \Illuminate\Cache\(callable(): TCacheValue) $callback + * @param \Illuminate\Cache\array{ seconds?: int, owner?: string }|null $lock + * @return \Illuminate\Cache\TCacheValue + * @static + */ public static function flexible($key, $ttl, $callback, $lock = null) + { + /** @var \Illuminate\Cache\Repository $instance */ + return $instance->flexible($key, $ttl, $callback, $lock); } /** * Remove an item from the cache. @@ -4228,6 +4301,146 @@ /** * * + * @method static array run(\Closure|array $tasks) + * @method static \Illuminate\Foundation\Defer\DeferredCallback defer(\Closure|array $tasks) + * @see \Illuminate\Concurrency\ConcurrencyManager + */ class Concurrency { + /** + * Get a driver instance by name. + * + * @param string|null $name + * @return mixed + * @static + */ public static function driver($name = null) + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->driver($name); + } + /** + * Create an instance of the process concurrency driver. + * + * @param array $config + * @return \Illuminate\Concurrency\ProcessDriver + * @static + */ public static function createProcessDriver($config) + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->createProcessDriver($config); + } + /** + * Create an instance of the fork concurrency driver. + * + * @param array $config + * @return \Illuminate\Concurrency\ForkDriver + * @static + */ public static function createForkDriver($config) + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->createForkDriver($config); + } + /** + * Create an instance of the sync concurrency driver. + * + * @param array $config + * @return \Illuminate\Concurrency\SyncDriver + * @static + */ public static function createSyncDriver($config) + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->createSyncDriver($config); + } + /** + * Get the default instance name. + * + * @return string + * @static + */ public static function getDefaultInstance() + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->getDefaultInstance(); + } + /** + * Set the default instance name. + * + * @param string $name + * @return void + * @static + */ public static function setDefaultInstance($name) + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + $instance->setDefaultInstance($name); + } + /** + * Get the instance specific configuration. + * + * @param string $name + * @return array + * @static + */ public static function getInstanceConfig($name) + { + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->getInstanceConfig($name); + } + /** + * Get an instance by name. + * + * @param string|null $name + * @return mixed + * @static + */ public static function instance($name = null) + { //Method inherited from \Illuminate\Support\MultipleInstanceManager + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->instance($name); + } + /** + * Unset the given instances. + * + * @param array|string|null $name + * @return \Illuminate\Concurrency\ConcurrencyManager + * @static + */ public static function forgetInstance($name = null) + { //Method inherited from \Illuminate\Support\MultipleInstanceManager + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->forgetInstance($name); + } + /** + * Disconnect the given instance and remove from local cache. + * + * @param string|null $name + * @return void + * @static + */ public static function purge($name = null) + { //Method inherited from \Illuminate\Support\MultipleInstanceManager + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + $instance->purge($name); + } + /** + * Register a custom instance creator Closure. + * + * @param string $name + * @param \Closure $callback + * @return \Illuminate\Concurrency\ConcurrencyManager + * @static + */ public static function extend($name, $callback) + { //Method inherited from \Illuminate\Support\MultipleInstanceManager + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->extend($name, $callback); + } + /** + * Set the application instance used by the manager. + * + * @param \Illuminate\Contracts\Foundation\Application $app + * @return \Illuminate\Concurrency\ConcurrencyManager + * @static + */ public static function setApplication($app) + { //Method inherited from \Illuminate\Support\MultipleInstanceManager + /** @var \Illuminate\Concurrency\ConcurrencyManager $instance */ + return $instance->setApplication($app); + } + } + /** + * + * * @see \Illuminate\Config\Repository */ class Config { /** @@ -4671,6 +4884,34 @@ { /** @var \Illuminate\Log\Context\Repository $instance */ return $instance->pushHidden($key, ...$values); + } + /** + * Determine if the given value is in the given stack. + * + * @param string $key + * @param mixed $value + * @param bool $strict + * @return bool + * @throws \RuntimeException + * @static + */ public static function stackContains($key, $value, $strict = false) + { + /** @var \Illuminate\Log\Context\Repository $instance */ + return $instance->stackContains($key, $value, $strict); + } + /** + * Determine if the given value is in the given hidden stack. + * + * @param string $key + * @param mixed $value + * @param bool $strict + * @return bool + * @throws \RuntimeException + * @static + */ public static function hiddenStackContains($key, $value, $strict = false) + { + /** @var \Illuminate\Log\Context\Repository $instance */ + return $instance->hiddenStackContains($key, $value, $strict); } /** * Determine if the repository is empty. @@ -5297,7 +5538,7 @@ * @param string $name * @param array $config * @param bool $force - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function connectUsing($name, $config, $force = false) { @@ -5500,15 +5741,68 @@ { /** @var \Illuminate\Database\DatabaseManager $instance */ return $instance->macroCall($method, $parameters); + } + /** + * Get a human-readable name for the given connection driver. + * + * @return string + * @static + */ public static function getDriverTitle() + { + /** @var \Illuminate\Database\MySqlConnection $instance */ + return $instance->getDriverTitle(); + } + /** + * Run an insert statement against the database. + * + * @param string $query + * @param array $bindings + * @param string|null $sequence + * @return bool + * @static + */ public static function insert($query, $bindings = [], $sequence = null) + { + /** @var \Illuminate\Database\MySqlConnection $instance */ + return $instance->insert($query, $bindings, $sequence); + } + /** + * Get the connection's last insert ID. + * + * @return string|int|null + * @static + */ public static function getLastInsertId() + { + /** @var \Illuminate\Database\MySqlConnection $instance */ + return $instance->getLastInsertId(); + } + /** + * Determine if the connected database is a MariaDB database. + * + * @return bool + * @static + */ public static function isMaria() + { + /** @var \Illuminate\Database\MySqlConnection $instance */ + return $instance->isMaria(); + } + /** + * Get the server version for the connection. + * + * @return string + * @static + */ public static function getServerVersion() + { + /** @var \Illuminate\Database\MySqlConnection $instance */ + return $instance->getServerVersion(); } /** * Get a schema builder instance for the connection. * - * @return \Illuminate\Database\Schema\SQLiteBuilder + * @return \Illuminate\Database\Schema\MySqlBuilder * @static */ public static function getSchemaBuilder() { - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getSchemaBuilder(); } /** @@ -5516,11 +5810,11 @@ * * @param \Illuminate\Filesystem\Filesystem|null $files * @param callable|null $processFactory - * @throws \RuntimeException + * @return \Illuminate\Database\Schema\MySqlSchemaState * @static */ public static function getSchemaState($files = null, $processFactory = null) { - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getSchemaState($files, $processFactory); } /** @@ -5530,7 +5824,7 @@ * @static */ public static function useDefaultQueryGrammar() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->useDefaultQueryGrammar(); } /** @@ -5540,7 +5834,7 @@ * @static */ public static function useDefaultSchemaGrammar() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->useDefaultSchemaGrammar(); } /** @@ -5550,7 +5844,7 @@ * @static */ public static function useDefaultPostProcessor() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->useDefaultPostProcessor(); } /** @@ -5562,7 +5856,7 @@ * @static */ public static function table($table, $as = null) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->table($table, $as); } /** @@ -5572,7 +5866,7 @@ * @static */ public static function query() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->query(); } /** @@ -5585,7 +5879,7 @@ * @static */ public static function selectOne($query, $bindings = [], $useReadPdo = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->selectOne($query, $bindings, $useReadPdo); } /** @@ -5599,7 +5893,7 @@ * @static */ public static function scalar($query, $bindings = [], $useReadPdo = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->scalar($query, $bindings, $useReadPdo); } /** @@ -5611,7 +5905,7 @@ * @static */ public static function selectFromWriteConnection($query, $bindings = []) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->selectFromWriteConnection($query, $bindings); } /** @@ -5624,7 +5918,7 @@ * @static */ public static function select($query, $bindings = [], $useReadPdo = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->select($query, $bindings, $useReadPdo); } /** @@ -5637,7 +5931,7 @@ * @static */ public static function selectResultSets($query, $bindings = [], $useReadPdo = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->selectResultSets($query, $bindings, $useReadPdo); } /** @@ -5650,20 +5944,8 @@ * @static */ public static function cursor($query, $bindings = [], $useReadPdo = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->cursor($query, $bindings, $useReadPdo); - } - /** - * Run an insert statement against the database. - * - * @param string $query - * @param array $bindings - * @return bool - * @static - */ public static function insert($query, $bindings = []) - { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ - return $instance->insert($query, $bindings); } /** * Run an update statement against the database. @@ -5674,7 +5956,7 @@ * @static */ public static function update($query, $bindings = []) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->update($query, $bindings); } /** @@ -5686,7 +5968,7 @@ * @static */ public static function delete($query, $bindings = []) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->delete($query, $bindings); } /** @@ -5698,7 +5980,7 @@ * @static */ public static function statement($query, $bindings = []) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->statement($query, $bindings); } /** @@ -5710,7 +5992,7 @@ * @static */ public static function affectingStatement($query, $bindings = []) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->affectingStatement($query, $bindings); } /** @@ -5721,8 +6003,18 @@ * @static */ public static function unprepared($query) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->unprepared($query); + } + /** + * Get the number of open connections for the database. + * + * @return int|null + * @static + */ public static function threadCount() + { //Method inherited from \Illuminate\Database\Connection + /** @var \Illuminate\Database\MySqlConnection $instance */ + return $instance->threadCount(); } /** * Execute the given callback in "dry run" mode. @@ -5732,7 +6024,7 @@ * @static */ public static function pretend($callback) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->pretend($callback); } /** @@ -5743,7 +6035,7 @@ * @static */ public static function withoutPretending($callback) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->withoutPretending($callback); } /** @@ -5755,7 +6047,7 @@ * @static */ public static function bindValues($statement, $bindings) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->bindValues($statement, $bindings); } /** @@ -5766,7 +6058,7 @@ * @static */ public static function prepareBindings($bindings) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->prepareBindings($bindings); } /** @@ -5779,7 +6071,7 @@ * @static */ public static function logQuery($query, $bindings, $time = null) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->logQuery($query, $bindings, $time); } /** @@ -5791,7 +6083,7 @@ * @static */ public static function whenQueryingForLongerThan($threshold, $handler) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->whenQueryingForLongerThan($threshold, $handler); } /** @@ -5801,7 +6093,7 @@ * @static */ public static function allowQueryDurationHandlersToRunAgain() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->allowQueryDurationHandlersToRunAgain(); } /** @@ -5811,7 +6103,7 @@ * @static */ public static function totalQueryDuration() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->totalQueryDuration(); } /** @@ -5821,7 +6113,7 @@ * @static */ public static function resetTotalQueryDuration() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->resetTotalQueryDuration(); } /** @@ -5831,29 +6123,29 @@ * @static */ public static function reconnectIfMissingConnection() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->reconnectIfMissingConnection(); } /** * Register a hook to be run just before a database transaction is started. * * @param \Closure $callback - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function beforeStartingTransaction($callback) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->beforeStartingTransaction($callback); } /** * Register a hook to be run just before a database query is executed. * * @param \Closure $callback - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function beforeExecuting($callback) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->beforeExecuting($callback); } /** @@ -5864,7 +6156,7 @@ * @static */ public static function listen($callback) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->listen($callback); } /** @@ -5875,7 +6167,7 @@ * @static */ public static function raw($value) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->raw($value); } /** @@ -5887,7 +6179,7 @@ * @static */ public static function escape($value, $binary = false) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->escape($value, $binary); } /** @@ -5897,7 +6189,7 @@ * @static */ public static function hasModifiedRecords() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->hasModifiedRecords(); } /** @@ -5908,18 +6200,18 @@ * @static */ public static function recordsHaveBeenModified($value = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->recordsHaveBeenModified($value); } /** * Set the record modification state. * * @param bool $value - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setRecordModificationState($value) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setRecordModificationState($value); } /** @@ -5929,18 +6221,18 @@ * @static */ public static function forgetRecordModificationState() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->forgetRecordModificationState(); } /** * Indicate that the connection should use the write PDO connection for reads. * * @param bool $value - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function useWriteConnectionWhenReading($value = true) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->useWriteConnectionWhenReading($value); } /** @@ -5950,7 +6242,7 @@ * @static */ public static function getPdo() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getPdo(); } /** @@ -5960,7 +6252,7 @@ * @static */ public static function getRawPdo() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getRawPdo(); } /** @@ -5970,7 +6262,7 @@ * @static */ public static function getReadPdo() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getReadPdo(); } /** @@ -5980,29 +6272,29 @@ * @static */ public static function getRawReadPdo() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getRawReadPdo(); } /** * Set the PDO connection. * * @param \PDO|\Closure|null $pdo - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setPdo($pdo) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setPdo($pdo); } /** * Set the PDO connection used for reading. * * @param \PDO|\Closure|null $pdo - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setReadPdo($pdo) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setReadPdo($pdo); } /** @@ -6012,7 +6304,7 @@ * @static */ public static function getName() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getName(); } /** @@ -6022,7 +6314,7 @@ * @static */ public static function getNameWithReadWriteType() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getNameWithReadWriteType(); } /** @@ -6033,7 +6325,7 @@ * @static */ public static function getConfig($option = null) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getConfig($option); } /** @@ -6043,7 +6335,7 @@ * @static */ public static function getDriverName() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getDriverName(); } /** @@ -6053,18 +6345,18 @@ * @static */ public static function getQueryGrammar() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getQueryGrammar(); } /** * Set the query grammar used by the connection. * * @param \Illuminate\Database\Query\Grammars\Grammar $grammar - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setQueryGrammar($grammar) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setQueryGrammar($grammar); } /** @@ -6074,18 +6366,18 @@ * @static */ public static function getSchemaGrammar() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getSchemaGrammar(); } /** * Set the schema grammar used by the connection. * * @param \Illuminate\Database\Schema\Grammars\Grammar $grammar - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setSchemaGrammar($grammar) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setSchemaGrammar($grammar); } /** @@ -6095,18 +6387,18 @@ * @static */ public static function getPostProcessor() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getPostProcessor(); } /** * Set the query post processor used by the connection. * * @param \Illuminate\Database\Query\Processors\Processor $processor - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setPostProcessor($processor) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setPostProcessor($processor); } /** @@ -6116,18 +6408,18 @@ * @static */ public static function getEventDispatcher() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getEventDispatcher(); } /** * Set the event dispatcher instance on the connection. * * @param \Illuminate\Contracts\Events\Dispatcher $events - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setEventDispatcher($events) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setEventDispatcher($events); } /** @@ -6137,18 +6429,18 @@ * @static */ public static function unsetEventDispatcher() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->unsetEventDispatcher(); } /** * Set the transaction manager instance on the connection. * * @param \Illuminate\Database\DatabaseTransactionsManager $manager - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setTransactionManager($manager) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setTransactionManager($manager); } /** @@ -6158,7 +6450,7 @@ * @static */ public static function unsetTransactionManager() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->unsetTransactionManager(); } /** @@ -6168,7 +6460,7 @@ * @static */ public static function pretending() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->pretending(); } /** @@ -6178,7 +6470,7 @@ * @static */ public static function getQueryLog() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getQueryLog(); } /** @@ -6188,7 +6480,7 @@ * @static */ public static function getRawQueryLog() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getRawQueryLog(); } /** @@ -6198,7 +6490,7 @@ * @static */ public static function flushQueryLog() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->flushQueryLog(); } /** @@ -6208,7 +6500,7 @@ * @static */ public static function enableQueryLog() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->enableQueryLog(); } /** @@ -6218,7 +6510,7 @@ * @static */ public static function disableQueryLog() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->disableQueryLog(); } /** @@ -6228,7 +6520,7 @@ * @static */ public static function logging() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->logging(); } /** @@ -6238,29 +6530,29 @@ * @static */ public static function getDatabaseName() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getDatabaseName(); } /** * Set the name of the connected database. * * @param string $database - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setDatabaseName($database) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setDatabaseName($database); } /** * Set the read / write type of the connection. * * @param string|null $readWriteType - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setReadWriteType($readWriteType) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setReadWriteType($readWriteType); } /** @@ -6270,18 +6562,18 @@ * @static */ public static function getTablePrefix() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->getTablePrefix(); } /** * Set the table prefix in use by the connection. * * @param string $prefix - * @return \Illuminate\Database\SQLiteConnection + * @return \Illuminate\Database\MySqlConnection * @static */ public static function setTablePrefix($prefix) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->setTablePrefix($prefix); } /** @@ -6292,18 +6584,8 @@ * @static */ public static function withTablePrefix($grammar) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->withTablePrefix($grammar); - } - /** - * Get the server version for the connection. - * - * @return string - * @static - */ public static function getServerVersion() - { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ - return $instance->getServerVersion(); } /** * Register a connection resolver. @@ -6314,7 +6596,7 @@ * @static */ public static function resolverFor($driver, $callback) { //Method inherited from \Illuminate\Database\Connection - \Illuminate\Database\SQLiteConnection::resolverFor($driver, $callback); + \Illuminate\Database\MySqlConnection::resolverFor($driver, $callback); } /** * Get the connection resolver for the given driver. @@ -6324,7 +6606,7 @@ * @static */ public static function getResolver($driver) { //Method inherited from \Illuminate\Database\Connection - return \Illuminate\Database\SQLiteConnection::getResolver($driver); + return \Illuminate\Database\MySqlConnection::getResolver($driver); } /** * Execute a Closure within a transaction. @@ -6336,7 +6618,7 @@ * @static */ public static function transaction($callback, $attempts = 1) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->transaction($callback, $attempts); } /** @@ -6347,7 +6629,7 @@ * @static */ public static function beginTransaction() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->beginTransaction(); } /** @@ -6358,7 +6640,7 @@ * @static */ public static function commit() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->commit(); } /** @@ -6370,7 +6652,7 @@ * @static */ public static function rollBack($toLevel = null) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->rollBack($toLevel); } /** @@ -6380,7 +6662,7 @@ * @static */ public static function transactionLevel() { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ return $instance->transactionLevel(); } /** @@ -6392,7 +6674,7 @@ * @static */ public static function afterCommit($callback) { //Method inherited from \Illuminate\Database\Connection - /** @var \Illuminate\Database\SQLiteConnection $instance */ + /** @var \Illuminate\Database\MySqlConnection $instance */ $instance->afterCommit($callback); } } @@ -6405,8 +6687,8 @@ /** * Register an event listener with the dispatcher. * - * @param \Closure|string|array $events - * @param \Closure|string|array|null $listener + * @param \Illuminate\Events\Queued\Closure|\Closure|string|array $events + * @param \Illuminate\Events\Queued\Closure|\Closure|string|array|null $listener * @return void * @static */ public static function listen($events, $listener = null) @@ -6837,7 +7119,7 @@ * * @param string $path * @param string $algorithm - * @return string + * @return string|false * @static */ public static function hash($path, $algorithm = 'md5') { @@ -7405,7 +7687,7 @@ /** * Define a new ability. * - * @param string $ability + * @param \BackedEnum|string $ability * @param callable|array|string $callback * @return \Illuminate\Auth\Access\Gate * @throws \InvalidArgumentException @@ -7465,7 +7747,7 @@ /** * Determine if all of the given abilities should be granted for the current user. * - * @param \Illuminate\Auth\Access\iterable|string $ability + * @param \Illuminate\Auth\Access\iterable|\BackedEnum|string $ability * @param array|mixed $arguments * @return bool * @static @@ -7477,7 +7759,7 @@ /** * Determine if any of the given abilities should be denied for the current user. * - * @param \Illuminate\Auth\Access\iterable|string $ability + * @param \Illuminate\Auth\Access\iterable|\BackedEnum|string $ability * @param array|mixed $arguments * @return bool * @static @@ -7489,7 +7771,7 @@ /** * Determine if all of the given abilities should be granted for the current user. * - * @param \Illuminate\Auth\Access\iterable|string $abilities + * @param \Illuminate\Auth\Access\iterable|\BackedEnum|string $abilities * @param array|mixed $arguments * @return bool * @static @@ -7501,7 +7783,7 @@ /** * Determine if any one of the given abilities should be granted for the current user. * - * @param \Illuminate\Auth\Access\iterable|string $abilities + * @param \Illuminate\Auth\Access\iterable|\BackedEnum|string $abilities * @param array|mixed $arguments * @return bool * @static @@ -7513,7 +7795,7 @@ /** * Determine if all of the given abilities should be denied for the current user. * - * @param \Illuminate\Auth\Access\iterable|string $abilities + * @param \Illuminate\Auth\Access\iterable|\BackedEnum|string $abilities * @param array|mixed $arguments * @return bool * @static @@ -7525,7 +7807,7 @@ /** * Determine if the given ability should be granted for the current user. * - * @param string $ability + * @param \BackedEnum|string $ability * @param array|mixed $arguments * @return \Illuminate\Auth\Access\Response * @throws \Illuminate\Auth\Access\AuthorizationException @@ -7538,7 +7820,7 @@ /** * Inspect the user for the given ability. * - * @param string $ability + * @param \BackedEnum|string $ability * @param array|mixed $arguments * @return \Illuminate\Auth\Access\Response * @static @@ -7777,6 +8059,18 @@ { /** @var \Illuminate\Hashing\HashManager $instance */ return $instance->getDefaultDriver(); + } + /** + * Verifies that the configuration is less than or equal to what is configured. + * + * @param array $value + * @return bool + * @internal + * @static + */ public static function verifyConfiguration($value) + { + /** @var \Illuminate\Hashing\HashManager $instance */ + return $instance->verifyConfiguration($value); } /** * Get a driver instance. @@ -7881,7 +8175,7 @@ * @method static \Illuminate\Http\Client\PendingRequest beforeSending(callable $callback) * @method static \Illuminate\Http\Client\PendingRequest throw(callable|null $callback = null) * @method static \Illuminate\Http\Client\PendingRequest throwIf(callable|bool $condition) - * @method static \Illuminate\Http\Client\PendingRequest throwUnless(bool $condition) + * @method static \Illuminate\Http\Client\PendingRequest throwUnless(callable|bool $condition) * @method static \Illuminate\Http\Client\PendingRequest dump() * @method static \Illuminate\Http\Client\PendingRequest dd() * @method static \Illuminate\Http\Client\Response get(string $url, array|string|null $query = null) @@ -8822,7 +9116,7 @@ * @method static \Illuminate\Contracts\View\Factory getViewFactory() * @method static void setSymfonyTransport(\Symfony\Component\Mailer\Transport\TransportInterface $transport) * @method static \Illuminate\Mail\Mailer setQueue(\Illuminate\Contracts\Queue\Factory $queue) - * @method static void macro(string $name, object|callable $macro, object|callable $macro = null) + * @method static void macro(string $name, object|callable $macro) * @method static void mixin(object $mixin, bool $replace = true) * @method static bool hasMacro(string $name) * @method static void flushMacros() @@ -8942,7 +9236,7 @@ * Assert if a mailable was sent based on a truth-test callback. * * @param string|\Closure $mailable - * @param callable|int|null $callback + * @param callable|array|string|int|null $callback * @return void * @static */ public static function assertSent($mailable, $callback = null) @@ -8966,7 +9260,7 @@ * Determine if a mailable was not sent based on a truth-test callback. * * @param string|\Closure $mailable - * @param callable|null $callback + * @param callable|array|string|null $callback * @return void * @static */ public static function assertNotSent($mailable, $callback = null) @@ -8998,7 +9292,7 @@ * Assert if a mailable was queued based on a truth-test callback. * * @param string|\Closure $mailable - * @param callable|int|null $callback + * @param callable|array|string|int|null $callback * @return void * @static */ public static function assertQueued($mailable, $callback = null) @@ -9010,7 +9304,7 @@ * Determine if a mailable was not queued based on a truth-test callback. * * @param string|\Closure $mailable - * @param callable|null $callback + * @param callable|array|string|null $callback * @return void * @static */ public static function assertNotQueued($mailable, $callback = null) @@ -10752,7 +11046,7 @@ /** * Create a new redirect response to a named route. * - * @param string $route + * @param \BackedEnum|string $route * @param mixed $parameters * @param int $status * @param array $headers @@ -10766,7 +11060,7 @@ /** * Create a new redirect response to a signed named route. * - * @param string $route + * @param \BackedEnum|string $route * @param mixed $parameters * @param \DateTimeInterface|\DateInterval|int|null $expiration * @param int $status @@ -10781,7 +11075,7 @@ /** * Create a new redirect response to a signed named route. * - * @param string $route + * @param \BackedEnum|string $route * @param \DateTimeInterface|\DateInterval|int|null $expiration * @param mixed $parameters * @param int $status @@ -13226,10 +13520,10 @@ * @method static \Illuminate\Routing\RouteRegistrar whereIn(array|string $parameters, array $values) * @method static \Illuminate\Routing\RouteRegistrar as(string $value) * @method static \Illuminate\Routing\RouteRegistrar controller(string $controller) - * @method static \Illuminate\Routing\RouteRegistrar domain(string $value) + * @method static \Illuminate\Routing\RouteRegistrar domain(\BackedEnum|string $value) * @method static \Illuminate\Routing\RouteRegistrar middleware(array|string|null $middleware) * @method static \Illuminate\Routing\RouteRegistrar missing(\Closure $missing) - * @method static \Illuminate\Routing\RouteRegistrar name(string $value) + * @method static \Illuminate\Routing\RouteRegistrar name(\BackedEnum|string $value) * @method static \Illuminate\Routing\RouteRegistrar namespace(string|null $value) * @method static \Illuminate\Routing\RouteRegistrar prefix(string $prefix) * @method static \Illuminate\Routing\RouteRegistrar scopeBindings() @@ -13965,7 +14259,7 @@ /** * Alias for the "currentRouteUses" method. * - * @param array $patterns + * @param array|string $patterns * @return bool * @static */ public static function uses(...$patterns) @@ -14125,6 +14419,17 @@ { /** @var \Illuminate\Routing\Router $instance */ return $instance->macroCall($method, $parameters); + } + /** + * Call the given Closure with this instance then return the instance. + * + * @param \Illuminate\Routing\(callable($this): mixed)|null $callback + * @return \Illuminate\Routing\($callback is null ? \Illuminate\Support\HigherOrderTapProxy : $this) + * @static + */ public static function tap($callback = null) + { + /** @var \Illuminate\Routing\Router $instance */ + return $instance->tap($callback); } /** * @@ -14331,7 +14636,7 @@ * @static */ public static function createDatabase($name) { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->createDatabase($name); } /** @@ -14342,19 +14647,28 @@ * @static */ public static function dropDatabaseIfExists($name) { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->dropDatabaseIfExists($name); } /** * Get the tables for the database. * - * @param bool $withSize * @return array * @static - */ public static function getTables($withSize = true) + */ public static function getTables() { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ - return $instance->getTables($withSize); + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ + return $instance->getTables(); + } + /** + * Get the views for the database. + * + * @return array + * @static + */ public static function getViews() + { + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ + return $instance->getViews(); } /** * Get the columns for a given table. @@ -14364,8 +14678,30 @@ * @static */ public static function getColumns($table) { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getColumns($table); + } + /** + * Get the indexes for a given table. + * + * @param string $table + * @return array + * @static + */ public static function getIndexes($table) + { + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ + return $instance->getIndexes($table); + } + /** + * Get the foreign keys for a given table. + * + * @param string $table + * @return array + * @static + */ public static function getForeignKeys($table) + { + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ + return $instance->getForeignKeys($table); } /** * Drop all tables from the database. @@ -14374,7 +14710,7 @@ * @static */ public static function dropAllTables() { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->dropAllTables(); } /** @@ -14384,18 +14720,8 @@ * @static */ public static function dropAllViews() { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->dropAllViews(); - } - /** - * Empty the database file. - * - * @return void - * @static - */ public static function refreshDatabaseFile() - { - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ - $instance->refreshDatabaseFile(); } /** * Set the default string length for migrations. @@ -14405,7 +14731,7 @@ * @static */ public static function defaultStringLength($length) { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::defaultStringLength($length); + \Illuminate\Database\Schema\MySqlBuilder::defaultStringLength($length); } /** * Set the default morph key type for migrations. @@ -14416,7 +14742,7 @@ * @static */ public static function defaultMorphKeyType($type) { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::defaultMorphKeyType($type); + \Illuminate\Database\Schema\MySqlBuilder::defaultMorphKeyType($type); } /** * Set the default morph key type for migrations to UUIDs. @@ -14425,7 +14751,7 @@ * @static */ public static function morphUsingUuids() { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::morphUsingUuids(); + \Illuminate\Database\Schema\MySqlBuilder::morphUsingUuids(); } /** * Set the default morph key type for migrations to ULIDs. @@ -14434,7 +14760,7 @@ * @static */ public static function morphUsingUlids() { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::morphUsingUlids(); + \Illuminate\Database\Schema\MySqlBuilder::morphUsingUlids(); } /** * Determine if the given table exists. @@ -14444,7 +14770,7 @@ * @static */ public static function hasTable($table) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->hasTable($table); } /** @@ -14455,7 +14781,7 @@ * @static */ public static function hasView($view) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->hasView($view); } /** @@ -14465,18 +14791,8 @@ * @static */ public static function getTableListing() { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getTableListing(); - } - /** - * Get the views that belong to the database. - * - * @return array - * @static - */ public static function getViews() - { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ - return $instance->getViews(); } /** * Get the user-defined types that belong to the database. @@ -14485,7 +14801,7 @@ * @static */ public static function getTypes() { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getTypes(); } /** @@ -14497,7 +14813,7 @@ * @static */ public static function hasColumn($table, $column) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->hasColumn($table, $column); } /** @@ -14509,7 +14825,7 @@ * @static */ public static function hasColumns($table, $columns) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->hasColumns($table, $columns); } /** @@ -14522,7 +14838,7 @@ * @static */ public static function whenTableHasColumn($table, $column, $callback) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->whenTableHasColumn($table, $column, $callback); } /** @@ -14535,7 +14851,7 @@ * @static */ public static function whenTableDoesntHaveColumn($table, $column, $callback) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->whenTableDoesntHaveColumn($table, $column, $callback); } /** @@ -14548,7 +14864,7 @@ * @static */ public static function getColumnType($table, $column, $fullDefinition = false) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getColumnType($table, $column, $fullDefinition); } /** @@ -14559,19 +14875,8 @@ * @static */ public static function getColumnListing($table) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getColumnListing($table); - } - /** - * Get the indexes for a given table. - * - * @param string $table - * @return array - * @static - */ public static function getIndexes($table) - { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ - return $instance->getIndexes($table); } /** * Get the names of the indexes for a given table. @@ -14581,7 +14886,7 @@ * @static */ public static function getIndexListing($table) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getIndexListing($table); } /** @@ -14594,19 +14899,8 @@ * @static */ public static function hasIndex($table, $index, $type = null) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->hasIndex($table, $index, $type); - } - /** - * Get the foreign keys for a given table. - * - * @param string $table - * @return array - * @static - */ public static function getForeignKeys($table) - { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ - return $instance->getForeignKeys($table); } /** * Modify a table on the schema. @@ -14617,7 +14911,7 @@ * @static */ public static function table($table, $callback) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->table($table, $callback); } /** @@ -14629,7 +14923,7 @@ * @static */ public static function create($table, $callback) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->create($table, $callback); } /** @@ -14640,7 +14934,7 @@ * @static */ public static function drop($table) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->drop($table); } /** @@ -14651,7 +14945,7 @@ * @static */ public static function dropIfExists($table) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->dropIfExists($table); } /** @@ -14663,7 +14957,7 @@ * @static */ public static function dropColumns($table, $columns) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->dropColumns($table, $columns); } /** @@ -14674,7 +14968,7 @@ * @static */ public static function dropAllTypes() { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->dropAllTypes(); } /** @@ -14686,7 +14980,7 @@ * @static */ public static function rename($from, $to) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->rename($from, $to); } /** @@ -14696,7 +14990,7 @@ * @static */ public static function enableForeignKeyConstraints() { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->enableForeignKeyConstraints(); } /** @@ -14706,7 +15000,7 @@ * @static */ public static function disableForeignKeyConstraints() { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->disableForeignKeyConstraints(); } /** @@ -14717,7 +15011,7 @@ * @static */ public static function withoutForeignKeyConstraints($callback) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->withoutForeignKeyConstraints($callback); } /** @@ -14727,18 +15021,18 @@ * @static */ public static function getConnection() { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->getConnection(); } /** * Set the database connection instance. * * @param \Illuminate\Database\Connection $connection - * @return \Illuminate\Database\Schema\SQLiteBuilder + * @return \Illuminate\Database\Schema\MySqlBuilder * @static */ public static function setConnection($connection) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ return $instance->setConnection($connection); } /** @@ -14749,7 +15043,7 @@ * @static */ public static function blueprintResolver($resolver) { //Method inherited from \Illuminate\Database\Schema\Builder - /** @var \Illuminate\Database\Schema\SQLiteBuilder $instance */ + /** @var \Illuminate\Database\Schema\MySqlBuilder $instance */ $instance->blueprintResolver($resolver); } /** @@ -14762,7 +15056,7 @@ * @static */ public static function macro($name, $macro) { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::macro($name, $macro); + \Illuminate\Database\Schema\MySqlBuilder::macro($name, $macro); } /** * Mix another object into the class. @@ -14774,7 +15068,7 @@ * @static */ public static function mixin($mixin, $replace = true) { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::mixin($mixin, $replace); + \Illuminate\Database\Schema\MySqlBuilder::mixin($mixin, $replace); } /** * Checks if macro is registered. @@ -14784,7 +15078,7 @@ * @static */ public static function hasMacro($name) { //Method inherited from \Illuminate\Database\Schema\Builder - return \Illuminate\Database\Schema\SQLiteBuilder::hasMacro($name); + return \Illuminate\Database\Schema\MySqlBuilder::hasMacro($name); } /** * Flush the existing macros. @@ -14793,7 +15087,7 @@ * @static */ public static function flushMacros() { //Method inherited from \Illuminate\Database\Schema\Builder - \Illuminate\Database\Schema\SQLiteBuilder::flushMacros(); + \Illuminate\Database\Schema\MySqlBuilder::flushMacros(); } } /** @@ -15518,7 +15812,7 @@ * Get a filesystem instance. * * @param string|null $name - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function drive($name = null) { @@ -15529,7 +15823,7 @@ * Get a filesystem instance. * * @param string|null $name - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function disk($name = null) { @@ -15550,7 +15844,7 @@ * Build an on-demand disk. * * @param string|array $config - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function build($config) { @@ -15561,18 +15855,19 @@ * Create an instance of the local driver. * * @param array $config - * @return \Illuminate\Filesystem\FilesystemAdapter + * @param string $name + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static - */ public static function createLocalDriver($config) + */ public static function createLocalDriver($config, $name = 'local') { /** @var \Illuminate\Filesystem\FilesystemManager $instance */ - return $instance->createLocalDriver($config); + return $instance->createLocalDriver($config, $name); } /** * Create an instance of the ftp driver. * * @param array $config - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function createFtpDriver($config) { @@ -15583,7 +15878,7 @@ * Create an instance of the sftp driver. * * @param array $config - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function createSftpDriver($config) { @@ -15605,7 +15900,7 @@ * Create a scoped driver. * * @param array $config - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function createScopedDriver($config) { @@ -15688,39 +15983,85 @@ { /** @var \Illuminate\Filesystem\FilesystemManager $instance */ return $instance->setApplication($app); + } + /** + * Determine if temporary URLs can be generated. + * + * @return bool + * @static + */ public static function providesTemporaryUrls() + { + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ + return $instance->providesTemporaryUrls(); + } + /** + * Get a temporary URL for the file at the given path. + * + * @param string $path + * @param \DateTimeInterface $expiration + * @param array $options + * @return string + * @static + */ public static function temporaryUrl($path, $expiration, $options = []) + { + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ + return $instance->temporaryUrl($path, $expiration, $options); + } + /** + * Specify the name of the disk the adapter is managing. + * + * @param string $disk + * @return \Illuminate\Filesystem\LocalFilesystemAdapter + * @static + */ public static function diskName($disk) + { + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ + return $instance->diskName($disk); + } + /** + * Indiate that signed URLs should serve the corresponding files. + * + * @param bool $serve + * @param \Closure|null $urlGeneratorResolver + * @return \Illuminate\Filesystem\LocalFilesystemAdapter + * @static + */ public static function shouldServeSignedUrls($serve = true, $urlGeneratorResolver = null) + { + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ + return $instance->shouldServeSignedUrls($serve, $urlGeneratorResolver); } /** * Assert that the given file or directory exists. * * @param string|array $path * @param string|null $content - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function assertExists($path, $content = null) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->assertExists($path, $content); } /** * Assert that the given file or directory does not exist. * * @param string|array $path - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function assertMissing($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->assertMissing($path); } /** * Assert that the given directory is empty. * * @param string $path - * @return \Illuminate\Filesystem\FilesystemAdapter + * @return \Illuminate\Filesystem\LocalFilesystemAdapter * @static */ public static function assertDirectoryEmpty($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->assertDirectoryEmpty($path); } /** @@ -15730,8 +16071,8 @@ * @return bool * @static */ public static function exists($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->exists($path); } /** @@ -15741,8 +16082,8 @@ * @return bool * @static */ public static function missing($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->missing($path); } /** @@ -15752,8 +16093,8 @@ * @return bool * @static */ public static function fileExists($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->fileExists($path); } /** @@ -15763,8 +16104,8 @@ * @return bool * @static */ public static function fileMissing($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->fileMissing($path); } /** @@ -15774,8 +16115,8 @@ * @return bool * @static */ public static function directoryExists($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->directoryExists($path); } /** @@ -15785,8 +16126,8 @@ * @return bool * @static */ public static function directoryMissing($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->directoryMissing($path); } /** @@ -15796,8 +16137,8 @@ * @return string * @static */ public static function path($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->path($path); } /** @@ -15807,8 +16148,8 @@ * @return string|null * @static */ public static function get($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->get($path); } /** @@ -15819,8 +16160,8 @@ * @return array|null * @static */ public static function json($path, $flags = 0) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->json($path, $flags); } /** @@ -15833,20 +16174,35 @@ * @return \Symfony\Component\HttpFoundation\StreamedResponse * @static */ public static function response($path, $name = null, $headers = [], $disposition = 'inline') - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->response($path, $name, $headers, $disposition); + } + /** + * Create a streamed download response for a given file. + * + * @param \Illuminate\Http\Request $request + * @param string $path + * @param string|null $name + * @param array $headers + * @return \Symfony\Component\HttpFoundation\StreamedResponse + * @static + */ public static function serve($request, $path, $name = null, $headers = []) + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ + return $instance->serve($request, $path, $name, $headers); } /** * Create a streamed download response for a given file. * * @param string $path * @param string|null $name + * @param array $headers * @return \Symfony\Component\HttpFoundation\StreamedResponse * @static */ public static function download($path, $name = null, $headers = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->download($path, $name, $headers); } /** @@ -15858,8 +16214,8 @@ * @return string|bool * @static */ public static function put($path, $contents, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->put($path, $contents, $options); } /** @@ -15871,8 +16227,8 @@ * @return string|false * @static */ public static function putFile($path, $file = null, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->putFile($path, $file, $options); } /** @@ -15885,8 +16241,8 @@ * @return string|false * @static */ public static function putFileAs($path, $file, $name = null, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->putFileAs($path, $file, $name, $options); } /** @@ -15896,8 +16252,8 @@ * @return string * @static */ public static function getVisibility($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->getVisibility($path); } /** @@ -15908,8 +16264,8 @@ * @return bool * @static */ public static function setVisibility($path, $visibility) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->setVisibility($path, $visibility); } /** @@ -15922,8 +16278,8 @@ * @static */ public static function prepend($path, $data, $separator = ' ') - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->prepend($path, $data, $separator); } /** @@ -15936,8 +16292,8 @@ * @static */ public static function append($path, $data, $separator = ' ') - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->append($path, $data, $separator); } /** @@ -15947,8 +16303,8 @@ * @return bool * @static */ public static function delete($paths) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->delete($paths); } /** @@ -15959,8 +16315,8 @@ * @return bool * @static */ public static function copy($from, $to) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->copy($from, $to); } /** @@ -15971,8 +16327,8 @@ * @return bool * @static */ public static function move($from, $to) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->move($from, $to); } /** @@ -15982,8 +16338,8 @@ * @return int * @static */ public static function size($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->size($path); } /** @@ -15993,8 +16349,8 @@ * @throws UnableToProvideChecksum * @static */ public static function checksum($path, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->checksum($path, $options); } /** @@ -16004,8 +16360,8 @@ * @return string|false * @static */ public static function mimeType($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->mimeType($path); } /** @@ -16015,8 +16371,8 @@ * @return int * @static */ public static function lastModified($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->lastModified($path); } /** @@ -16026,8 +16382,8 @@ * @return resource|null The path resource or null on failure. * @static */ public static function readStream($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->readStream($path); } /** @@ -16039,8 +16395,8 @@ * @return bool * @static */ public static function writeStream($path, $resource, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->writeStream($path, $resource, $options); } /** @@ -16051,33 +16407,9 @@ * @throws \RuntimeException * @static */ public static function url($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->url($path); - } - /** - * Determine if temporary URLs can be generated. - * - * @return bool - * @static - */ public static function providesTemporaryUrls() - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ - return $instance->providesTemporaryUrls(); - } - /** - * Get a temporary URL for the file at the given path. - * - * @param string $path - * @param \DateTimeInterface $expiration - * @param array $options - * @return string - * @throws \RuntimeException - * @static - */ public static function temporaryUrl($path, $expiration, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ - return $instance->temporaryUrl($path, $expiration, $options); } /** * Get a temporary upload URL for the file at the given path. @@ -16089,8 +16421,8 @@ * @throws \RuntimeException * @static */ public static function temporaryUploadUrl($path, $expiration, $options = []) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->temporaryUploadUrl($path, $expiration, $options); } /** @@ -16101,8 +16433,8 @@ * @return array * @static */ public static function files($directory = null, $recursive = false) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->files($directory, $recursive); } /** @@ -16112,8 +16444,8 @@ * @return array * @static */ public static function allFiles($directory = null) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->allFiles($directory); } /** @@ -16124,8 +16456,8 @@ * @return array * @static */ public static function directories($directory = null, $recursive = false) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->directories($directory, $recursive); } /** @@ -16135,8 +16467,8 @@ * @return array * @static */ public static function allDirectories($directory = null) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->allDirectories($directory); } /** @@ -16146,8 +16478,8 @@ * @return bool * @static */ public static function makeDirectory($path) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->makeDirectory($path); } /** @@ -16157,8 +16489,8 @@ * @return bool * @static */ public static function deleteDirectory($directory) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->deleteDirectory($directory); } /** @@ -16167,8 +16499,8 @@ * @return \League\Flysystem\FilesystemOperator * @static */ public static function getDriver() - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->getDriver(); } /** @@ -16177,8 +16509,8 @@ * @return \League\Flysystem\FilesystemAdapter * @static */ public static function getAdapter() - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->getAdapter(); } /** @@ -16187,9 +16519,20 @@ * @return array * @static */ public static function getConfig() - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->getConfig(); + } + /** + * Define a custom callback that generates file download responses. + * + * @param \Closure $callback + * @return void + * @static + */ public static function serveUsing($callback) + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ + $instance->serveUsing($callback); } /** * Define a custom temporary URL builder callback. @@ -16198,8 +16541,8 @@ * @return void * @static */ public static function buildTemporaryUrlsUsing($callback) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ $instance->buildTemporaryUrlsUsing($callback); } /** @@ -16214,7 +16557,7 @@ * @static */ public static function when($value = null, $callback = null, $default = null) { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->when($value, $callback, $default); } /** @@ -16229,7 +16572,7 @@ * @static */ public static function unless($value = null, $callback = null, $default = null) { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->unless($value, $callback, $default); } /** @@ -16241,8 +16584,8 @@ * @return void * @static */ public static function macro($name, $macro) - { - \Illuminate\Filesystem\FilesystemAdapter::macro($name, $macro); + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + \Illuminate\Filesystem\LocalFilesystemAdapter::macro($name, $macro); } /** * Mix another object into the class. @@ -16253,8 +16596,8 @@ * @throws \ReflectionException * @static */ public static function mixin($mixin, $replace = true) - { - \Illuminate\Filesystem\FilesystemAdapter::mixin($mixin, $replace); + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + \Illuminate\Filesystem\LocalFilesystemAdapter::mixin($mixin, $replace); } /** * Checks if macro is registered. @@ -16263,8 +16606,8 @@ * @return bool * @static */ public static function hasMacro($name) - { - return \Illuminate\Filesystem\FilesystemAdapter::hasMacro($name); + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + return \Illuminate\Filesystem\LocalFilesystemAdapter::hasMacro($name); } /** * Flush the existing macros. @@ -16272,8 +16615,8 @@ * @return void * @static */ public static function flushMacros() - { - \Illuminate\Filesystem\FilesystemAdapter::flushMacros(); + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + \Illuminate\Filesystem\LocalFilesystemAdapter::flushMacros(); } /** * Dynamically handle calls to the class. @@ -16284,8 +16627,8 @@ * @throws \BadMethodCallException * @static */ public static function macroCall($method, $parameters) - { - /** @var \Illuminate\Filesystem\FilesystemAdapter $instance */ + { //Method inherited from \Illuminate\Filesystem\FilesystemAdapter + /** @var \Illuminate\Filesystem\LocalFilesystemAdapter $instance */ return $instance->macroCall($method, $parameters); } } @@ -16425,7 +16768,7 @@ /** * Create a signed route URL for a named route. * - * @param string $name + * @param \BackedEnum|string $name * @param mixed $parameters * @param \DateTimeInterface|\DateInterval|int|null $expiration * @param bool $absolute @@ -16440,7 +16783,7 @@ /** * Create a temporary signed route URL for a named route. * - * @param string $name + * @param \BackedEnum|string $name * @param \DateTimeInterface|\DateInterval|int $expiration * @param array $parameters * @param bool $absolute @@ -16503,11 +16846,11 @@ /** * Get the URL to a named route. * - * @param string $name + * @param \BackedEnum|string $name * @param mixed $parameters * @param bool $absolute * @return string - * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException + * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException|\InvalidArgumentException * @static */ public static function route($name, $parameters = [], $absolute = true) { @@ -17984,6 +18327,50 @@ { /** @var \Illuminate\Foundation\Vite $instance */ return $instance->usePreloadTagAttributes($attributes); + } + /** + * Eagerly prefetch assets. + * + * @param int|null $concurrency + * @param string $event + * @return \Illuminate\Foundation\Vite + * @static + */ public static function prefetch($concurrency = null, $event = 'load') + { + /** @var \Illuminate\Foundation\Vite $instance */ + return $instance->prefetch($concurrency, $event); + } + /** + * Use the "waterfall" prefetching strategy. + * + * @return \Illuminate\Foundation\Vite + * @static + */ public static function useWaterfallPrefetching($concurrency = null) + { + /** @var \Illuminate\Foundation\Vite $instance */ + return $instance->useWaterfallPrefetching($concurrency); + } + /** + * Use the "aggressive" prefetching strategy. + * + * @return \Illuminate\Foundation\Vite + * @static + */ public static function useAggressivePrefetching() + { + /** @var \Illuminate\Foundation\Vite $instance */ + return $instance->useAggressivePrefetching(); + } + /** + * Set the prefetching strategy. + * + * @param \Illuminate\Foundation\'waterfall'|\Illuminate\Foundation\'aggressive'|null $strategy + * @param array $config + * @return \Illuminate\Foundation\Vite + * @static + */ public static function usePrefetchStrategy($strategy, $config = []) + { + /** @var \Illuminate\Foundation\Vite $instance */ + return $instance->usePrefetchStrategy($strategy, $config); } /** * Generate React refresh runtime script. @@ -18013,7 +18400,7 @@ * @param string $asset * @param string|null $buildDirectory * @return string - * @throws \Exception + * @throws \Illuminate\Foundation\ViteException * @static */ public static function content($asset, $buildDirectory = null) { @@ -18132,12 +18519,13 @@ * Assign one or more accounts to a group * * @param array|int $ids accounts ids to assign - * @param \App\Models\Group|null $group The group the accounts will be assigned to + * @param \App\Models\User $user The user who owns the accounts & the target group + * @param mixed $targetGroup The group the accounts should be assigned to * @throws \Illuminate\Auth\Access\AuthorizationException * @static - */ public static function assign($ids, $user, $group = null) + */ public static function assign($ids, $user, $targetGroup = null) { - return \App\Services\GroupService::assign($ids, $user, $group); + return \App\Services\GroupService::assign($ids, $user, $targetGroup); } /** * Prepends the pseudo group named 'All' to a group collection @@ -18243,10 +18631,10 @@ /** * Set a setting * - * @param string|array $setting A single setting name or an associative array of name:value settings - * @param string|int|bool|null $value The value for single setting + * @param string $setting A single setting name + * @param string|int|bool $value The value for single setting * @static - */ public static function set($setting, $value = null) + */ public static function set($setting, $value) { /** @var \App\Services\SettingService $instance */ return $instance->set($setting, $value); @@ -19315,6 +19703,7 @@ class Blade extends \Illuminate\Support\Facades\Blade {} class Broadcast extends \Illuminate\Support\Facades\Broadcast {} class Bus extends \Illuminate\Support\Facades\Bus {} class Cache extends \Illuminate\Support\Facades\Cache {} + class Concurrency extends \Illuminate\Support\Facades\Concurrency {} class Config extends \Illuminate\Support\Facades\Config {} class Context extends \Illuminate\Support\Facades\Context {} class Cookie extends \Illuminate\Support\Facades\Cookie {} @@ -19325,7 +19714,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Create and return an un-saved model instance. * * @param array $attributes - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function make($attributes = []) { @@ -19401,7 +19790,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a basic where clause to the query. * - * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column + * @param \Illuminate\Database\Eloquent\(\Closure(static): mixed)|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value * @param string $boolean @@ -19415,11 +19804,11 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a basic where clause to the query, and return the first result. * - * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column + * @param \Illuminate\Database\Eloquent\(\Closure(static): mixed)|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value * @param string $boolean - * @return \Illuminate\Database\Eloquent\Model|static|null + * @return \Illuminate\Database\Eloquent\TModel|null * @static */ public static function firstWhere($column, $operator = null, $value = null, $boolean = 'and') { @@ -19429,7 +19818,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an "or where" clause to the query. * - * @param \Closure|array|string|\Illuminate\Contracts\Database\Query\Expression $column + * @param \Illuminate\Database\Eloquent\(\Closure(static): mixed)|array|string|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value * @return \Illuminate\Database\Eloquent\Builder|static @@ -19442,7 +19831,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a basic "where not" clause to the query. * - * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column + * @param \Illuminate\Database\Eloquent\(\Closure(static): mixed)|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value * @param string $boolean @@ -19456,7 +19845,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an "or where not" clause to the query. * - * @param \Closure|array|string|\Illuminate\Contracts\Database\Query\Expression $column + * @param \Illuminate\Database\Eloquent\(\Closure(static): mixed)|array|string|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value * @return \Illuminate\Database\Eloquent\Builder|static @@ -19492,7 +19881,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Create a collection of models from plain arrays. * * @param array $items - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection * @static */ public static function hydrate($items) { @@ -19504,7 +19893,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param string $query * @param array $bindings - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection * @static */ public static function fromQuery($query, $bindings = []) { @@ -19516,7 +19905,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param mixed $id * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|static[]|static|null + * @return \Illuminate\Database\Eloquent\($id is (\Illuminate\Contracts\Support\Arrayable|array) ? \Illuminate\Database\Eloquent\Collection : TModel|null) * @static */ public static function find($id, $columns = []) { @@ -19528,7 +19917,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param \Illuminate\Contracts\Support\Arrayable|array $ids * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Collection + * @return \Illuminate\Database\Eloquent\Collection * @static */ public static function findMany($ids, $columns = []) { @@ -19540,8 +19929,8 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param mixed $id * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|static|static[] - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> + * @return \Illuminate\Database\Eloquent\($id is (\Illuminate\Contracts\Support\Arrayable|array) ? \Illuminate\Database\Eloquent\Collection : TModel) + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException * @static */ public static function findOrFail($id, $columns = []) { @@ -19553,7 +19942,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param mixed $id * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\($id is (\Illuminate\Contracts\Support\Arrayable|array) ? \Illuminate\Database\Eloquent\Collection : TModel) * @static */ public static function findOrNew($id, $columns = []) { @@ -19563,10 +19952,14 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Find a model by its primary key or call a callback. * + * @template TValue * @param mixed $id - * @param \Closure|array|string $columns - * @param \Closure|null $callback - * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|static[]|static|mixed + * @param \Illuminate\Database\Eloquent\(\Closure(): TValue)|list|string $columns + * @param \Illuminate\Database\Eloquent\(\Closure(): TValue)|null $callback + * @return \Illuminate\Database\Eloquent\( $id is (\Illuminate\Contracts\Support\Arrayable|array) + * ? \Illuminate\Database\Eloquent\Collection + * : TModel|TValue + * ) * @static */ public static function findOr($id, $columns = [], $callback = null) { @@ -19578,7 +19971,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param array $attributes * @param array $values - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function firstOrNew($attributes = [], $values = []) { @@ -19590,7 +19983,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param array $attributes * @param array $values - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function firstOrCreate($attributes = [], $values = []) { @@ -19602,7 +19995,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param array $attributes * @param array $values - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function createOrFirst($attributes = [], $values = []) { @@ -19614,7 +20007,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param array $attributes * @param array $values - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function updateOrCreate($attributes, $values = []) { @@ -19625,8 +20018,8 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Execute the query and get the first result or throw an exception. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|static - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> + * @return \Illuminate\Database\Eloquent\TModel + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException * @static */ public static function firstOrFail($columns = []) { @@ -19636,9 +20029,10 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Execute the query and get the first result or call a callback. * - * @param \Closure|array|string $columns - * @param \Closure|null $callback - * @return \Illuminate\Database\Eloquent\Model|static|mixed + * @template TValue + * @param \Illuminate\Database\Eloquent\(\Closure(): TValue)|list $columns + * @param \Illuminate\Database\Eloquent\(\Closure(): TValue)|null $callback + * @return \Illuminate\Database\Eloquent\TModel|\Illuminate\Database\Eloquent\TValue * @static */ public static function firstOr($columns = [], $callback = null) { @@ -19649,8 +20043,8 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Execute the query and get the first result if it's the sole matching record. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> + * @return \Illuminate\Database\Eloquent\TModel + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException * @throws \Illuminate\Database\MultipleRecordsFoundException * @static */ public static function sole($columns = []) @@ -19674,7 +20068,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param string|\Illuminate\Contracts\Database\Query\Expression $column * @return mixed - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException * @throws \Illuminate\Database\MultipleRecordsFoundException * @static */ public static function soleValue($column) @@ -19687,7 +20081,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param string|\Illuminate\Contracts\Database\Query\Expression $column * @return mixed - * @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model> + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException * @static */ public static function valueOrFail($column) { @@ -19698,7 +20092,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Execute the query as a "select" statement. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Collection|static[] + * @return \Illuminate\Database\Eloquent\Collection * @static */ public static function get($columns = []) { @@ -19709,7 +20103,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Get the hydrated models without eager loading. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model[]|static[] + * @return array * @static */ public static function getModels($columns = []) { @@ -19719,8 +20113,8 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Eager load the relationships for the models. * - * @param array $models - * @return array + * @param array $models + * @return array * @static */ public static function eagerLoadRelations($models) { @@ -19752,7 +20146,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Get a lazy collection for the given query. * - * @return \Illuminate\Support\LazyCollection + * @return \Illuminate\Support\LazyCollection * @static */ public static function cursor() { @@ -19764,7 +20158,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * @param string|\Illuminate\Contracts\Database\Query\Expression $column * @param string|null $key - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection * @static */ public static function pluck($column, $key = null) { @@ -19819,7 +20213,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Save a new model and return the instance. * * @param array $attributes - * @return \Illuminate\Database\Eloquent\Model|$this + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function create($attributes = []) { @@ -19830,7 +20224,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Save a new model and return the instance. Allow mass-assignment. * * @param array $attributes - * @return \Illuminate\Database\Eloquent\Model|$this + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function forceCreate($attributes) { @@ -19841,7 +20235,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Save a new model instance with mass assignment without raising model events. * * @param array $attributes - * @return \Illuminate\Database\Eloquent\Model|$this + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function forceCreateQuietly($attributes = []) { @@ -19907,7 +20301,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Set the relationships that should be eager loaded while removing any previously added eager loading specifications. * - * @param mixed $relations + * @param \Illuminate\Database\Eloquent\array): mixed)|string>|string $relations * @return \Illuminate\Database\Eloquent\Builder|static * @static */ public static function withOnly($relations) @@ -19919,7 +20313,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Create a new instance of the model being queried. * * @param array $attributes - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function newModelInstance($attributes = []) { @@ -20025,7 +20419,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Get the model instance being queried. * - * @return \Illuminate\Database\Eloquent\Model|static + * @return \Illuminate\Database\Eloquent\TModel * @static */ public static function getModel() { @@ -20035,8 +20429,9 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Set a model instance for the model being queried. * - * @param \Illuminate\Database\Eloquent\Model $model - * @return \Illuminate\Database\Eloquent\Builder|static + * @template TModelNew of \Illuminate\Database\Eloquent\Model + * @param \Illuminate\Database\Eloquent\TModelNew $model + * @return \Illuminate\Database\Eloquent\static * @static */ public static function setModel($model) { @@ -20099,7 +20494,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Chunk the results of the query. * * @param int $count - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable(\Illuminate\Support\Collection, int): mixed $callback * @return bool * @static */ public static function chunk($count, $callback) @@ -20110,9 +20505,10 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Run a map over each item while chunking. * - * @param callable $callback + * @template TReturn + * @param \Illuminate\Database\Eloquent\callable(TValue): TReturn $callback * @param int $count - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection * @static */ public static function chunkMap($callback, $count = 1000) { @@ -20122,7 +20518,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Execute a callback over each item while chunking. * - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable(TValue, int): mixed $callback * @param int $count * @return bool * @throws \RuntimeException @@ -20136,7 +20532,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Chunk the results of a query by comparing IDs. * * @param int $count - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable(\Illuminate\Support\Collection, int): mixed $callback * @param string|null $column * @param string|null $alias * @return bool @@ -20150,7 +20546,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Chunk the results of a query by comparing IDs in descending order. * * @param int $count - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable(\Illuminate\Support\Collection, int): mixed $callback * @param string|null $column * @param string|null $alias * @return bool @@ -20164,7 +20560,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Chunk the results of a query by comparing IDs in a given order. * * @param int $count - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable(\Illuminate\Support\Collection, int): mixed $callback * @param string|null $column * @param string|null $alias * @param bool $descending @@ -20179,7 +20575,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Execute a callback over each item while chunking by ID. * - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable(TValue, int): mixed $callback * @param int $count * @param string|null $column * @param string|null $alias @@ -20234,7 +20630,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Execute the query and get the first result. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|object|static|null + * @return \Illuminate\Database\Eloquent\TValue|null * @static */ public static function first($columns = []) { @@ -20245,7 +20641,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Execute the query and get the first result if it's the sole matching record. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|object|static|null + * @return \Illuminate\Database\Eloquent\TValue * @throws \Illuminate\Database\RecordsNotFoundException * @throws \Illuminate\Database\MultipleRecordsFoundException * @static @@ -20257,7 +20653,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Pass the query to a given callback. * - * @param callable $callback + * @param \Illuminate\Database\Eloquent\callable($this): mixed $callback * @return \Illuminate\Database\Eloquent\Builder|static * @static */ public static function tap($callback) @@ -20298,7 +20694,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query. * - * @param \Illuminate\Database\Eloquent\Relations\Relation|string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param string $operator * @param int $count * @param string $boolean @@ -20314,7 +20710,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query with an "or". * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param string $operator * @param int $count * @return \Illuminate\Database\Eloquent\Builder|static @@ -20327,7 +20723,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query. * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param string $boolean * @param \Closure|null $callback * @return \Illuminate\Database\Eloquent\Builder|static @@ -20340,7 +20736,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query with an "or". * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @return \Illuminate\Database\Eloquent\Builder|static * @static */ public static function orDoesntHave($relation) @@ -20351,7 +20747,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query with where clauses. * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|null $callback * @param string $operator * @param int $count @@ -20367,7 +20763,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * * Also load the relationship with same condition. * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|null $callback * @param string $operator * @param int $count @@ -20381,7 +20777,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query with where clauses and an "or". * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|null $callback * @param string $operator * @param int $count @@ -20395,7 +20791,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query with where clauses. * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|null $callback * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20407,7 +20803,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a relationship count / exists condition to the query with where clauses and an "or". * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|null $callback * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20419,7 +20815,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param string $operator * @param int $count @@ -20435,7 +20831,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query with an "or". * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param string $operator * @param int $count @@ -20449,7 +20845,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param string $boolean * @param \Closure|null $callback @@ -20463,7 +20859,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query with an "or". * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20475,7 +20871,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query with where clauses. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param \Closure|null $callback * @param string $operator @@ -20490,7 +20886,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query with where clauses and an "or". * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param \Closure|null $callback * @param string $operator @@ -20505,7 +20901,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query with where clauses. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param \Closure|null $callback * @return \Illuminate\Database\Eloquent\Builder|static @@ -20518,7 +20914,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship count / exists condition to the query with where clauses and an "or". * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param \Closure|null $callback * @return \Illuminate\Database\Eloquent\Builder|static @@ -20531,7 +20927,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a basic where clause to a relationship query. * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value @@ -20545,7 +20941,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an "or where" clause to a relationship query. * - * @param string $relation + * @param \Illuminate\Database\Eloquent\Relations\Relation<*, *, *>|string $relation * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator * @param mixed $value @@ -20559,7 +20955,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship condition to the query with a where clause. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator @@ -20574,7 +20970,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a polymorphic relationship condition to the query with an "or where" clause. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param string|array $types * @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $column * @param mixed $operator @@ -20589,7 +20985,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a morph-to relationship condition to the query. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param \Illuminate\Database\Eloquent\Model|string|null $model * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20601,7 +20997,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a not morph-to relationship condition to the query. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param \Illuminate\Database\Eloquent\Model|string $model * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20613,7 +21009,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a morph-to relationship condition to the query with an "or where" clause. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param \Illuminate\Database\Eloquent\Model|string|null $model * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20625,7 +21021,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a not morph-to relationship condition to the query with an "or where" clause. * - * @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation + * @param \Illuminate\Database\Eloquent\Relations\MorphTo<*, *>|string $relation * @param \Illuminate\Database\Eloquent\Model|string $model * @return \Illuminate\Database\Eloquent\Builder|static * @static @@ -20637,7 +21033,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a "belongs to" relationship where clause to the query. * - * @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model> $related + * @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection $related * @param string|null $relationshipName * @param string $boolean * @return \Illuminate\Database\Eloquent\Builder|static @@ -20747,7 +21143,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Merge the where constraints from another query to the current query. * - * @param \Illuminate\Database\Eloquent\Builder $from + * @param \Illuminate\Database\Eloquent\Builder<*> $from * @return \Illuminate\Database\Eloquent\Builder|static * @static */ public static function mergeConstraintsFrom($from) @@ -20769,7 +21165,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a subselect expression to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @return \Illuminate\Database\Query\Builder * @throws \InvalidArgumentException @@ -20794,7 +21190,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Makes "from" fetch from a subquery. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @return \Illuminate\Database\Query\Builder * @throws \InvalidArgumentException @@ -20840,7 +21236,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Set the table which the query is targeting. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Contracts\Database\Query\Expression|string $table + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|\Illuminate\Contracts\Database\Query\Expression|string $table * @param string|null $as * @return \Illuminate\Database\Query\Builder * @static @@ -20916,7 +21312,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a subquery join clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @param \Closure|\Illuminate\Contracts\Database\Query\Expression|string $first * @param string|null $operator @@ -20934,7 +21330,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a lateral join clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @param string $type * @return \Illuminate\Database\Query\Builder @@ -20947,7 +21343,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a lateral left join to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @return \Illuminate\Database\Query\Builder * @static @@ -20987,7 +21383,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a subquery left join to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @param \Closure|\Illuminate\Contracts\Database\Query\Expression|string $first * @param string|null $operator @@ -21030,7 +21426,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a subquery right join to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @param \Closure|\Illuminate\Contracts\Database\Query\Expression|string $first * @param string|null $operator @@ -21059,7 +21455,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a subquery cross join to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @param string $as * @return \Illuminate\Database\Query\Builder * @static @@ -21145,6 +21541,61 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { { /** @var \Illuminate\Database\Query\Builder $instance */ return $instance->orWhereRaw($sql, $bindings); + } + /** + * Add a "where like" clause to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $column + * @param string $value + * @param bool $caseSensitive + * @param string $boolean + * @param bool $not + * @return \Illuminate\Database\Query\Builder + * @static + */ public static function whereLike($column, $value, $caseSensitive = false, $boolean = 'and', $not = false) + { + /** @var \Illuminate\Database\Query\Builder $instance */ + return $instance->whereLike($column, $value, $caseSensitive, $boolean, $not); + } + /** + * Add an "or where like" clause to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $column + * @param string $value + * @param bool $caseSensitive + * @return \Illuminate\Database\Query\Builder + * @static + */ public static function orWhereLike($column, $value, $caseSensitive = false) + { + /** @var \Illuminate\Database\Query\Builder $instance */ + return $instance->orWhereLike($column, $value, $caseSensitive); + } + /** + * Add a "where not like" clause to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $column + * @param string $value + * @param bool $caseSensitive + * @param string $boolean + * @return \Illuminate\Database\Query\Builder + * @static + */ public static function whereNotLike($column, $value, $caseSensitive = false, $boolean = 'and') + { + /** @var \Illuminate\Database\Query\Builder $instance */ + return $instance->whereNotLike($column, $value, $caseSensitive, $boolean); + } + /** + * Add an "or where not like" clause to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $column + * @param string $value + * @param bool $caseSensitive + * @return \Illuminate\Database\Query\Builder + * @static + */ public static function orWhereNotLike($column, $value, $caseSensitive = false) + { + /** @var \Illuminate\Database\Query\Builder $instance */ + return $instance->orWhereNotLike($column, $value, $caseSensitive); } /** * Add a "where in" clause to the query. @@ -21569,7 +22020,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an exists clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $callback + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*> $callback * @param string $boolean * @param bool $not * @return \Illuminate\Database\Query\Builder @@ -21582,7 +22033,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an or exists clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $callback + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*> $callback * @param bool $not * @return \Illuminate\Database\Query\Builder * @static @@ -21594,7 +22045,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a where not exists clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $callback + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*> $callback * @param string $boolean * @return \Illuminate\Database\Query\Builder * @static @@ -21606,7 +22057,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a where not exists clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $callback + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*> $callback * @return \Illuminate\Database\Query\Builder * @static */ public static function orWhereNotExists($callback) @@ -21871,7 +22322,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a "where" clause to the query for multiple columns with "and" conditions between them. * - * @param string[] $columns + * @param \Illuminate\Contracts\Database\Query\Expression[]|\Closure[]|string[] $columns * @param mixed $operator * @param mixed $value * @param string $boolean @@ -21885,8 +22336,8 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an "or where" clause to the query for multiple columns with "and" conditions between them. * - * @param string[] $columns - * @param string $operator + * @param \Illuminate\Contracts\Database\Query\Expression[]|\Closure[]|string[] $columns + * @param mixed $operator * @param mixed $value * @return \Illuminate\Database\Query\Builder * @static @@ -21896,10 +22347,10 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { return $instance->orWhereAll($columns, $operator, $value); } /** - * Add an "where" clause to the query for multiple columns with "or" conditions between them. + * Add a "where" clause to the query for multiple columns with "or" conditions between them. * - * @param string[] $columns - * @param string $operator + * @param \Illuminate\Contracts\Database\Query\Expression[]|\Closure[]|string[] $columns + * @param mixed $operator * @param mixed $value * @param string $boolean * @return \Illuminate\Database\Query\Builder @@ -21912,8 +22363,8 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an "or where" clause to the query for multiple columns with "or" conditions between them. * - * @param string[] $columns - * @param string $operator + * @param \Illuminate\Contracts\Database\Query\Expression[]|\Closure[]|string[] $columns + * @param mixed $operator * @param mixed $value * @return \Illuminate\Database\Query\Builder * @static @@ -21921,6 +22372,33 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { { /** @var \Illuminate\Database\Query\Builder $instance */ return $instance->orWhereAny($columns, $operator, $value); + } + /** + * Add a "where not" clause to the query for multiple columns where none of the conditions should be true. + * + * @param \Illuminate\Contracts\Database\Query\Expression[]|\Closure[]|string[] $columns + * @param mixed $operator + * @param mixed $value + * @param string $boolean + * @return \Illuminate\Database\Query\Builder + * @static + */ public static function whereNone($columns, $operator = null, $value = null, $boolean = 'and') + { + /** @var \Illuminate\Database\Query\Builder $instance */ + return $instance->whereNone($columns, $operator, $value, $boolean); + } + /** + * Add an "or where not" clause to the query for multiple columns where none of the conditions should be true. + * + * @param \Illuminate\Contracts\Database\Query\Expression[]|\Closure[]|string[] $columns + * @param mixed $operator + * @param mixed $value + * @return \Illuminate\Database\Query\Builder + * @static + */ public static function orWhereNone($columns, $operator = null, $value = null) + { + /** @var \Illuminate\Database\Query\Builder $instance */ + return $instance->orWhereNone($columns, $operator, $value); } /** * Add a "group by" clause to the query. @@ -22085,7 +22563,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add an "order by" clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Contracts\Database\Query\Expression|string $column + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|\Illuminate\Contracts\Database\Query\Expression|string $column * @param string $direction * @return \Illuminate\Database\Query\Builder * @throws \InvalidArgumentException @@ -22098,7 +22576,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a descending "order by" clause to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Contracts\Database\Query\Expression|string $column + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|\Illuminate\Contracts\Database\Query\Expression|string $column * @return \Illuminate\Database\Query\Builder * @static */ public static function orderByDesc($column) @@ -22238,7 +22716,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a union statement to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*> $query * @param bool $all * @return \Illuminate\Database\Query\Builder * @static @@ -22250,7 +22728,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { /** * Add a union all statement to the query. * - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*> $query * @return \Illuminate\Database\Query\Builder * @static */ public static function unionAll($query) @@ -22535,7 +23013,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Insert new records into the table using a subquery. * * @param array $columns - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @return int * @static */ public static function insertUsing($columns, $query) @@ -22547,7 +23025,7 @@ class Eloquent extends \Illuminate\Database\Eloquent\Model { * Insert new records into the table using a subquery while ignoring errors. * * @param array $columns - * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query * @return int * @static */ public static function insertOrIgnoreUsing($columns, $query) @@ -22903,11 +23381,6 @@ class Socialite extends \Laravel\Socialite\Facades\Socialite {} } -namespace Facades\App\Services { - /** - * @mixin \App\Services\ReleaseRadarService */ - class ReleaseRadarService extends \App\Services\ReleaseRadarService {} -} namespace Illuminate\Support { diff --git a/app/Api/v1/Controllers/IconController.php b/app/Api/v1/Controllers/IconController.php index d4acfc71..9f258cb5 100644 --- a/app/Api/v1/Controllers/IconController.php +++ b/app/Api/v1/Controllers/IconController.php @@ -3,11 +3,14 @@ namespace App\Api\v1\Controllers; use App\Api\v1\Requests\IconFetchRequest; +use App\Facades\IconStore; +use App\Helpers\Helpers; use App\Http\Controllers\Controller; use App\Models\TwoFAccount; use App\Services\LogoService; +use Exception; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Storage; +use Illuminate\Http\UploadedFile; class IconController extends Controller { @@ -22,11 +25,21 @@ public function upload(Request $request) 'icon' => 'required|image', ]); - $icon = $request->file('icon'); - $path = $icon instanceof \Illuminate\Http\UploadedFile ? $icon->store('', 'icons') : false; + $icon = $request->file('icon'); + $isStored = $name = false; - return $path - ? response()->json(['filename' => pathinfo($path)['basename']], 201) + if ($icon instanceof UploadedFile) { + try { + if ($content = $icon->get()) { + $name = Helpers::getRandomFilename($icon->extension()); + $isStored = IconStore::store($name, $content); + } + } + catch (Exception) { } + } + + return $isStored + ? response()->json(['filename' => $name], 201) : response()->json(['message' => __('errors.file_upload_failed')], 500); } @@ -58,7 +71,7 @@ public function delete(string $icon, Request $request) abort(403, 'unauthorized'); } - Storage::disk('icons')->delete($icon); + IconStore::delete($icon); return response()->json(null, 204); } diff --git a/app/Api/v1/Controllers/TwoFAccountController.php b/app/Api/v1/Controllers/TwoFAccountController.php index 557779d7..94572030 100644 --- a/app/Api/v1/Controllers/TwoFAccountController.php +++ b/app/Api/v1/Controllers/TwoFAccountController.php @@ -56,6 +56,9 @@ public function show(TwoFAccount $twofaccount) { $this->authorize('view', $twofaccount); + // $icon = $twofaccount->icon; + // $iconRes = $twofaccount->icon()->get(); + return new TwoFAccountReadResource($twofaccount); } diff --git a/app/Api/v1/Resources/TwoFAccountExportResource.php b/app/Api/v1/Resources/TwoFAccountExportResource.php index 8acf1844..74165e72 100644 --- a/app/Api/v1/Resources/TwoFAccountExportResource.php +++ b/app/Api/v1/Resources/TwoFAccountExportResource.php @@ -2,6 +2,7 @@ namespace App\Api\v1\Resources; +use App\Facades\IconStore; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Storage; @@ -33,8 +34,8 @@ public function toArray($request) 'account' => $this->account, 'service' => $this->service, 'icon' => $this->icon, - 'icon_mime' => $this->icon ? Storage::disk('icons')->mimeType((string) $this->icon) : null, - 'icon_file' => $this->icon ? base64_encode(Storage::disk('icons')->get((string) $this->icon)) : null, + 'icon_mime' => $this->icon && IconStore::exists($this->icon) ? IconStore::mimeType($this->icon) : null, + 'icon_file' => $this->icon && IconStore::exists($this->icon) ? base64_encode(IconStore::get($this->icon)) : null, 'secret' => $this->secret, 'digits' => (int) $this->digits, 'algorithm' => $this->algorithm, diff --git a/app/Api/v1/Resources/TwoFAccountReadResource.php b/app/Api/v1/Resources/TwoFAccountReadResource.php index 773be357..4de6c0aa 100644 --- a/app/Api/v1/Resources/TwoFAccountReadResource.php +++ b/app/Api/v1/Resources/TwoFAccountReadResource.php @@ -5,7 +5,7 @@ /** * @property mixed $id * @property mixed $group_id - * + * * @method App\Models\Dto\TotpDto|App\Models\Dto\HotpDto getOtp(int $time) */ class TwoFAccountReadResource extends TwoFAccountStoreResource diff --git a/app/Api/v1/Resources/TwoFAccountStoreResource.php b/app/Api/v1/Resources/TwoFAccountStoreResource.php index 94cb55d2..3d890bf9 100644 --- a/app/Api/v1/Resources/TwoFAccountStoreResource.php +++ b/app/Api/v1/Resources/TwoFAccountStoreResource.php @@ -2,6 +2,7 @@ namespace App\Api\v1\Resources; +use App\Facades\IconStore; use Illuminate\Http\Resources\Json\JsonResource; /** @@ -29,7 +30,7 @@ public function toArray($request) 'otp_type' => $this->otp_type, 'account' => $this->account, 'service' => $this->service, - 'icon' => $this->icon, + 'icon' => $this->icon && IconStore::exists($this->icon) ? $this->icon : null, 'secret' => $this->when( ! $request->has('withSecret') || (int) filter_var($request->input('withSecret'), FILTER_VALIDATE_BOOLEAN) == 1, $this->secret diff --git a/app/Console/Commands/Utils/IconGenerator.php b/app/Console/Commands/Utils/DemoIcons.php similarity index 99% rename from app/Console/Commands/Utils/IconGenerator.php rename to app/Console/Commands/Utils/DemoIcons.php index 90e415cb..dc9aa10b 100644 --- a/app/Console/Commands/Utils/IconGenerator.php +++ b/app/Console/Commands/Utils/DemoIcons.php @@ -2,15 +2,8 @@ namespace App\Console\Commands\Utils; -use Illuminate\Support\Facades\Storage; - -class IconGenerator +class DemoIcons { - public static function generateIcon(string $serviceName, string $base64icon) : void - { - Storage::disk('icons')->put($serviceName . '.png', base64_decode($base64icon)); - } - const AMAZON = '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'; const APPLE = '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'; diff --git a/app/Console/Commands/Utils/ResetTrait.php b/app/Console/Commands/Utils/ResetTrait.php index 15ee8e0d..f256c6d2 100644 --- a/app/Console/Commands/Utils/ResetTrait.php +++ b/app/Console/Commands/Utils/ResetTrait.php @@ -2,8 +2,9 @@ namespace App\Console\Commands\Utils; +use App\Facades\IconStore; +use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; trait ResetTrait { @@ -21,8 +22,7 @@ protected function resetIcons() : void */ protected function deleteIcons() : void { - $filesForDelete = \Illuminate\Support\Facades\File::glob('public/icons/*.png'); - Storage::delete($filesForDelete); + IconStore::clear(); $this->line('Existing icons deleted'); } @@ -32,15 +32,20 @@ protected function deleteIcons() : void */ protected function generateIcons() : void { - IconGenerator::generateIcon('amazon', IconGenerator::AMAZON); - IconGenerator::generateIcon('apple', IconGenerator::APPLE); - IconGenerator::generateIcon('dropbox', IconGenerator::DROPBOX); - IconGenerator::generateIcon('facebook', IconGenerator::FACEBOOK); - IconGenerator::generateIcon('github', IconGenerator::GITHUB); - IconGenerator::generateIcon('google', IconGenerator::GOOGLE); - IconGenerator::generateIcon('instagram', IconGenerator::INSTAGRAM); - IconGenerator::generateIcon('linkedin', IconGenerator::LINKEDIN); - IconGenerator::generateIcon('twitter', IconGenerator::TWITTER); + $icons = collect(); + $icons->push(['amazon.png', base64_decode(DemoIcons::AMAZON)]); + $icons->push(['apple.png', base64_decode(DemoIcons::APPLE)]); + $icons->push(['dropbox.png', base64_decode(DemoIcons::DROPBOX)]); + $icons->push(['facebook.png', base64_decode(DemoIcons::FACEBOOK)]); + $icons->push(['github.png', base64_decode(DemoIcons::GITHUB)]); + $icons->push(['google.png', base64_decode(DemoIcons::GOOGLE)]); + $icons->push(['instagram.png', base64_decode(DemoIcons::INSTAGRAM)]); + $icons->push(['linkedin.png', base64_decode(DemoIcons::LINKEDIN)]); + $icons->push(['twitter.png', base64_decode(DemoIcons::TWITTER)]); + + $icons->each(function (array $icon) { + IconStore::store($icon[0], $icon[1]); + }); $this->line('Icons regenerated'); } diff --git a/app/Events/storeIconsInDatabaseSettingChanged.php b/app/Events/storeIconsInDatabaseSettingChanged.php new file mode 100644 index 00000000..8e00507f --- /dev/null +++ b/app/Events/storeIconsInDatabaseSettingChanged.php @@ -0,0 +1,27 @@ +newValue = $newValue; + Log::info('storeIconsInDatabaseSettingChanged event dispatched'); + } +} diff --git a/app/Exceptions/FailedIconStoreDatabaseTogglingException.php b/app/Exceptions/FailedIconStoreDatabaseTogglingException.php new file mode 100644 index 00000000..0eab11d3 --- /dev/null +++ b/app/Exceptions/FailedIconStoreDatabaseTogglingException.php @@ -0,0 +1,12 @@ +renderable(function (FailedIconStoreDatabaseTogglingException $exception, $request) { + return response()->json([ + 'message' => __('errors.failed_icon_store_database_toggling'), + ], 400); + }); + $this->renderable(function (\Illuminate\Auth\AuthenticationException $exception, $request) { if ($exception->guards() === ['reverse-proxy-guard']) { return response()->json([ diff --git a/app/Facades/IconStore.php b/app/Facades/IconStore.php new file mode 100644 index 00000000..e3405d77 --- /dev/null +++ b/app/Facades/IconStore.php @@ -0,0 +1,17 @@ +delete($event->twofaccount->icon ?? []); + IconStore::delete($event->twofaccount->icon ?? []); + Log::info(sprintf('Icon cleaned for deleted TwoFAccount #%d', $event->twofaccount->id)); } } diff --git a/app/Listeners/ToggleIconReplicationToDatabase.php b/app/Listeners/ToggleIconReplicationToDatabase.php new file mode 100644 index 00000000..a2670093 --- /dev/null +++ b/app/Listeners/ToggleIconReplicationToDatabase.php @@ -0,0 +1,24 @@ +newValue); + } +} diff --git a/app/Models/AuthLog.php b/app/Models/AuthLog.php index 5a2e32b5..17b984dc 100644 --- a/app/Models/AuthLog.php +++ b/app/Models/AuthLog.php @@ -43,8 +43,22 @@ * @property string|null $method * @property string|null $login_method * @property-read Model|\Eloquent $authenticatable - * * @mixin \Eloquent + * @method static \Database\Factories\AuthLogFactory factory($count = null, $state = []) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog query() + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereAuthenticatableId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereAuthenticatableType($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereClearedByUser($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereGuard($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereIpAddress($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLoginAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLoginMethod($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLoginSuccessful($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereLogoutAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|AuthLog whereUserAgent($value) */ class AuthLog extends Model { diff --git a/app/Models/Group.php b/app/Models/Group.php index b34c1c21..f2e506dd 100644 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -20,7 +20,6 @@ * @property int|null $user_id * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\TwoFAccount[] $twofaccounts * @property-read \App\Models\User|null $user - * * @method static \Database\Factories\GroupFactory factory(...$parameters) * @method static \Illuminate\Database\Eloquent\Builder|Group newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Group newQuery() @@ -30,8 +29,8 @@ * @method static \Illuminate\Database\Eloquent\Builder|Group whereName($value) * @method static \Illuminate\Database\Eloquent\Builder|Group whereUpdatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|Group whereUserId($value) - * * @mixin \Eloquent + * @method static \Illuminate\Database\Eloquent\Builder|Group orphans() */ class Group extends Model { diff --git a/app/Models/Icon.php b/app/Models/Icon.php new file mode 100644 index 00000000..b7bed8db --- /dev/null +++ b/app/Models/Icon.php @@ -0,0 +1,111 @@ + + */ + use HasFactory, CanEncryptField; + + /** + * The primary key for the model. + * + * @var string + */ + protected $primaryKey = 'name'; + + + /** + * The "type" of the primary key ID. + * + * @var string + */ + protected $keyType = 'string'; + + /** + * Indicates if the IDs are auto-incrementing. + * + * @var bool + */ + public $incrementing = false; + + /** + * Get the twofaccount that owns the icon. + * + * @return BelongsTo<\App\Models\TwoFAccount, \App\Models\Icon> + */ + public function twofaccount() : BelongsTo + { + return $this->belongsTo(TwoFAccount::class, 'name', 'icon'); + } + + /** + * The model's attributes. + * + * @var array + */ + protected $attributes = []; + + /** + * The attributes that should be hidden for arrays. + * + * @var array + */ + protected $hidden = ['created_at', 'updated_at']; + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = ['name']; + + /** + * Get content attribute + * + * @param string $value + * @return string + */ + public function getContentAttribute($value) + { + return $this->decryptOrReturn(base64_decode($value)); + } + + /** + * Set content attribute + * + * @param string $value + * @return void + */ + public function setContentAttribute($value) + { + // Encrypt if needed + $this->attributes['content'] = $this->encryptOrReturn(base64_encode($value)); + } +} diff --git a/app/Models/Option.php b/app/Models/Option.php index c47ddf67..ec20da66 100644 --- a/app/Models/Option.php +++ b/app/Models/Option.php @@ -10,14 +10,12 @@ * @property int $id * @property string $key * @property string $value - * * @method static \Illuminate\Database\Eloquent\Builder|Option newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Option newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Option query() * @method static \Illuminate\Database\Eloquent\Builder|Option whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|Option whereKey($value) * @method static \Illuminate\Database\Eloquent\Builder|Option whereValue($value) - * * @mixin \Eloquent */ class Option extends Model diff --git a/app/Models/Traits/CanEncryptField.php b/app/Models/Traits/CanEncryptField.php new file mode 100644 index 00000000..26d6bdf0 --- /dev/null +++ b/app/Models/Traits/CanEncryptField.php @@ -0,0 +1,35 @@ + */ - use HasFactory; - - use SortableTrait; + use HasFactory, SortableTrait, CanEncryptField; const TOTP = 'totp'; @@ -234,6 +231,16 @@ public function user() return $this->belongsTo(\App\Models\User::class); } + /** + * Get the relation between the icon resource and the model. + * + * @return HasOne<\App\Models\Icon> + */ + public function iconResource(): HasOne + { + return $this->hasOne(Icon::class, 'name', 'icon'); + } + /** * Scope a query to only include orphan (userless) accounts. * @@ -467,7 +474,7 @@ public function fillWithOtpParameters(array $parameters, bool $skipIconFetching } if (! $this->icon && ! $skipIconFetching && Auth::user()?->preferences['getOfficialIcons']) { - $this->icon = App::make(IconService::class)->buildFromOfficialLogo($this->service); + $this->icon = Icons::buildFromOfficialLogo($this->service); } Log::info(sprintf('TwoFAccount filled with OTP parameters')); @@ -534,11 +541,12 @@ public function fillWithURI(string $uri, bool $isSteamTotp = false, bool $skipIc $this->enforceAsSteam(); } if ($this->generator->hasParameter('image')) { - $this->icon = App::make(IconService::class)->buildFromRemoteImage($this->generator->getParameter('image')); + $this->icon = Icons::buildFromRemoteImage($this->generator->getParameter('image')); } + $uuu = Auth::user()?->preferences; if (! $this->icon && ! $skipIconFetching && Auth::user()?->preferences['getOfficialIcons']) { - $this->icon = App::make(IconService::class)->buildFromOfficialLogo($this->service); + $this->icon = Icons::buildFromOfficialLogo($this->service); } Log::info(sprintf('TwoFAccount filled with an URI')); @@ -646,34 +654,6 @@ private function initGenerator() : void } } - /** - * Returns an acceptable value - */ - private function decryptOrReturn(mixed $value) : mixed - { - // Decipher when needed - if (Settings::get('useEncryption') && $value) { - try { - return Crypt::decryptString($value); - } catch (Exception $ex) { - Log::debug(sprintf('Service field of twofaccount with id #%s cannot be deciphered', $this->id)); - - return __('errors.indecipherable'); - } - } else { - return $value; - } - } - - /** - * Encrypt a value - */ - private function encryptOrReturn(mixed $value) : mixed - { - // should be replaced by laravel 8 attribute encryption casting - return Settings::get('useEncryption') ? Crypt::encryptString($value) : $value; - } - /** * @return \Illuminate\Database\Eloquent\Builder */ diff --git a/app/Models/User.php b/app/Models/User.php index 50643aeb..60158e31 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -47,7 +47,6 @@ * @property-read \Illuminate\Database\Eloquent\Collection $authentications * @property-read int|null $authentications_count * @property-read \App\Models\AuthLog|null $latestAuthentication - * * @method static \Illuminate\Database\Eloquent\Builder|User admins() * @method static \Database\Factories\UserFactory factory(...$parameters) * @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery() @@ -64,8 +63,9 @@ * @method static \Illuminate\Database\Eloquent\Builder|User wherePreferences($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value) - * * @mixin \Eloquent + * @method static \Illuminate\Database\Eloquent\Builder|User whereOauthId($value) + * @method static \Illuminate\Database\Eloquent\Builder|User whereOauthProvider($value) */ class User extends Authenticatable implements HasLocalePreference, WebAuthnAuthenticatable { diff --git a/app/Observers/UserObserver.php b/app/Observers/UserObserver.php index 25116a09..8ba3658d 100644 --- a/app/Observers/UserObserver.php +++ b/app/Observers/UserObserver.php @@ -2,12 +2,13 @@ namespace App\Observers; +use App\Facades\IconStore; use App\Models\User; +use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Password; -use Illuminate\Support\Facades\Storage; class UserObserver { @@ -66,7 +67,8 @@ public function deleting(User $user) : bool })->map(function ($twofaccount, $key) { return $twofaccount->icon; }); - Storage::disk('icons')->delete($iconPathes->toArray()); + + IconStore::delete($iconPathes->toArray()); return true; } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 785aa855..f78fc338 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -4,6 +4,7 @@ use App\Events\GroupDeleted; use App\Events\GroupDeleting; +use App\Events\storeIconsInDatabaseSettingChanged; use App\Events\ScanForNewReleaseCalled; use App\Events\TwoFAccountDeleted; use App\Events\VisitedByProxyUser; @@ -14,6 +15,7 @@ use App\Listeners\CleanIconStorage; use App\Listeners\DissociateTwofaccountFromGroup; use App\Listeners\LogNotificationListener; +use App\Listeners\ToggleIconReplicationToDatabase; use App\Listeners\RegisterOpenId; use App\Listeners\ReleaseRadar; use App\Listeners\ResetUsersPreference; @@ -69,6 +71,9 @@ class EventServiceProvider extends ServiceProvider VisitedByProxyUser::class => [ VisitedByProxyUserListener::class, ], + storeIconsInDatabaseSettingChanged::class => [ + ToggleIconReplicationToDatabase::class, + ], ]; /** @@ -76,6 +81,7 @@ class EventServiceProvider extends ServiceProvider * * @var array> */ + // TODO: bind the observer using the ObservedBy attribute (https://laravel.com/docs/11.x/eloquent#defining-observers) protected $observers = [ User::class => [UserObserver::class], ]; diff --git a/app/Providers/TwoFAuthServiceProvider.php b/app/Providers/TwoFAuthServiceProvider.php index cd9a3124..77089274 100644 --- a/app/Providers/TwoFAuthServiceProvider.php +++ b/app/Providers/TwoFAuthServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use App\Factories\MigratorFactoryInterface; +use App\Services\IconStoreService; use App\Services\IconService; use App\Services\LogoService; use App\Services\ReleaseRadarService; @@ -29,11 +30,15 @@ public function register() return new SettingService; }); - $this->app->singleton(LogoService::class, function () { + $this->app->singleton(IconStoreService::class, function () { + return new IconStoreService; + }); + + $this->app->singleton(LogoService::class, function ($app) { return new LogoService; }); - $this->app->singleton(IconService::class, function () { + $this->app->singleton(IconService::class, function ($app) { return new IconService; }); @@ -67,7 +72,9 @@ public function provides() { return [ IconService::class, + IconStoreService::class, LogoService::class, + QrReader::class, ReleaseRadarService::class, ]; } diff --git a/app/Services/IconService.php b/app/Services/IconService.php index 67dd2e0d..a2ac6f06 100644 --- a/app/Services/IconService.php +++ b/app/Services/IconService.php @@ -2,7 +2,8 @@ namespace App\Services; -use App\Services\LogoService; +use App\Facades\IconStore; +use App\Helpers\Helpers; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; @@ -10,9 +11,6 @@ use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; -/** - * App\Services\IconService - */ class IconService { /** @@ -31,16 +29,19 @@ public function buildFromOfficialLogo(?string $service) : ?string */ public function buildFromResource($resource, $extension) : ?string { - // TODO : controller la valeur de $extension - $filename = self::getRandomName($extension); + if (! $resource || ! $extension) { + return null; + } - if (Storage::disk('icons')->put($filename, $resource)) { - if (self::isValidImageFile($filename, 'icons')) { + $filename = Helpers::getRandomFilename($extension); + + if (IconStore::store($filename, $resource)) { + if (self::isValidImageResource($filename, $resource)) { Log::info(sprintf('Image "%s" successfully stored for import', $filename)); return $filename; } else { - Storage::disk('icons')->delete($filename); + IconStore::delete($filename); } } @@ -52,10 +53,10 @@ public function buildFromResource($resource, $extension) : ?string */ public function buildFromRemoteImage(string $url) : ?string { - $isRemoteData = Str::startsWith($url, ['http://', 'https://']) && Validator::make( + $isRemoteData = Validator::make( [$url], ['url'] - )->passes(); + )->passes() && Str::startsWith($url, ['http://', 'https://']); return $isRemoteData ? $this->storeRemoteImage($url) : null; } @@ -67,7 +68,7 @@ protected function storeRemoteImage(string $url) : ?string { try { $path_parts = pathinfo($url); - $filename = $this->getRandomName($path_parts['extension']); + $filename = Helpers::getRandomFilename($path_parts['extension']); try { $response = Http::withOptions([ @@ -83,9 +84,10 @@ protected function storeRemoteImage(string $url) : ?string return null; } - if (self::isValidImageFile($filename, 'imagesLink')) { + $imagesLinkResource = Storage::disk('imagesLink')->get($filename); + if ($imagesLinkResource && self::isValidImageResource($filename, $imagesLinkResource)) { // Should be a valid image, we move it to the icons disk - if (Storage::disk('icons')->put($filename, Storage::disk('imagesLink')->get($filename))) { + if (IconStore::store($filename, $imagesLinkResource)) { Storage::disk('imagesLink')->delete($filename); } @@ -95,7 +97,7 @@ protected function storeRemoteImage(string $url) : ?string throw new \Exception('Unsupported mimeType or missing image on storage'); } - if (Storage::disk('icons')->exists($filename)) { + if (IconStore::exists($filename)) { return $filename; } } @@ -108,30 +110,32 @@ protected function storeRemoteImage(string $url) : ?string return null; } - /** - * Generate a unique filename - * - */ - private static function getRandomName(string $extension) : string - { - return Str::random(40) . '.' . $extension; - } - /** * Validate a file is a valid image * * @param string $filename - * @param string $disk + * @param string $content */ - public static function isValidImageFile($filename, $disk) : bool + public static function isValidImageResource($filename, $content) : bool { - return in_array(Storage::disk($disk)->mimeType($filename), [ + Storage::disk('temp')->put($filename, $content); + $extension = Str::replace('jpg', 'jpeg', pathinfo($filename, PATHINFO_EXTENSION), false); + $mimeType = Storage::disk('temp')->mimeType($filename); + $acceptedMimeTypes = [ 'image/png', 'image/jpeg', 'image/webp', 'image/bmp', 'image/x-ms-bmp', 'image/svg+xml', - ]) && (Storage::disk($disk)->mimeType($filename) !== 'image/svg+xml' ? getimagesize(Storage::disk($disk)->path($filename)) : true); + ]; + + $isValid = in_array($mimeType, $acceptedMimeTypes) + && ($mimeType !== 'image/svg+xml' ? getimagesize(Storage::disk('temp')->path($filename)) : true) + && Str::contains($mimeType, $extension, true); + + Storage::disk('temp')->delete($filename); + + return $isValid; } } diff --git a/app/Services/IconStoreService.php b/app/Services/IconStoreService.php new file mode 100644 index 00000000..ed579c4f --- /dev/null +++ b/app/Services/IconStoreService.php @@ -0,0 +1,276 @@ +usesDatabase = Settings::get('storeIconsInDatabase'); + $this->setDisk(); + } + + /** + * The storage disk instance + */ + protected function disk() : Filesystem|MockInterface + { + return Storage::disk($this->disk); + } + + /** + * Set the storage disk to use + * + * @return $this + */ + public function setDisk(string $diskName = 'icons') + { + $this->disk = $diskName; + + return $this; + } + + /** + * Whether or not database replication is enabled on the store. + * This should always equals the 'storeIconsInDatabase' setting + */ + public function usesDatabase() : bool + { + return $this->usesDatabase; + } + + /** + * Toggle database replication + */ + public function setDatabaseReplication(bool $usesDatabase) : void + { + if ($this->usesDatabase != $usesDatabase) { + if ($usesDatabase) { + $this->clearDatabase(); + $this->mirrorDiskToDatabase(); + } + else { + $this->mirrorDatabaseToDisk(); + $this->clearDatabase(); + } + + $this->usesDatabase = $usesDatabase; + } + } + + /** + * Insert all registered icons into the database + */ + protected function mirrorDiskToDatabase() : void + { + DB::beginTransaction(); + try { + foreach ($this->registeredIcons() as $filename) { + if ($content = $this->get($filename)) { + $this->storeToDatabase($filename, $content); + } + } + DB::commit(); + } catch (\Exception $e) { + DB::rollback(); + + throw new FailedIconStoreDatabaseTogglingException; + } + } + + /** + * Save all database records as file in the disk + */ + protected function mirrorDatabaseToDisk() : void + { + foreach (Icon::all() as $icon) { + if (! $this->storeToDisk($icon->name, $icon->content)) { + throw new FailedIconStoreDatabaseTogglingException; + } + } + } + + /** + * Get the list of all icon names registered in the TwoFAccount table + * + * @return Collection + */ + protected function registeredIcons() + { + return TwoFAccount::whereNotNull('icon')->pluck('icon'); + } + + /** + * Get the content of a given icon resource, prior to the database record + */ + public function get(string $name) : ?string + { + return $this->usesDatabase + ? Icon::find($name)?->content + : $this->disk()->get($name); + } + + /** + * Get the mime-type of a given icon resource + */ + public function mimeType(string $name) : string|false + { + if ($this->usesDatabase && $this->missingInDisk($name)) { + $this->storeToDisk($name, $this->get($name)); + } + + return $this->disk()->mimeType($name); + } + + /** + * Delete all icons from the storage + */ + public function clear() : bool + { + $diskCleared = $this->clearDisk(); + + if ($diskCleared && $this->usesDatabase) { + $this->clearDatabase(); + } + + return $diskCleared; + } + + /** + * Delete all icons on the disk + */ + protected function clearDisk() : bool + { + $filesForDelete = Arr::where($this->disk()->files(), function (string $filename) { + return Str::endsWith($filename, ['png', 'jpg', 'jpeg', 'bmp', 'webp', 'svg']); + }); + + return $this->disk()->delete($filesForDelete); + } + + /** + * Delete all icons from the database + */ + protected function clearDatabase() : void + { + Icon::truncate(); + } + + /** + * Delete the given icons from the storage + */ + public function delete(array|string $names) : bool + { + $names = is_array($names) ? $names : func_get_args(); + + $deletedFromDisk = $this->disk()->delete($names); + + if ($deletedFromDisk && $this->usesDatabase) { + Icon::destroy($names); + + return Icon::whereIn('name', $names)->count() == 0; + } + + return $deletedFromDisk; + } + + /** + * Create the given icon in the storage + */ + public function store(string $name, string $content) : bool + { + $storedToDisk = $this->storeToDisk($name, $content); + + if ($this->usesDatabase) { + return $this->storeToDatabase($name, $content); + } + + return $storedToDisk; + } + + /** + * Create the given icon in the disk + */ + protected function storeToDisk(string $name, string $content) : bool + { + return $this->disk()->put($name, $content); + } + + /** + * Create the given icon in the database + */ + protected function storeToDatabase(string $name, string $content) : bool + { + $icon = Icon::firstOrNew(['name' => $name]); + $icon->content = $content; + + return $icon->save(); + } + + /** + * Determines if an icon exists in the store, prior to the database. + * If a database record does not have the corresponding file in disk, it will create it. + */ + public function exists(string $name) : bool + { + if ($this->usesDatabase) { + $exists = $this->existsInDatabase($name); + if ($exists && $this->missingInDisk($name)) { + $this->storeToDisk($name, $this->get($name)); + } + + return $exists; + } else { + return $this->existsInDisk($name); + } + } + + /** + * Determine if an icon exists in the database + */ + protected function existsInDatabase(string $name) : bool + { + return Icon::find($name) != null; + } + + /** + * Determine if an icon exists in the database + */ + protected function existsInDisk(string $name) : bool + { + return $this->disk()->exists($name); + } + + /** + * Determine if an icon is missing in the database + */ + protected function missingInDisk(string $name) : bool + { + return ! $this->existsInDisk($name); + } +} diff --git a/app/Services/LogoService.php b/app/Services/LogoService.php index 491afc5c..c66f132f 100644 --- a/app/Services/LogoService.php +++ b/app/Services/LogoService.php @@ -2,14 +2,14 @@ namespace App\Services; +use App\Facades\IconStore; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Str; class LogoService -{ +{ /** * @var \Illuminate\Support\Collection */ @@ -25,6 +25,14 @@ class LogoService */ const TFA_URL = 'https://2fa.directory/api/v3/tfa.json'; + /** + * @var string + */ + const TFA_IMG_URL = 'https://raw.githubusercontent.com/2factorauth/twofactorauth/master/img/'; + + /** + * + */ public function __construct() { $this->setTfaCollection(); @@ -41,9 +49,10 @@ public function getIcon(?string $serviceName) $logoFilename = $this->getLogo(strval($serviceName)); if ($logoFilename) { - $iconFilename = Str::random(40) . '.svg'; + // $iconFilename = IconService::getRandomName('svg'); + $iconFilename = \Illuminate\Support\Str::random(40) . '.svg'; - return $this->copyToIcons($logoFilename, $iconFilename) ? $iconFilename : null; + return $this->copyToIconStore($logoFilename, $iconFilename) ? $iconFilename : null; } else { return null; } @@ -121,7 +130,7 @@ protected function fetchLogo(string $logoFile) : void try { $response = Http::withOptions([ 'proxy' => config('2fauth.config.outgoingProxy'), - ])->retry(3, 100)->get('https://raw.githubusercontent.com/2factorauth/twofactorauth/master/img/' . $logoFile[0] . '/' . $logoFile); + ])->retry(3, 100)->get(self::TFA_IMG_URL . $logoFile[0] . '/' . $logoFile); if ($response->successful()) { Storage::disk('logos')->put($logoFile, $response->body()) @@ -144,14 +153,18 @@ protected function cleanDomain(string $domain) : string } /** - * Copy a logo file to the icons disk with a new name + * Copy a logo file to the icons store with a new name * * @param string $logoFilename * @param string $iconFilename - * @return bool Weither the copy succed or not + * @return bool Whether the copy succeed or not */ - protected function copyToIcons($logoFilename, $iconFilename) : bool + protected function copyToIconStore($logoFilename, $iconFilename) : bool { - return Storage::disk('icons')->put($iconFilename, Storage::disk('logos')->get($logoFilename)); + if ($content = Storage::disk('logos')->get($logoFilename)) { + return IconStore::store($iconFilename, $content); + } + + return false; } } diff --git a/app/Services/SettingService.php b/app/Services/SettingService.php index 6244bada..cc48da31 100644 --- a/app/Services/SettingService.php +++ b/app/Services/SettingService.php @@ -2,6 +2,7 @@ namespace App\Services; +use App\Events\storeIconsInDatabaseSettingChanged; use App\Exceptions\DbEncryptionException; use App\Models\Option; use Exception; @@ -67,26 +68,23 @@ public function all() : Collection /** * Set a setting * - * @param string|array $setting A single setting name or an associative array of name:value settings - * @param string|int|bool|null $value The value for single setting + * @param string $setting A single setting name + * @param string|int|bool $value The value for single setting */ - public function set($setting, $value = null) : void + public function set($setting, $value) : void { - $settings = is_array($setting) ? $setting : [$setting => $value]; - - foreach ($settings as $setting => $value) { - if ($setting === 'useEncryption') { - $this->setEncryptionTo($value); - } - - $settings[$setting] = $this->replaceBoolean($value); + // TODO: Move setEncryptionTo() logic to a dedicated class + if ($setting === 'useEncryption') { + $this->setEncryptionTo($value); } - foreach ($settings as $setting => $value) { - Option::updateOrCreate(['key' => $setting], ['value' => $value]); - Log::notice(sprintf('App setting %s set to %s', var_export($setting, true), var_export($this->restoreType($value), true))); + if ($setting === 'storeIconsInDatabase') { + storeIconsInDatabaseSettingChanged::dispatch($value); } + Option::updateOrCreate(['key' => $setting], ['value' => $this->replaceBoolean($value)]); + Log::notice(sprintf('App setting %s set to %s', var_export($setting, true), var_export($this->restoreType($value), true))); + self::buildAndCache(); } @@ -207,6 +205,7 @@ private function updateRecords(bool $encrypted) : bool { $success = true; $twofaccounts = DB::table('twofaccounts')->get(); + $icons = DB::table('icons')->get(); $twofaccounts->each(function ($item, $key) use (&$success, $encrypted) { try { @@ -227,6 +226,17 @@ private function updateRecords(bool $encrypted) : bool } }); + $icons->each(function ($item, $key) use (&$success, $encrypted) { + try { + $item->content = $encrypted ? Crypt::encryptString($item->content) : Crypt::decryptString($item->content); + } catch (Exception $ex) { + $success = false; + + // Exit the each iteration + return false; + } + }); + if ($success) { // The whole collection has now its sensible data encrypted/decrypted // We update the db using a transaction that can rollback everything if an error occured @@ -244,6 +254,14 @@ private function updateRecords(bool $encrypted) : bool ]); }); + $icons->each(function ($item, $key) { + DB::table('icons') + ->where('name', $item->name) + ->update([ + 'content' => $item->content, + ]); + }); + DB::commit(); return true; diff --git a/config/2fauth.php b/config/2fauth.php index e2f0697c..e0c95163 100644 --- a/config/2fauth.php +++ b/config/2fauth.php @@ -94,6 +94,7 @@ 'restrictList' => '', 'restrictRule' => '', 'keepSsoRegistrationEnabled' => false, + 'storeIconsInDatabase' => false, ], /* diff --git a/config/filesystems.php b/config/filesystems.php index 51ac99ae..a15928ec 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -13,6 +13,7 @@ | */ + // TODO : disable this env var and make driver be set from admin panel 'default' => env('FILESYSTEM_DISK', env('FILESYSTEM_DRIVER', 'local')), /* @@ -44,6 +45,18 @@ 'throw' => false, ], + // 'tempicons' => [ + // 'driver' => 'local', + // 'root' => storage_path('app/tempicons'), + // 'throw' => false, + // ], + + 'temp' => [ + 'driver' => 'local', + 'root' => storage_path('app/temp'), + 'throw' => false, + ], + 'logos' => [ 'driver' => 'local', 'root' => storage_path('app/logos'), diff --git a/database/factories/IconFactory.php b/database/factories/IconFactory.php new file mode 100644 index 00000000..c4c2f978 --- /dev/null +++ b/database/factories/IconFactory.php @@ -0,0 +1,86 @@ + + */ +class IconFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + return [ + 'name' => OtpTestData::ICON_PNG, + 'content' => base64_decode(OtpTestData::ICON_PNG_DATA), + ]; + } + + /** + * Indicate that the icon is a jpeg image. + * + * @return \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Icon> + */ + public function jpeg() + { + return $this->state(function (array $attributes) { + return [ + 'name' => OtpTestData::ICON_JPEG, + 'content' => base64_decode(OtpTestData::ICON_JPEG_DATA), + ]; + }); + } + + /** + * Indicate that the icon is a webp image. + * + * @return \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Icon> + */ + public function webp() + { + return $this->state(function (array $attributes) { + return [ + 'name' => OtpTestData::ICON_WEBP, + 'content' => base64_decode(OtpTestData::ICON_WEBP_DATA), + ]; + }); + } + + /** + * Indicate that the icon is a bmp image. + * + * @return \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Icon> + */ + public function bmp() + { + return $this->state(function (array $attributes) { + return [ + 'name' => OtpTestData::ICON_BMP, + 'content' => base64_decode(OtpTestData::ICON_BMP_DATA), + ]; + }); + } + + /** + * Indicate that the icon is a svg image. + * + * @return \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Icon> + */ + public function svg() + { + return $this->state(function (array $attributes) { + return [ + 'name' => OtpTestData::ICON_SVG, + 'content' => base64_decode(OtpTestData::ICON_SVG_DATA_ENCODED), + ]; + }); + } +} \ No newline at end of file diff --git a/database/migrations/2021_09_14_195451_change_nullable_in_twofaccounts_table.php b/database/migrations/2021_09_14_195451_change_nullable_in_twofaccounts_table.php index 15a0f5ee..037282a8 100644 --- a/database/migrations/2021_09_14_195451_change_nullable_in_twofaccounts_table.php +++ b/database/migrations/2021_09_14_195451_change_nullable_in_twofaccounts_table.php @@ -1,12 +1,12 @@ select('id', 'legacy_uri')->get(); foreach ($twofaccounts as $twofaccount) { try { - $legacy_uri = Settings::get('useEncryption') ? Crypt::decryptString($twofaccount->legacy_uri) : $twofaccount->legacy_uri; + $legacy_uri = $settingService->get('useEncryption') ? Crypt::decryptString($twofaccount->legacy_uri) : $twofaccount->legacy_uri; $token = \OTPHP\Factory::loadFromProvisioningUri($legacy_uri); $affected = DB::table('twofaccounts') ->where('id', $twofaccount->id) ->update([ 'otp_type' => get_class($token) === 'OTPHP\TOTP' ? 'totp' : 'hotp', - 'secret' => Settings::get('useEncryption') ? Crypt::encryptString($token->getSecret()) : $token->getSecret(), + 'secret' => $settingService->get('useEncryption') ? Crypt::encryptString($token->getSecret()) : $token->getSecret(), 'algorithm' => $token->getDigest(), 'digits' => $token->getDigits(), 'period' => $token->hasParameter('period') ? $token->getParameter('period') : null, diff --git a/database/migrations/2024_08_08_133136_encrypt_twofaccount_service_field.php b/database/migrations/2024_08_08_133136_encrypt_twofaccount_service_field.php index 9722bbee..bf3d4f00 100644 --- a/database/migrations/2024_08_08_133136_encrypt_twofaccount_service_field.php +++ b/database/migrations/2024_08_08_133136_encrypt_twofaccount_service_field.php @@ -1,7 +1,7 @@ get('useEncryption'); } /** diff --git a/database/migrations/2024_09_30_110610_create_icons_table.php b/database/migrations/2024_09_30_110610_create_icons_table.php new file mode 100644 index 00000000..38456b3e --- /dev/null +++ b/database/migrations/2024_09_30_110610_create_icons_table.php @@ -0,0 +1,28 @@ +string('name')->primary(); + $table->longText('content'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('icons'); + } +}; diff --git a/database/seeders/TestingSeeder.php b/database/seeders/TestingSeeder.php index 6f814632..dc6a61b9 100644 --- a/database/seeders/TestingSeeder.php +++ b/database/seeders/TestingSeeder.php @@ -3,8 +3,6 @@ namespace Database\Seeders; use App\Models\User; -use App\Models\Group; -use App\Models\TwoFAccount; use Illuminate\Database\Seeder; class TestingSeeder extends Seeder diff --git a/resources/js/icons.js b/resources/js/icons.js index dc07f04b..dfa30e45 100644 --- a/resources/js/icons.js +++ b/resources/js/icons.js @@ -120,7 +120,7 @@ library.add( faTabletScreenButton, faDisplay, faCalendar, - faArrowUpLong + faArrowUpLong, ); export default FontAwesomeIcon \ No newline at end of file diff --git a/resources/js/views/admin/AppSetup.vue b/resources/js/views/admin/AppSetup.vue index 9b0f60a1..f6f7cadd 100644 --- a/resources/js/views/admin/AppSetup.vue +++ b/resources/js/views/admin/AppSetup.vue @@ -97,9 +97,12 @@