diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 4cec837a..04478e58 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -17,6 +17,7 @@ // Syntax & consistency 'array_syntax' => ['syntax' => 'short'], 'binary_operator_spaces' => ['default' => 'single_space'], + 'cast_spaces' => ['space' => 'single'], 'concat_space' => ['spacing' => 'one'], 'single_quote' => true, 'trailing_comma_in_multiline' => true, diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e260f81..ce201644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated CI pipeline to test against PHP 7.4, 8.0, and 8.1 - CI now fails on PHP warnings and deprecations for stricter quality control - Added `declare(strict_types=1)` to all Exception classes for improved type safety +- **BREAKING:** Refactored model architecture: + - Introduced a base Model class for non-database models + - Refactored QtModel into DbModel with persistence-only responsibilities + - Database fetch methods (first(), findOne(), findOneBy(), get()) now return new model instances instead of mutating existing ones + - Calling create() resets model state to ensure clean inserts + - Database-generated primary keys are now synced into the model after save() + - Models are hydrated only on fetch operations, not implicitly via getters ### Fixed - PHP 8.1 compatibility: Fixed null parameter deprecations in `explode()`, `parse_url()`, and `str_replace()` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1345b22c..29c31fe2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,8 @@ Thanks for your interest in contributing to Quantum PHP Framework 💡 Whether y ## Before You Start -- Familiarize yourself with the codebase: Quantum PHP Framework is modular — most features live under `/src` (core logic) and `/modules` (demo templates and optional components). Start by reviewing the `Router`, `Controller`, and `QtModel` classes to understand the framework flow. +- Familiarize yourself with the codebase: Quantum PHP Framework is modular — most features live under `/src` (core logic) and `/modules` (demo templates and optional components). +- Start by reviewing the `Router`, `Controller`, and `Model` classes to understand the framework flow. - Check existing issues and milestones: look for tickets labeled `good first issue`, `help wanted`, or assigned to an upcoming version. - Don’t hesitate to open a new issue if you find something worth improving. diff --git a/src/App/Helpers/misc.php b/src/App/Helpers/misc.php index 2baee3b1..a008e3b3 100644 --- a/src/App/Helpers/misc.php +++ b/src/App/Helpers/misc.php @@ -59,7 +59,7 @@ function random_number(int $length = 10): int for ($i = 0; $i < $length; $i++) { $randomString .= random_int(0, 9); } - return (int)$randomString; + return (int) $randomString; } /** diff --git a/src/App/Traits/AppTrait.php b/src/App/Traits/AppTrait.php index c2ddfc3e..bc22f6a5 100644 --- a/src/App/Traits/AppTrait.php +++ b/src/App/Traits/AppTrait.php @@ -17,11 +17,9 @@ use Quantum\Libraries\Logger\Factories\LoggerFactory; use Quantum\Libraries\Lang\Exceptions\LangException; use Quantum\Libraries\Lang\Factories\LangFactory; -use Quantum\Environment\Exceptions\EnvException; use Quantum\Config\Exceptions\ConfigException; use Quantum\App\Exceptions\BaseException; use Quantum\Di\Exceptions\DiException; -use Quantum\Environment\Environment; use Quantum\Tracer\ErrorHandler; use Quantum\Loader\Loader; use Quantum\Config\Config; @@ -125,18 +123,6 @@ protected function loadModuleHelperFunctions(): void $loader->loadDir(App::getBaseDir() . DS . 'modules' . DS . '*' . DS . 'helpers'); } - /** - * @return void - * @throws DiException - * @throws ReflectionException - * @throws EnvException - * @throws BaseException - */ - protected function loadEnvironment() - { - Environment::getInstance()->load(new Setup('config', 'env')); - } - /** * @return void * @throws DiException diff --git a/src/App/Traits/ConsoleAppTrait.php b/src/App/Traits/ConsoleAppTrait.php index 21ae36e4..7c4c7b49 100644 --- a/src/App/Traits/ConsoleAppTrait.php +++ b/src/App/Traits/ConsoleAppTrait.php @@ -14,8 +14,13 @@ namespace Quantum\App\Traits; +use Quantum\Environment\Exceptions\EnvException; use Symfony\Component\Console\Application; +use Quantum\App\Exceptions\BaseException; +use Quantum\Di\Exceptions\DiException; use Quantum\Console\CommandDiscovery; +use Quantum\Environment\Environment; +use Quantum\Loader\Setup; use ReflectionException; use Exception; @@ -25,6 +30,19 @@ */ trait ConsoleAppTrait { + /** + * @throws DiException + * @throws ReflectionException + * @throws EnvException + * @throws BaseException + */ + protected function loadEnvironment() + { + Environment::getInstance() + ->setMutable(true) + ->load(new Setup('config', 'env')); + } + /** * @param string $name * @param string $version diff --git a/src/App/Traits/WebAppTrait.php b/src/App/Traits/WebAppTrait.php index 00d7ae28..7dd9c036 100644 --- a/src/App/Traits/WebAppTrait.php +++ b/src/App/Traits/WebAppTrait.php @@ -15,6 +15,7 @@ namespace Quantum\App\Traits; use Quantum\App\Exceptions\StopExecutionException; +use Quantum\Environment\Exceptions\EnvException; use Quantum\Libraries\ResourceCache\ViewCache; use Quantum\Module\Exceptions\ModuleException; use Quantum\Config\Exceptions\ConfigException; @@ -22,6 +23,7 @@ use Quantum\Http\Exceptions\HttpException; use Quantum\App\Exceptions\BaseException; use Quantum\Di\Exceptions\DiException; +use Quantum\Environment\Environment; use Quantum\Module\ModuleLoader; use Quantum\Router\RouteBuilder; use DebugBar\DebugBarException; @@ -40,6 +42,17 @@ */ trait WebAppTrait { + /** + * @throws DiException + * @throws ReflectionException + * @throws EnvException + * @throws BaseException + */ + protected function loadEnvironment() + { + Environment::getInstance()->load(new Setup('config', 'env')); + } + /** * @param Request $request * @param Response $response diff --git a/src/Console/Commands/KeyGenerateCommand.php b/src/Console/Commands/KeyGenerateCommand.php index 9a13382e..b8d3ddb5 100644 --- a/src/Console/Commands/KeyGenerateCommand.php +++ b/src/Console/Commands/KeyGenerateCommand.php @@ -80,6 +80,6 @@ public function exec() */ private function generateRandomKey(): string { - return bin2hex(random_bytes((int)$this->getOption('length'))); + return bin2hex(random_bytes((int) $this->getOption('length'))); } } diff --git a/src/Console/Commands/MigrationMigrateCommand.php b/src/Console/Commands/MigrationMigrateCommand.php index 6036e809..65ef7d6f 100644 --- a/src/Console/Commands/MigrationMigrateCommand.php +++ b/src/Console/Commands/MigrationMigrateCommand.php @@ -75,7 +75,7 @@ public function exec() return; } - $step = (int)$this->getOption('step') ?: null; + $step = (int) $this->getOption('step') ?: null; $migrationManager = new MigrationManager(); diff --git a/src/Console/Commands/ModuleGenerateCommand.php b/src/Console/Commands/ModuleGenerateCommand.php index 205e4a5b..713405c3 100644 --- a/src/Console/Commands/ModuleGenerateCommand.php +++ b/src/Console/Commands/ModuleGenerateCommand.php @@ -84,6 +84,7 @@ public function exec() $this->info($moduleName . ' module successfully created'); } catch (Exception $e) { $this->error($e->getMessage()); + exit(1); } } } diff --git a/src/Environment/Environment.php b/src/Environment/Environment.php index 57a24e75..e953add8 100644 --- a/src/Environment/Environment.php +++ b/src/Environment/Environment.php @@ -15,6 +15,7 @@ namespace Quantum\Environment; use Quantum\Environment\Exceptions\EnvException; +use Quantum\Config\Exceptions\ConfigException; use Quantum\App\Exceptions\BaseException; use Quantum\Di\Exceptions\DiException; use Quantum\Environment\Enums\Env; @@ -36,26 +37,34 @@ class Environment * Environment file * @var string */ - private $envFile = '.env'; + private string $envFile = '.env'; /** * @var bool */ - private $isMutable = false; + private bool $isMutable = false; /** * Loaded env content * @var array */ - private $envContent = []; + private array $envContent = []; - private static $appEnv = Env::PRODUCTION; + /** + * @var bool + */ + private bool $loaded = false; + + /** + * @var string + */ + private static string $appEnv = Env::PRODUCTION; /** * Instance of Environment - * @var Environment + * @var Environment|null */ - private static $instance = null; + private static ?Environment $instance = null; /** * GetInstance @@ -91,7 +100,7 @@ public function setMutable(bool $isMutable): Environment */ public function load(Setup $setup) { - if (!empty($this->envContent)) { + if ($this->loaded) { return; } @@ -101,16 +110,13 @@ public function load(Setup $setup) $this->envFile = '.env' . ($appEnv !== Env::PRODUCTION ? ".$appEnv" : ''); - if (!file_exists(App::getBaseDir() . DS . $this->envFile)) { + if (!fs()->exists($this->getEnvFilePath())) { throw EnvException::fileNotFound($this->envFile); } - $dotenv = $this->isMutable - ? Dotenv::createMutable(App::getBaseDir(), $this->envFile) - : Dotenv::createImmutable(App::getBaseDir(), $this->envFile); - - $this->envContent = $dotenv->load(); + $this->envContent = $this->loadDotenvFile(); + $this->loaded = true; self::$appEnv = $appEnv; } @@ -132,7 +138,7 @@ public function getAppEnv(): string */ public function getValue(string $key, $default = null) { - if (empty($this->envContent)) { + if (!$this->loaded) { throw EnvException::environmentNotLoaded(); } @@ -140,9 +146,7 @@ public function getValue(string $key, $default = null) return $this->envContent[$key]; } - $val = getenv($key); - - return $val !== false ? $val : $default; + return $default; } /** @@ -169,7 +173,12 @@ public function getRow(string $key): ?string * Creates or updates the row in .env * @param string $key * @param string|null $value + * @return void + * @throws BaseException + * @throws DiException * @throws EnvException + * @throws ReflectionException + * @throws ConfigException */ public function updateRow(string $key, ?string $value) { @@ -177,23 +186,23 @@ public function updateRow(string $key, ?string $value) throw EnvException::environmentImmutable(); } - if (empty($this->envContent)) { + if (!$this->loaded) { throw EnvException::environmentNotLoaded(); } + $envFilePath = $this->getEnvFilePath(); $row = $this->getRow($key); - $envFilePath = App::getBaseDir() . DS . $this->envFile; - if ($row) { - $envFileContent = file_get_contents($envFilePath); + $envFileContent = fs()->get($envFilePath); $envFileContent = preg_replace('/^' . preg_quote($row, '/') . '/m', $key . '=' . $value, $envFileContent); - file_put_contents($envFilePath, $envFileContent); + + fs()->put($envFilePath, $envFileContent); } else { - file_put_contents($envFilePath, PHP_EOL . $key . '=' . $value . PHP_EOL, FILE_APPEND); + fs()->append($envFilePath, PHP_EOL . $key . '=' . $value . PHP_EOL); } - $this->envContent = Dotenv::createMutable(App::getBaseDir(), $this->envFile)->load(); + $this->envContent = $this->loadDotenvFile(true); } /** @@ -211,4 +220,29 @@ private function findKeyRow(string $key): ?string return null; } + + /** + * @param bool $forceMutableReload + * @return array + */ + private function loadDotenvFile(bool $forceMutableReload = false): array + { + $baseDir = App::getBaseDir(); + + $dotenv = ($forceMutableReload || $this->isMutable) + ? Dotenv::createMutable($baseDir, $this->envFile) + : Dotenv::createImmutable($baseDir, $this->envFile); + + $loadedVars = $dotenv->load(); + + return is_array($loadedVars) ? $loadedVars : []; + } + + /** + * @return string + */ + private function getEnvFilePath(): string + { + return App::getBaseDir() . DS . $this->envFile; + } } diff --git a/src/Http/Request/HttpRequest.php b/src/Http/Request/HttpRequest.php index 3e794e29..828bebe5 100644 --- a/src/Http/Request/HttpRequest.php +++ b/src/Http/Request/HttpRequest.php @@ -195,7 +195,7 @@ public static function getCsrfToken(): ?string $csrfToken = null; if (self::has(Csrf::TOKEN_KEY)) { - $csrfToken = (string)self::get(Csrf::TOKEN_KEY); + $csrfToken = (string) self::get(Csrf::TOKEN_KEY); } elseif (self::hasHeader('X-' . Csrf::TOKEN_KEY)) { $csrfToken = self::getHeader('X-' . Csrf::TOKEN_KEY); } @@ -275,6 +275,6 @@ private static function setContentType() */ private static function setRequestHeaders() { - self::$__headers = array_change_key_case((array)getallheaders()); + self::$__headers = array_change_key_case((array) getallheaders()); } } diff --git a/src/Http/Traits/Request/Header.php b/src/Http/Traits/Request/Header.php index b3222c24..65799108 100644 --- a/src/Http/Traits/Request/Header.php +++ b/src/Http/Traits/Request/Header.php @@ -91,7 +91,7 @@ public static function getAuthorizationBearer(): ?string { $bearerToken = null; - $authorization = (string)self::getHeader('Authorization'); + $authorization = (string) self::getHeader('Authorization'); if (self::hasHeader('Authorization') && preg_match('/Bearer\s(\S+)/', $authorization, $matches)) { $bearerToken = $matches[1]; @@ -117,7 +117,7 @@ public static function getBasicAuthCredentials(): ?array return null; } - $authorization = (string)self::getHeader('Authorization'); + $authorization = (string) self::getHeader('Authorization'); if (preg_match('/Basic\s(\S+)/', $authorization, $matches)) { $decoded = base64_decode($matches[1], true); diff --git a/src/Libraries/Auth/Factories/AuthFactory.php b/src/Libraries/Auth/Factories/AuthFactory.php index dfe3ad30..54296358 100644 --- a/src/Libraries/Auth/Factories/AuthFactory.php +++ b/src/Libraries/Auth/Factories/AuthFactory.php @@ -137,6 +137,6 @@ private static function createAuthService(string $adapter): AuthServiceInterface */ private static function createJwtInstance(string $adapter): ?JwtToken { - return $adapter === Auth::JWT ? (new JwtToken())->setLeeway(1)->setClaims((array)config()->get('auth.claims')) : null; + return $adapter === Auth::JWT ? (new JwtToken())->setLeeway(1)->setClaims((array) config()->get('auth.claims')) : null; } } diff --git a/src/Libraries/Cache/Adapters/DatabaseAdapter.php b/src/Libraries/Cache/Adapters/DatabaseAdapter.php index dab6eab8..b9458243 100644 --- a/src/Libraries/Cache/Adapters/DatabaseAdapter.php +++ b/src/Libraries/Cache/Adapters/DatabaseAdapter.php @@ -18,7 +18,7 @@ use Quantum\Model\Factories\ModelFactory; use Psr\SimpleCache\CacheInterface; use InvalidArgumentException; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; use Exception; /** @@ -38,9 +38,9 @@ class DatabaseAdapter implements CacheInterface private $prefix; /** - * @var QtModel + * @var DbModel */ - private $cacheModel; + private DbModel $cacheModel; /** * @param array $params @@ -154,7 +154,7 @@ public function delete($key): bool $cacheItem = $this->cacheModel->findOneBy('key', $this->keyHash($key)); if (!empty($cacheItem->asArray())) { - return $this->cacheModel->delete(); + return $cacheItem->delete(); } return false; diff --git a/src/Libraries/Cron/CronLock.php b/src/Libraries/Cron/CronLock.php index e5b0d68d..203a076a 100644 --- a/src/Libraries/Cron/CronLock.php +++ b/src/Libraries/Cron/CronLock.php @@ -79,6 +79,16 @@ public function refresh(): bool return $this->writeTimestampToHandle($this->lockHandle); } + public function getTimestamp(): int + { + if ($this->lockHandle === null) { + return 0; + } + + $timestamp = $this->readTimestampFromHandle($this->lockHandle); + return $timestamp ?? 0; + } + public function release(): bool { if (!$this->ownsLock || $this->lockHandle === null) { @@ -226,9 +236,14 @@ private function writeTimestampToHandle($handle): bool if (rewind($handle) === false) { return false; } - if (fwrite($handle, (string) time()) === false) { + + $timestamp = (string) time(); + $bytes = fwrite($handle, $timestamp); + + if ($bytes === false) { return false; } + if (fflush($handle) === false) { return false; } diff --git a/src/Libraries/Database/Adapters/Idiorm/Statements/Join.php b/src/Libraries/Database/Adapters/Idiorm/Statements/Join.php index 61dcf6cd..610a8623 100644 --- a/src/Libraries/Database/Adapters/Idiorm/Statements/Join.php +++ b/src/Libraries/Database/Adapters/Idiorm/Statements/Join.php @@ -19,7 +19,7 @@ use Quantum\Libraries\Database\Enums\Relation; use Quantum\Model\Exceptions\ModelException; use Quantum\App\Exceptions\BaseException; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Trait Join @@ -78,7 +78,7 @@ public function rightJoin(string $table, array $constraint, ?string $tableAlias * @throws BaseException * @throws ModelException */ - public function joinTo(QtModel $relatedModel, bool $switch = true): DbalInterface + public function joinTo(DbModel $relatedModel, bool $switch = true): DbalInterface { $relation = $this->getValidatedRelation($relatedModel); @@ -107,12 +107,12 @@ public function joinTo(QtModel $relatedModel, bool $switch = true): DbalInterfac } /** - * @param QtModel $relatedModel + * @param DbModel $relatedModel * @param array $relation * @return void * @throws BaseException */ - protected function applyHasRelation(QtModel $relatedModel, array $relation): void + protected function applyHasRelation(DbModel $relatedModel, array $relation): void { $this->getOrmModel()->join( $relatedModel->table, @@ -125,12 +125,12 @@ protected function applyHasRelation(QtModel $relatedModel, array $relation): voi } /** - * @param QtModel $relatedModel + * @param DbModel $relatedModel * @param array $relation * @return void * @throws BaseException */ - protected function applyBelongsTo(QtModel $relatedModel, array $relation): void + protected function applyBelongsTo(DbModel $relatedModel, array $relation): void { $this->getOrmModel()->join( $relatedModel->table, @@ -143,11 +143,11 @@ protected function applyBelongsTo(QtModel $relatedModel, array $relation): void } /** - * @param QtModel $modelToJoin + * @param DbModel $modelToJoin * @return array * @throws ModelException */ - private function getValidatedRelation(QtModel $modelToJoin): array + private function getValidatedRelation(DbModel $modelToJoin): array { $relations = $this->getForeignKeys(); $relatedModelName = get_class($modelToJoin); diff --git a/src/Libraries/Database/Adapters/Sleekdb/Statements/Join.php b/src/Libraries/Database/Adapters/Sleekdb/Statements/Join.php index e0fcc7fd..32d60e8b 100644 --- a/src/Libraries/Database/Adapters/Sleekdb/Statements/Join.php +++ b/src/Libraries/Database/Adapters/Sleekdb/Statements/Join.php @@ -19,7 +19,7 @@ use SleekDB\Exceptions\InvalidArgumentException; use Quantum\Libraries\Database\Enums\Relation; use Quantum\Model\Exceptions\ModelException; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; use SleekDB\QueryBuilder; /** @@ -31,7 +31,7 @@ trait Join /** * @inheritDoc */ - public function joinTo(QtModel $model, bool $switch = true): DbalInterface + public function joinTo(DbModel $model, bool $switch = true): DbalInterface { $this->joins[] = [ 'model' => serialize($model), @@ -97,14 +97,14 @@ private function applyJoin(QueryBuilder $queryBuilder, SleekDbal $currentItem, a /** * Apply join condition for JOINTO type * @param QueryBuilder $queryBuilder - * @param QtModel $relatedModel + * @param DbModel $relatedModel * @param SleekDbal $currentModel * @param array $currentItem * @return void * @throws InvalidArgumentException * @throws ModelException */ - private function applyJoinTo(QueryBuilder $queryBuilder, QtModel $relatedModel, SleekDbal $currentModel, array $currentItem): void + private function applyJoinTo(QueryBuilder $queryBuilder, DbModel $relatedModel, SleekDbal $currentModel, array $currentItem): void { $relation = $this->getValidatedRelation($currentModel, $relatedModel); @@ -163,11 +163,11 @@ private function applyBelongsTo(QueryBuilder $queryBuilder, array $currentItem, /** * @param SleekDbal $currentModel - * @param QtModel $relatedModel + * @param DbModel $relatedModel * @return array * @throws ModelException */ - private function getValidatedRelation(SleekDbal $currentModel, QtModel $relatedModel): array + private function getValidatedRelation(SleekDbal $currentModel, DbModel $relatedModel): array { $relations = $currentModel->getForeignKeys(); $relatedModelName = get_class($relatedModel); diff --git a/src/Libraries/Database/Contracts/DbalInterface.php b/src/Libraries/Database/Contracts/DbalInterface.php index 88c143de..0a0b6d94 100644 --- a/src/Libraries/Database/Contracts/DbalInterface.php +++ b/src/Libraries/Database/Contracts/DbalInterface.php @@ -14,7 +14,7 @@ namespace Quantum\Libraries\Database\Contracts; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Database Abstract Layer interface @@ -185,11 +185,11 @@ public function deleteMany(): bool; /** * Joins two models - * @param QtModel $model + * @param DbModel $model * @param bool $switch * @return DbalInterface */ - public function joinTo(QtModel $model, bool $switch = true): DbalInterface; + public function joinTo(DbModel $model, bool $switch = true): DbalInterface; /** * Checks if the given column is NULL diff --git a/src/Libraries/Database/Schemas/Table.php b/src/Libraries/Database/Schemas/Table.php index 478f7c99..9df16fa1 100644 --- a/src/Libraries/Database/Schemas/Table.php +++ b/src/Libraries/Database/Schemas/Table.php @@ -63,22 +63,22 @@ class Table /** * @var string */ - private $name; + private string $name; /** * @var string */ - private $newName; + private string $newName = ''; /** - * @var int + * @var int|null */ - private $action = null; + private ?int $action = null; /** * @var array */ - private $columns = []; + private array $columns = []; /** * @var array @@ -330,6 +330,6 @@ private function checkColumnExists(string $columnName): bool */ private function columnKey(): int { - return (int)array_key_last($this->columns); + return (int) array_key_last($this->columns); } } diff --git a/src/Libraries/Jwt/JwtToken.php b/src/Libraries/Jwt/JwtToken.php index 9d0b27ae..acf22922 100644 --- a/src/Libraries/Jwt/JwtToken.php +++ b/src/Libraries/Jwt/JwtToken.php @@ -159,7 +159,7 @@ public function fetchPayload(): ?object */ public function fetchData(): ?array { - return isset($this->fetchedPayload->data) ? (array)$this->fetchedPayload->data : null; + return isset($this->fetchedPayload->data) ? (array) $this->fetchedPayload->data : null; } /** diff --git a/src/Libraries/Lang/Factories/LangFactory.php b/src/Libraries/Lang/Factories/LangFactory.php index 6549f6a2..db9e98d2 100644 --- a/src/Libraries/Lang/Factories/LangFactory.php +++ b/src/Libraries/Lang/Factories/LangFactory.php @@ -71,7 +71,7 @@ private static function loadLangConfig(): array return [ filter_var(config()->get('lang.enabled'), FILTER_VALIDATE_BOOLEAN), - (array)config()->get('lang.supported'), + (array) config()->get('lang.supported'), config()->get('lang.default'), ]; } @@ -122,7 +122,7 @@ private static function getLangFromQuery(array $supported): ?string */ private static function getLangFromUrlSegment(array $supported): ?string { - $segmentIndex = (int)config()->get('lang.url_segment'); + $segmentIndex = (int) config()->get('lang.url_segment'); if (!in_array(route_prefix(), [null, '', '0'], true) && $segmentIndex === 1) { $segmentIndex++; diff --git a/src/Libraries/Storage/Adapters/Dropbox/DropboxApp.php b/src/Libraries/Storage/Adapters/Dropbox/DropboxApp.php index 18c3b391..582c6c5f 100644 --- a/src/Libraries/Storage/Adapters/Dropbox/DropboxApp.php +++ b/src/Libraries/Storage/Adapters/Dropbox/DropboxApp.php @@ -273,7 +273,7 @@ private function accessTokenNeedsRefresh(int $code, ?object $message = null): bo } if (isset($message->error)) { - $error = (array)$message->error; + $error = (array) $message->error; if (!isset($error['.tag']) && !in_array($error['.tag'], self::ACCESS_TOKEN_STATUS)) { return false; diff --git a/src/Libraries/Storage/Adapters/Dropbox/DropboxFileSystemAdapter.php b/src/Libraries/Storage/Adapters/Dropbox/DropboxFileSystemAdapter.php index 9f41f573..06bb46e6 100644 --- a/src/Libraries/Storage/Adapters/Dropbox/DropboxFileSystemAdapter.php +++ b/src/Libraries/Storage/Adapters/Dropbox/DropboxFileSystemAdapter.php @@ -68,7 +68,7 @@ public function removeDirectory(string $dirname): bool public function get(string $filename) { try { - return (string)$this->dropboxApp->contentRequest(DropboxApp::ENDPOINT_DOWNLOAD_FILE, $this->dropboxApp->path($filename)); + return (string) $this->dropboxApp->contentRequest(DropboxApp::ENDPOINT_DOWNLOAD_FILE, $this->dropboxApp->path($filename)); } catch (Exception $e) { return false; } @@ -151,7 +151,7 @@ public function exists(string $filename): bool public function size(string $filename) { try { - $meta = (array)$this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($filename)); + $meta = (array) $this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($filename)); return $meta['size']; } catch (Exception $e) { return false; @@ -164,7 +164,7 @@ public function size(string $filename) public function lastModified(string $filename) { try { - $meta = (array)$this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($filename)); + $meta = (array) $this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($filename)); return isset($meta['server_modified']) ? strtotime($meta['server_modified']) : false; } catch (Exception $e) { return false; @@ -192,7 +192,7 @@ public function remove(string $filename): bool public function isFile(string $filename): bool { try { - $meta = (array)$this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($filename)); + $meta = (array) $this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($filename)); return $meta['.tag'] == 'file'; } catch (Exception $e) { return false; @@ -206,7 +206,7 @@ public function isFile(string $filename): bool public function isDirectory(string $dirname): bool { try { - $meta = (array)$this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($dirname)); + $meta = (array) $this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_FILE_METADATA, $this->dropboxApp->path($dirname)); return $meta['.tag'] == 'folder'; } catch (Exception $e) { return false; @@ -219,7 +219,7 @@ public function isDirectory(string $dirname): bool public function listDirectory(string $dirname) { try { - $response = (array)$this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_LIST_FOLDER, $this->dropboxApp->path($dirname)); + $response = (array) $this->dropboxApp->rpcRequest(DropboxApp::ENDPOINT_LIST_FOLDER, $this->dropboxApp->path($dirname)); return $response['entries']; } catch (Exception $e) { return false; diff --git a/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveApp.php b/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveApp.php index e8253acb..b6bd911b 100644 --- a/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveApp.php +++ b/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveApp.php @@ -193,7 +193,7 @@ public function rpcRequest(string $url, $params = [], string $method = 'POST', s ]; return $this->sendRequest($url, $params, $headers, $method); } catch (Exception $e) { - throw new Exception($e->getMessage(), (int)$e->getCode(), $e); + throw new Exception($e->getMessage(), (int) $e->getCode(), $e); } } diff --git a/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapter.php b/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapter.php index c232880b..03d06b37 100644 --- a/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapter.php +++ b/src/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapter.php @@ -69,7 +69,7 @@ public function removeDirectory(string $dirname): bool public function get(string $filename) { try { - return (string)$this->googleDriveApp->getFileInfo($filename, true); + return (string) $this->googleDriveApp->getFileInfo($filename, true); } catch (Exception $e) { return false; } @@ -171,7 +171,7 @@ public function exists(string $filename): bool public function size(string $filename) { try { - $meta = (array)$this->googleDriveApp->getFileInfo($filename); + $meta = (array) $this->googleDriveApp->getFileInfo($filename); return $meta['size']; } catch (Exception $e) { return false; @@ -184,7 +184,7 @@ public function size(string $filename) public function lastModified(string $filename) { try { - $meta = (array)$this->googleDriveApp->getFileInfo($filename); + $meta = (array) $this->googleDriveApp->getFileInfo($filename); return empty($meta['modifiedTime']) ? false : strtotime($meta['modifiedTime']); } catch (Exception $e) { return false; @@ -212,7 +212,7 @@ public function remove(string $filename): bool public function isFile(string $filename): bool { try { - $meta = (array)$this->googleDriveApp->getFileInfo($filename); + $meta = (array) $this->googleDriveApp->getFileInfo($filename); return $meta['kind'] === GoogleDriveApp::DRIVE_FILE_KIND && $meta['mimeType'] != GoogleDriveApp::FOLDER_MIMETYPE; } catch (Exception $e) { @@ -226,7 +226,7 @@ public function isFile(string $filename): bool public function isDirectory(string $dirname): bool { try { - $meta = (array)$this->googleDriveApp->getFileInfo($dirname); + $meta = (array) $this->googleDriveApp->getFileInfo($dirname); return $meta['kind'] === GoogleDriveApp::DRIVE_FILE_KIND && $meta['mimeType'] === GoogleDriveApp::FOLDER_MIMETYPE; } catch (Exception $e) { @@ -244,7 +244,7 @@ public function listDirectory(string $dirname) 'q' => "'$dirname' in parents and trashed = false", 'fields' => '*', ]; - $response = (array)$this->googleDriveApp->rpcRequest(GoogleDriveApp::FILE_METADATA_URL . '?' . http_build_query($params), [], 'GET'); + $response = (array) $this->googleDriveApp->rpcRequest(GoogleDriveApp::FILE_METADATA_URL . '?' . http_build_query($params), [], 'GET'); return $response['files']; } catch (Exception $e) { return false; diff --git a/src/Libraries/Storage/Adapters/Local/LocalFileSystemAdapter.php b/src/Libraries/Storage/Adapters/Local/LocalFileSystemAdapter.php index f7f791a0..3248a332 100644 --- a/src/Libraries/Storage/Adapters/Local/LocalFileSystemAdapter.php +++ b/src/Libraries/Storage/Adapters/Local/LocalFileSystemAdapter.php @@ -222,7 +222,7 @@ public function getLines(string $filename, int $offset = 0, ?int $length = null) */ public function fileNameWithExtension(string $path): string { - return (string)pathinfo($path, PATHINFO_BASENAME); + return (string) pathinfo($path, PATHINFO_BASENAME); } /** @@ -230,7 +230,7 @@ public function fileNameWithExtension(string $path): string */ public function fileName(string $path): string { - return (string)pathinfo($path, PATHINFO_FILENAME); + return (string) pathinfo($path, PATHINFO_FILENAME); } /** @@ -238,7 +238,7 @@ public function fileName(string $path): string */ public function extension(string $path): string { - return (string)pathinfo($path, PATHINFO_EXTENSION); + return (string) pathinfo($path, PATHINFO_EXTENSION); } /** diff --git a/src/Libraries/Storage/UploadedFile.php b/src/Libraries/Storage/UploadedFile.php index 625832cb..8b642822 100644 --- a/src/Libraries/Storage/UploadedFile.php +++ b/src/Libraries/Storage/UploadedFile.php @@ -389,7 +389,7 @@ public function isImage($filePath): bool protected function moveUploadedFile(string $filePath): bool { if ($this->remoteFileSystem) { - return (bool)$this->remoteFileSystem->put($filePath, $this->localFileSystem->get($this->getPathname())); + return (bool) $this->remoteFileSystem->put($filePath, $this->localFileSystem->get($this->getPathname())); } elseif ($this->isUploaded()) { return move_uploaded_file($this->getPathname(), $filePath); } else { diff --git a/src/Libraries/Validation/Traits/General.php b/src/Libraries/Validation/Traits/General.php index 1c6c2f71..83dabab6 100644 --- a/src/Libraries/Validation/Traits/General.php +++ b/src/Libraries/Validation/Traits/General.php @@ -20,6 +20,7 @@ use Quantum\App\Exceptions\BaseException; use Quantum\Model\Factories\ModelFactory; use Quantum\Di\Exceptions\DiException; +use Quantum\Model\DbModel; use ReflectionException; use DateTime; @@ -211,15 +212,17 @@ protected function same(string $value, string $otherField): bool } /** - * Validates uniqueness + * Validates uniqueness * @param $value * @param string $className * @param string $columnName * @return bool + * @throws BaseException * @throws ModelException */ protected function unique($value, string $className, string $columnName): bool { + /** @var DbModel $model */ $model = ModelFactory::get(ucfirst($className)); $record = $model->findOneBy($columnName, $value); @@ -233,10 +236,12 @@ protected function unique($value, string $className, string $columnName): bool * @param string $className * @param string $columnName * @return bool + * @throws BaseException * @throws ModelException */ protected function exists($value, string $className, string $columnName): bool { + /** @var DbModel $model */ $model = ModelFactory::get(ucfirst($className)); $record = $model->findOneBy($columnName, $value); diff --git a/src/Model/DbModel.php b/src/Model/DbModel.php new file mode 100644 index 00000000..5b7501cc --- /dev/null +++ b/src/Model/DbModel.php @@ -0,0 +1,293 @@ + + * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) + * @link http://quantum.softberg.org/ + * @since 3.0.0 + */ + +namespace Quantum\Model; + +use Quantum\Libraries\Database\Contracts\DbalInterface; +use Quantum\Paginator\Exceptions\PaginatorException; +use Quantum\Paginator\Factories\PaginatorFactory; +use Quantum\Model\Exceptions\ModelException; +use Quantum\App\Exceptions\BaseException; +use Quantum\Paginator\Paginator; + +/** + * Class DbModel + * @package Quantum\Model + * + * @method string getTable() + * @method string getModelName() + * @method self select(...$columns) + * @method self criteria(string $column, string $operator, $value = null) + * @method self criterias(...$criterias) + * @method self having(string $column, string $operator, string $value = null) + * @method self orderBy(string $column, string $direction) + * @method self offset(int $offset) + * @method self limit(int $limit) + * @method int count() + * @method bool deleteMany() + * @method self joinTo(DbModel $model, bool $switch = true) + * @method self isNull(string $column) + * @method self isNotNull(string $column) + */ +abstract class DbModel extends Model +{ + /** + * Database table + * @var string + */ + public string $table = ''; + + /** + * Primary key column + * @var string + */ + public string $idColumn = 'id'; + + /** + * ORM instance (Idiorm or SleekDB) + * @var DbalInterface|null + */ + protected ?DbalInterface $ormInstance = null; + + /** + * Set ORM instance + * @param DbalInterface $ormInstance + * @return void + */ + public function setOrmInstance(DbalInterface $ormInstance): void + { + $this->ormInstance = $ormInstance; + } + + /** + * Get ORM instance + * @return DbalInterface + * @throws ModelException + */ + public function getOrmInstance(): DbalInterface + { + if (!isset($this->ormInstance)) { + throw ModelException::ormIsNotSet(); + } + + return $this->ormInstance; + } + + /** + * @return array + */ + public function relations(): array + { + return []; + } + + /** + * Finds the record by primary key and returns a new model instance + * @param int $id + * @return DbModel|null + * @throws BaseException + */ + public function findOne(int $id): ?DbModel + { + $orm = $this->getOrmInstance()->findOne($id); + + return wrapToModel($orm, static::class); + } + + /** + * Finds the record by given column and value and returns a new model instance + * @param string $column + * @param mixed $value + * @return DbModel|null + * @throws BaseException + */ + public function findOneBy(string $column, $value): ?DbModel + { + $orm = $this->getOrmInstance()->findOneBy($column, $value); + + return wrapToModel($orm, static::class); + } + + /** + * Gets the first record and returns a new model instance + * @return DbModel|null + * @throws BaseException + */ + public function first(): ?DbModel + { + $orm = $this->getOrmInstance()->first(); + + return wrapToModel($orm, static::class); + } + + /** + * Fetch multiple results + * @return ModelCollection + * @throws BaseException + */ + public function get(): ModelCollection + { + $models = array_map( + fn ($item) => wrapToModel($item, static::class), + $this->getOrmInstance()->get() + ); + + return new ModelCollection($models); + } + + /** + * Paginates the result + * @param int $perPage + * @param int $currentPage + * @return Paginator + * @throws BaseException + * @throws PaginatorException + */ + public function paginate(int $perPage, int $currentPage = 1): Paginator + { + return PaginatorFactory::create(Paginator::MODEL, [ + 'model' => $this, + 'perPage' => $perPage, + 'page' => $currentPage, + ]); + } + + /** + * Creates a new record + * @return $this + * @throws ModelException + */ + public function create(): self + { + $this->attributes = []; + $this->getOrmInstance()->create(); + return $this; + } + + /** + * Save model + * @return bool + * @throws ModelException + */ + public function save(): bool + { + $this->syncAttributesToOrm(); + + $result = $this->getOrmInstance()->save(); + + $this->syncPrimaryKeyFromOrm(); + + return $result; + } + + /** + * Delete model + * @return bool + * @throws ModelException + */ + public function delete(): bool + { + return $this->getOrmInstance()->delete(); + } + + /** + * @param array $data + * @return $this + */ + public function hydrateFromOrm(array $data): self + { + $this->attributes = $data; + return $this; + } + + /** + * @param string $method + * @param array $args + * @return mixed + * @throws ModelException + */ + public function __call(string $method, array $args = []) + { + $orm = $this->getOrmInstance(); + + if (!method_exists($orm, $method)) { + throw ModelException::methodNotSupported( + $method, + get_class($orm) + ); + } + + $result = $orm->{$method}(...$args); + + return $result instanceof DbalInterface ? $this : $result; + } + + /** + * @return string[] + */ + public function __sleep() + { + return [ + 'table', + 'idColumn', + 'hidden', + 'attributes', + ]; + } + + /** + * Sync model attributes into ORM + * @return void + * @throws ModelException + */ + protected function syncAttributesToOrm(): void + { + $orm = $this->getOrmInstance(); + + foreach ($this->attributes as $key => $value) { + if ($key === $this->idColumn) { + continue; + } + + $orm->prop($key, $value); + } + } + + /** + * @param string $key + * @return bool + */ + protected function shouldFill(string $key): bool + { + if ($key === $this->idColumn) { + return false; + } + + return parent::shouldFill($key); + } + + /** + * Syncs primary key from ORM to model attributes + * @return void + * @throws ModelException + */ + private function syncPrimaryKeyFromOrm(): void + { + $id = $this->getOrmInstance()->prop($this->idColumn); + + if ($id !== null) { + $this->attributes[$this->idColumn] = $id; + } + } +} diff --git a/src/Model/Enums/ExceptionMessages.php b/src/Model/Enums/ExceptionMessages.php index 2d4f24af..56a9bc6f 100644 --- a/src/Model/Enums/ExceptionMessages.php +++ b/src/Model/Enums/ExceptionMessages.php @@ -33,4 +33,6 @@ final class ExceptionMessages extends BaseExceptionMessages public const MISSING_FOREIGN_KEY = 'Foreign key `{%1}` is missing in model `{%2}`'; public const UNSUPPORTED_RELATION = 'Relation type `{%1}` is not supported'; + + public const ORM_IS_NOT_SET = 'ORM instance not initialized'; } diff --git a/src/Model/Exceptions/ModelException.php b/src/Model/Exceptions/ModelException.php index efc4ea77..6626c049 100644 --- a/src/Model/Exceptions/ModelException.php +++ b/src/Model/Exceptions/ModelException.php @@ -100,4 +100,15 @@ public static function unsupportedRelationType(string $relationType): self E_ERROR ); } + + /** + * @return ModelException + */ + public static function ormIsNotSet(): self + { + return new self( + ExceptionMessages::ORM_IS_NOT_SET, + E_ERROR + ); + } } diff --git a/src/Model/Factories/ModelFactory.php b/src/Model/Factories/ModelFactory.php index 7b6c3f5c..0d8cd15e 100644 --- a/src/Model/Factories/ModelFactory.php +++ b/src/Model/Factories/ModelFactory.php @@ -16,9 +16,9 @@ use Quantum\Libraries\Database\Contracts\DbalInterface; use Quantum\Model\Exceptions\ModelException; -use Quantum\App\Exceptions\BaseException; use Quantum\Libraries\Database\Database; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; +use Quantum\Model\Model; /** * Class ModelFactory @@ -29,11 +29,10 @@ class ModelFactory /** * Gets the Model * @param string $modelClass - * @return QtModel + * @return Model * @throws ModelException - * @throws BaseException */ - public static function get(string $modelClass): QtModel + public static function get(string $modelClass): Model { if (!class_exists($modelClass)) { throw ModelException::notFound('Model', $modelClass); @@ -41,19 +40,21 @@ public static function get(string $modelClass): QtModel $model = new $modelClass(); - if (!$model instanceof QtModel) { - throw ModelException::notInstanceOf($modelClass, QtModel::class); + if (!$model instanceof Model) { + throw ModelException::notInstanceOf($modelClass, Model::class); } - $ormInstance = self::createOrmInstance( - $model->table, - $modelClass, - $model->idColumn, - $model->relations(), - $model->hidden - ); + if ($model instanceof DbModel) { + $ormInstance = self::createOrmInstance( + $model->table, + $modelClass, + $model->idColumn, + $model->relations(), + $model->hidden ?? [] + ); - $model->setOrmInstance($ormInstance); + $model->setOrmInstance($ormInstance); + } return $model; } @@ -65,7 +66,7 @@ public static function get(string $modelClass): QtModel * @param string $idColumn * @param array $foreignKeys * @param array $hidden - * @return QtModel + * @return DbModel */ public static function createDynamicModel( string $table, @@ -73,10 +74,16 @@ public static function createDynamicModel( string $idColumn = 'id', array $foreignKeys = [], array $hidden = [] - ): QtModel { - $model = new class () extends QtModel {}; + ): DbModel { + $model = new class () extends DbModel {}; - $ormInstance = self::createOrmInstance($table, $modelName, $idColumn, $foreignKeys, $hidden); + $ormInstance = self::createOrmInstance( + $table, + $modelName, + $idColumn, + $foreignKeys, + $hidden + ); $model->setOrmInstance($ormInstance); @@ -100,6 +107,12 @@ protected static function createOrmInstance( ): DbalInterface { $ormClass = Database::getInstance()->getOrmClass(); - return new $ormClass($table, $modelName, $idColumn, $foreignKeys, $hidden); + return new $ormClass( + $table, + $modelName, + $idColumn, + $foreignKeys, + $hidden + ); } } diff --git a/src/Model/Helpers/model.php b/src/Model/Helpers/model.php index 3b6cc978..9395afdc 100644 --- a/src/Model/Helpers/model.php +++ b/src/Model/Helpers/model.php @@ -14,18 +14,18 @@ use Quantum\Libraries\Database\Contracts\DbalInterface; use Quantum\Model\Exceptions\ModelException; -use Quantum\App\Exceptions\BaseException; use Quantum\Model\Factories\ModelFactory; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; +use Quantum\Model\Model; /** * Gets the model instance - * @param string $modelClass - * @return QtModel + * @template T of Model + * @param class-string $modelClass + * @return T * @throws ModelException - * @throws BaseException */ -function model(string $modelClass): QtModel +function model(string $modelClass): Model { return ModelFactory::get($modelClass); } @@ -37,7 +37,7 @@ function model(string $modelClass): QtModel * @param string $idColumn * @param array $foreignKeys * @param array $hidden - * @return QtModel + * @return DbModel */ function dynamicModel( string $table, @@ -45,30 +45,41 @@ function dynamicModel( string $idColumn = 'id', array $foreignKeys = [], array $hidden = [] -): QtModel { - return ModelFactory::createDynamicModel($table, $modelName, $idColumn, $foreignKeys, $hidden); +): DbModel { + return ModelFactory::createDynamicModel( + $table, + $modelName, + $idColumn, + $foreignKeys, + $hidden + ); } /** * Wraps the orm instance into model - * @param DbalInterface $ormInstance + * @param DbalInterface|null $ormInstance * @param string $modelClass - * @return QtModel - * @throws BaseException + * @return DbModel|null + * @throws ModelException */ -function wrapToModel(DbalInterface $ormInstance, string $modelClass): QtModel +function wrapToModel(?DbalInterface $ormInstance, string $modelClass): ?DbModel { + if ($ormInstance === null) { + return null; + } + if (!class_exists($modelClass)) { throw ModelException::notFound('Model class', $modelClass); } $model = new $modelClass(); - if (!$model instanceof QtModel) { - throw ModelException::notInstanceOf($modelClass, QtModel::class); + if (!$model instanceof DbModel) { + throw ModelException::notInstanceOf($modelClass, DbModel::class); } $model->setOrmInstance($ormInstance); + $model->hydrateFromOrm($ormInstance->asArray()); return $model; } diff --git a/src/Model/Model.php b/src/Model/Model.php new file mode 100644 index 00000000..13087bd7 --- /dev/null +++ b/src/Model/Model.php @@ -0,0 +1,148 @@ + + * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) + * @link http://quantum.softberg.org/ + * @since 3.0.0 + */ + +namespace Quantum\Model; + +use Quantum\Model\Exceptions\ModelException; + +/** + * Class Model + * @package Quantum\Model + */ +abstract class Model +{ + /** + * Internal attributes + * @var array + */ + protected array $attributes = []; + + /** + * Models fillable properties + * @var array + */ + protected array $fillable = []; + + /** + * Models hidden properties + * Used by DBAL and plain models + * @var array + */ + public array $hidden = []; + + /** + * @param string $key + * @param $value + * @return $this|mixed|null + */ + public function prop(string $key, $value = null) + { + if (func_num_args() === 1) { + return $this->attributes[$key] ?? null; + } + + $this->attributes[$key] = $value; + return $this; + } + + /** + * Fill object properties + * @param array $props + * @return $this + * @throws ModelException + */ + public function fill(array $props): self + { + foreach ($props as $key => $value) { + if (!$this->shouldFill($key)) { + throw ModelException::inappropriateProperty($key); + } + + $this->attributes[$key] = $value; + } + + return $this; + } + + /** + * Converts to array + * @return array + */ + public function asArray(): array + { + if (!$this->hidden) { + return $this->attributes; + } + + return array_diff_key( + $this->attributes, + array_flip($this->hidden) + ); + } + + /** + * Checks if model is empty + * @return bool + */ + public function isEmpty(): bool + { + return empty($this->asArray()); + } + + /** + * @param string $key + * @return $this|mixed|null + */ + public function __get(string $key) + { + return $this->prop($key); + } + + /** + * @param string $key + * @param $value + * @return void + */ + public function __set(string $key, $value): void + { + $this->prop($key, $value); + } + + /** + * @param string $key + * @return bool + */ + public function __isset(string $key): bool + { + return isset($this->attributes[$key]); + } + + /** + * @param string $key + * @return void + */ + public function __unset(string $key): void + { + unset($this->attributes[$key]); + } + + /** + * @param string $key + * @return bool + */ + protected function shouldFill(string $key): bool + { + return in_array($key, $this->fillable, true); + } +} diff --git a/src/Model/ModelCollection.php b/src/Model/ModelCollection.php index 8dadca40..153926b0 100644 --- a/src/Model/ModelCollection.php +++ b/src/Model/ModelCollection.php @@ -27,19 +27,19 @@ class ModelCollection implements Countable, IteratorAggregate { /** - * @var QtModel[] + * @var Model[] */ - private $models = []; + private array $models = []; /** * @var iterable */ - private $originalModels; + private iterable $originalModels; /** * @var bool */ - private $modelsProcessed = false; + private bool $modelsProcessed = false; /** * @param iterable $models @@ -56,11 +56,11 @@ public function __construct(iterable $models = []) /** * Add a model to the collection - * @param QtModel $model + * @param Model $model * @return self * @throws BaseException */ - public function add(QtModel $model): self + public function add(Model $model): self { $this->processModels(); @@ -77,11 +77,11 @@ public function add(QtModel $model): self /** * Remove a model from the collection - * @param QtModel $model + * @param Model $model * @return self * @throws BaseException */ - public function remove(QtModel $model): self + public function remove(Model $model): self { $this->processModels(); @@ -94,7 +94,7 @@ public function remove(QtModel $model): self /** * Get all models as an array - * @return QtModel[] + * @return Model[] * @throws BaseException */ public function all(): array @@ -116,10 +116,10 @@ public function count(): int /** * Get the first model in the collection - * @return QtModel|null + * @return Model|null * @throws BaseException */ - public function first(): ?QtModel + public function first(): ?Model { foreach ($this->getIterator() as $model) { return $model; @@ -130,10 +130,10 @@ public function first(): ?QtModel /** * Get the last model in the collection - * @return QtModel|null + * @return Model|null * @throws BaseException */ - public function last(): ?QtModel + public function last(): ?Model { $this->processModels(); return empty($this->models) ? null : end($this->models); @@ -142,10 +142,11 @@ public function last(): ?QtModel /** * Check if the collection is empty * @return bool + * @throws BaseException */ public function isEmpty(): bool { - return !$this->first() instanceof \Quantum\Model\QtModel; + return !$this->first() instanceof Model; } /** @@ -188,15 +189,15 @@ private function processModels() } /** - * Validate that an item is a QtModel instance + * Validate that an item is a Model instance * @param $model * @return void * @throws BaseException */ private function validateModel($model): void { - if (!$model instanceof QtModel) { - throw ModelException::notInstanceOf(get_class($model), QtModel::class); + if (!$model instanceof Model) { + throw ModelException::notInstanceOf(get_class($model), Model::class); } } } diff --git a/src/Model/QtModel.php b/src/Model/QtModel.php deleted file mode 100644 index 86d13016..00000000 --- a/src/Model/QtModel.php +++ /dev/null @@ -1,236 +0,0 @@ - - * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) - * @link http://quantum.softberg.org/ - * @since 3.0.0 - */ - -namespace Quantum\Model; - -use Quantum\Libraries\Database\Contracts\DbalInterface; -use Quantum\Paginator\Exceptions\PaginatorException; -use Quantum\Paginator\Factories\PaginatorFactory; -use Quantum\Model\Exceptions\ModelException; -use Quantum\App\Exceptions\BaseException; -use Quantum\Paginator\Paginator; - -/** - * Class QtModel - * @package Quantum\Model - * @method string getTable() - * @method string getModelName() - * @method static select(...$columns) - * @method static findOne(int $id) - * @method static findOneBy(string $column, $value) - * @method static first() - * @method static criteria(string $column, string $operator, $value = null) - * @method static criterias(...$criterias) - * @method static having(string $column, string $operator, string $value = null) - * @method static orderBy(string $column, string $direction) - * @method static offset(int $offset) - * @method static limit(int $limit) - * @method int count() - * @method array asArray() - * @method static create() - * @method bool save() - * @method bool delete() - * @method bool deleteMany() - * @method static joinTo(QtModel $model, bool $switch = true) - * @method static isNull(string $column) - * @method static isNotNull(string $column) - */ -abstract class QtModel -{ - /** - * The database table associated with model - * @var string - */ - public $table; - - /** - * Id column of table - * @var string - */ - public $idColumn = 'id'; - - /** - * Foreign keys - * @var array - */ - public $foreignKeys = []; - - /** - * Models fillable properties - * @var array - */ - protected $fillable = []; - - /** - * Models hidden properties - * @var array - */ - public $hidden = []; - - /** - * ORM database abstract layer object - * @var DbalInterface - */ - protected $ormInstance; - - /** - * Sets the ORM instance - * @param DbalInterface $ormInstance - */ - public function setOrmInstance(DbalInterface $ormInstance) - { - $this->ormInstance = $ormInstance; - } - - /** - * Gets ORM instance of current model - * @return DbalInterface - */ - public function getOrmInstance(): DbalInterface - { - return $this->ormInstance; - } - - /** - * Returns the model's foreign key relations. - * @return array - */ - public function relations(): array - { - return []; - } - - /** - * @return ModelCollection - * @throws BaseException - */ - public function get(): ModelCollection - { - $models = array_map(fn ($item) => wrapToModel($item, static::class), $this->ormInstance->get()); - - return new ModelCollection($models); - } - - /** - * @param int $perPage - * @param int $currentPage - * @return Paginator - * @throws BaseException - * @throws PaginatorException - */ - public function paginate(int $perPage, int $currentPage = 1): Paginator - { - return PaginatorFactory::create(Paginator::MODEL, [ - 'model' => $this, - 'perPage' => $perPage, - 'page' => $currentPage, - ]); - } - - /** - * Fills the object properties - * @param array $props - * @return QtModel - * @throws ModelException - */ - public function fillObjectProps(array $props): QtModel - { - foreach ($props as $key => $value) { - if ($key == $this->idColumn) { - continue; - } - - if (!in_array($key, $this->fillable)) { - throw ModelException::inappropriateProperty($key); - } - - $this->prop($key, $value); - } - - return $this; - } - - /** - * @return bool - */ - public function isEmpty(): bool - { - return empty($this->asArray()); - } - - /** - * Sets or gets the model property - * @param string $property - * @param mixed|null $value - * @return mixed - */ - public function prop(string $property, $value = null) - { - return $this->ormInstance->prop(...func_get_args()); - } - - /** - * Gets the model property with magic - * @param string $property - * @return mixed - */ - public function __get(string $property) - { - return $this->prop($property); - } - - /** - * Sets a value to the model property with magic - * @param string $property - * @param mixed $value - */ - public function __set(string $property, $value) - { - $this->prop($property, $value); - } - - /** - * @param string $method - * @param $args - * @return $this - * @throws BaseException - */ - public function __call(string $method, $args = null) - { - if (!method_exists($this->ormInstance, $method)) { - throw ModelException::methodNotSupported($method, get_class($this->ormInstance)); - } - - $result = $this->ormInstance->{$method}(...$args); - - if (!$result instanceof DbalInterface) { - return $result; - } - - return $this; - } - - /** - * Keeps only relevant props at serialization - * @return string[] - */ - public function __sleep() - { - return [ - 'table', - 'idColumn', - 'hidden', - ]; - } -} diff --git a/src/Model/Traits/SoftDeletes.php b/src/Model/Traits/SoftDeletes.php index fede27b7..3342d3e7 100644 --- a/src/Model/Traits/SoftDeletes.php +++ b/src/Model/Traits/SoftDeletes.php @@ -15,9 +15,11 @@ namespace Quantum\Model\Traits; use Quantum\Paginator\Exceptions\PaginatorException; +use Quantum\Model\Exceptions\ModelException; use Quantum\App\Exceptions\BaseException; use Quantum\Model\ModelCollection; use Quantum\Paginator\Paginator; +use Quantum\Model\DbModel; /** * Trait SoftDeletes @@ -28,11 +30,12 @@ trait SoftDeletes /** * @var bool */ - protected $includeTrashed = false; + protected bool $includeTrashed = false; /** * Soft delete the model by setting the deleted_at timestamp. * @return bool + * @throws ModelException */ public function delete(): bool { @@ -44,6 +47,7 @@ public function delete(): bool /** * Restore a soft deleted model. * @return bool + * @throws ModelException */ public function restore(): bool { @@ -54,6 +58,7 @@ public function restore(): bool /** * Force delete the model from the database. * @return bool + * @throws ModelException */ public function forceDelete(): bool { @@ -74,12 +79,13 @@ public function withTrashed(): self /** * Return only soft deleted records. * @return static + * @throws ModelException */ public function onlyTrashed(): self { $this->includeTrashed = true; - $this->ormInstance->isNotNull($this->getDeleteAtColumn()); + $this->getOrmInstance()->isNotNull($this->getDeleteAtColumn()); return $this; } @@ -87,6 +93,7 @@ public function onlyTrashed(): self /** * Get all non-deleted records unless withTrashed is called. * @return ModelCollection + * @throws BaseException */ public function get(): ModelCollection { @@ -113,6 +120,7 @@ public function paginate(int $perPage, int $currentPage = 1): Paginator /** * Count all non-deleted records unless withTrashed() is called. * @return int + * @throws ModelException */ public function count(): int { @@ -124,52 +132,50 @@ public function count(): int /** * Find one record by its ID, excluding soft deleted unless withTrashed() is called. * @param int $id - * @return static + * @return DbModel|null + * @throws BaseException */ - public function findOne(int $id): self + public function findOne(int $id): ?DbModel { $this->applySoftDeleteScope(); - parent::findOne($id); - - return $this; + return parent::findOne($id); } /** * Find one record by column and value, excluding soft deleted unless withTrashed() is called. * @param string $column * @param $value - * @return static + * @return DbModel|null + * @throws BaseException */ - public function findOneBy(string $column, $value): self + public function findOneBy(string $column, $value): ?DbModel { $this->applySoftDeleteScope(); - parent::findOneBy($column, $value); - - return $this; + return parent::findOneBy($column, $value); } /** * Get the first record, excluding soft deleted unless withTrashed() is called. - * @return static + * @return DbModel|null + * @throws BaseException */ - public function first(): self + public function first(): ?DbModel { $this->applySoftDeleteScope(); - parent::first(); - - return $this; + return parent::first(); } /** * Apply soft delete scope to the current query if not including trashed. + * @throws ModelException */ protected function applySoftDeleteScope(): void { if (!$this->includeTrashed) { - $this->ormInstance->isNull($this->getDeleteAtColumn()); + $this->getOrmInstance()->isNull($this->getDeleteAtColumn()); } } diff --git a/src/Module/Templates/DemoApi/src/Models/Comment.php.tpl b/src/Module/Templates/DemoApi/src/Models/Comment.php.tpl index f1fedad3..1027c383 100644 --- a/src/Module/Templates/DemoApi/src/Models/Comment.php.tpl +++ b/src/Module/Templates/DemoApi/src/Models/Comment.php.tpl @@ -9,20 +9,20 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Models; use Quantum\Libraries\Database\Enums\Relation; use Quantum\Model\Traits\SoftDeletes; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class Comment * @package Modules\{{MODULE_NAME}} */ -class Comment extends QtModel +class Comment extends DbModel { use SoftDeletes; @@ -31,19 +31,19 @@ class Comment extends QtModel * ID column of table * @var string */ - public $idColumn = 'id'; + public string $idColumn = 'id'; /** * The table name * @var string */ - public $table = 'comments'; + public string $table = 'comments'; /** * Fillable properties * @var array */ - public $fillable = [ + public array $fillable = [ 'uuid', 'post_uuid', 'user_uuid', diff --git a/src/Module/Templates/DemoApi/src/Models/Post.php.tpl b/src/Module/Templates/DemoApi/src/Models/Post.php.tpl index 1dc72926..fe0537fa 100644 --- a/src/Module/Templates/DemoApi/src/Models/Post.php.tpl +++ b/src/Module/Templates/DemoApi/src/Models/Post.php.tpl @@ -9,20 +9,20 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Models; use Quantum\Libraries\Database\Enums\Relation; use Quantum\Model\Traits\SoftDeletes; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class Post * @package Modules\{{MODULE_NAME}} */ -class Post extends QtModel +class Post extends DbModel { use SoftDeletes; @@ -31,19 +31,19 @@ class Post extends QtModel * ID column of table * @var string */ - public $idColumn = 'id'; + public string $idColumn = 'id'; /** * The table name * @var string */ - public $table = 'posts'; + public string $table = 'posts'; /** * Fillable properties * @var array */ - public $fillable = [ + public array $fillable = [ 'uuid', 'user_uuid', 'title', diff --git a/src/Module/Templates/DemoApi/src/Models/User.php.tpl b/src/Module/Templates/DemoApi/src/Models/User.php.tpl index c796eb17..b4331053 100644 --- a/src/Module/Templates/DemoApi/src/Models/User.php.tpl +++ b/src/Module/Templates/DemoApi/src/Models/User.php.tpl @@ -9,37 +9,37 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Models; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class User * @package Modules\{{MODULE_NAME}} */ -class User extends QtModel +class User extends DbModel { /** * ID column of table * @var string */ - public $idColumn = 'id'; + public string $idColumn = 'id'; /** * The table name * @var string */ - public $table = 'users'; + public string $table = 'users'; /** * Fillable properties * @var array */ - public $fillable = [ + public array $fillable = [ 'uuid', 'firstname', 'lastname', diff --git a/src/Module/Templates/DemoApi/src/Services/AuthService.php.tpl b/src/Module/Templates/DemoApi/src/Services/AuthService.php.tpl index eb1881d3..4af8dd04 100644 --- a/src/Module/Templates/DemoApi/src/Services/AuthService.php.tpl +++ b/src/Module/Templates/DemoApi/src/Services/AuthService.php.tpl @@ -9,7 +9,7 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Services; @@ -23,8 +23,6 @@ use Quantum\Di\Exceptions\DiException; use Quantum\Model\ModelCollection; use Quantum\Service\QtService; use {{MODULE_NAMESPACE}}\Models\User; -use Quantum\Model\QtModel; -use ReflectionException; /** * Class AuthService @@ -34,12 +32,11 @@ class AuthService extends QtService implements AuthServiceInterface { /** - * @var QtModel + * @var User */ - private $model; + private User $model; /** - * @throws BaseException * @throws ModelException */ public function __construct() @@ -50,6 +47,7 @@ class AuthService extends QtService implements AuthServiceInterface /** * Get users * @return ModelCollection + * @throws BaseException */ public function getAll(): ModelCollection { @@ -60,6 +58,7 @@ class AuthService extends QtService implements AuthServiceInterface * Get user * @param string $uuid * @return User + * @throws BaseException */ public function getUserByUuid(string $uuid): User { @@ -71,6 +70,7 @@ class AuthService extends QtService implements AuthServiceInterface * @param string $field * @param $value * @return AuthUser|null + * @throws BaseException */ public function get(string $field, $value): ?AuthUser { @@ -100,7 +100,7 @@ class AuthService extends QtService implements AuthServiceInterface $this->createUserDirectory($data['uuid']); $user = $this->model->create(); - $user->fillObjectProps($data); + $user->fill($data); $user->save(); return (new AuthUser())->setData($data); @@ -112,6 +112,8 @@ class AuthService extends QtService implements AuthServiceInterface * @param string|null $value * @param array $data * @return AuthUser|null + * @throws BaseException + * @throws ModelException */ public function update(string $field, ?string $value, array $data): ?AuthUser { @@ -123,7 +125,7 @@ class AuthService extends QtService implements AuthServiceInterface $data['updated_at'] = date('Y-m-d H:i:s'); - $user->fillObjectProps($data); + $user->fill($data); $user->save(); return (new AuthUser())->setData($this->model->findOneBy($field, $value)->asArray()); diff --git a/src/Module/Templates/DemoApi/src/Services/CommentService.php.tpl b/src/Module/Templates/DemoApi/src/Services/CommentService.php.tpl index 0d1f4ee1..c93291d7 100644 --- a/src/Module/Templates/DemoApi/src/Services/CommentService.php.tpl +++ b/src/Module/Templates/DemoApi/src/Services/CommentService.php.tpl @@ -9,13 +9,14 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Services; use {{MODULE_NAMESPACE}}\Transformers\CommentTransformer; -use Quantum\App\Exceptions\BaseException;use Quantum\Model\Exceptions\ModelException; +use Quantum\Model\Exceptions\ModelException; +use Quantum\App\Exceptions\BaseException; use Quantum\Service\QtService; use {{MODULE_NAMESPACE}}\Models\Comment; use {{MODULE_NAMESPACE}}\Models\User; @@ -30,17 +31,16 @@ class CommentService extends QtService /** * @var Comment */ - private $model; + private Comment $model; /** * @var CommentTransformer */ - private $transformer; + private CommentTransformer $transformer; /** * @param CommentTransformer $transformer * @throws ModelException - * @throws BaseException */ public function __construct(CommentTransformer $transformer) { @@ -96,7 +96,7 @@ class CommentService extends QtService $data['created_at'] = date('Y-m-d H:i:s'); $comment = $this->model->create(); - $comment->fillObjectProps($data); + $comment->fill($data); $comment->save(); return $data; diff --git a/src/Module/Templates/DemoApi/src/Services/PostService.php.tpl b/src/Module/Templates/DemoApi/src/Services/PostService.php.tpl index 4ffb9f32..b9a67c0f 100644 --- a/src/Module/Templates/DemoApi/src/Services/PostService.php.tpl +++ b/src/Module/Templates/DemoApi/src/Services/PostService.php.tpl @@ -9,7 +9,7 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Services; @@ -28,8 +28,7 @@ use Quantum\Di\Exceptions\DiException; use Quantum\Model\ModelCollection; use Gumlet\ImageResizeException; use Quantum\Service\QtService; -use Quantum\Model\QtModel; -use ReflectionException; +use Quantum\Model\DbModel; /** * Class PostService @@ -39,18 +38,17 @@ class PostService extends QtService { /** - * @var QtModel + * @var Post */ - private $model; + private Post $model; /** * @var PostTransformer */ - private $transformer; + private PostTransformer $transformer; /** * @param PostTransformer $transformer - * @throws BaseException * @throws ModelException */ public function __construct(PostTransformer $transformer) @@ -163,7 +161,7 @@ class PostService extends QtService $data['created_at'] = date('Y-m-d H:i:s'); $post = $this->model->create(); - $post->fillObjectProps($data); + $post->fill($data); $post->save(); return $this->getPost($post->uuid); @@ -182,7 +180,7 @@ class PostService extends QtService $data['updated_at'] = date('Y-m-d H:i:s'); $post = $this->model->findOneBy('uuid', $uuid); - $post->fillObjectProps($data); + $post->fill($data); $post->save(); return $this->getPost($post->uuid); @@ -192,7 +190,6 @@ class PostService extends QtService * Deletes post * @param string $uuid * @return bool - * @throws ModelException */ public function deletePost(string $uuid): bool { @@ -203,7 +200,7 @@ class PostService extends QtService * Delete posts table * @throws ModelException */ - public function deleteAllPost() + public function deleteAllPosts() { $this->model->truncate(); } diff --git a/src/Module/Templates/DemoWeb/src/Models/Comment.php.tpl b/src/Module/Templates/DemoWeb/src/Models/Comment.php.tpl index c35d1bcb..746ff366 100644 --- a/src/Module/Templates/DemoWeb/src/Models/Comment.php.tpl +++ b/src/Module/Templates/DemoWeb/src/Models/Comment.php.tpl @@ -9,20 +9,20 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Models; use Quantum\Libraries\Database\Enums\Relation; use Quantum\Model\Traits\SoftDeletes; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class Comment * @package Modules\{{MODULE_NAME}} */ -class Comment extends QtModel +class Comment extends DbModel { use SoftDeletes; @@ -31,19 +31,19 @@ class Comment extends QtModel * ID column of table * @var string */ - public $idColumn = 'id'; + public string $idColumn = 'id'; /** * The table name * @var string */ - public $table = 'comments'; + public string $table = 'comments'; /** * Fillable properties * @var array */ - public $fillable = [ + public array $fillable = [ 'uuid', 'post_uuid', 'user_uuid', diff --git a/src/Module/Templates/DemoWeb/src/Models/Post.php.tpl b/src/Module/Templates/DemoWeb/src/Models/Post.php.tpl index 99720d99..7754aa7a 100644 --- a/src/Module/Templates/DemoWeb/src/Models/Post.php.tpl +++ b/src/Module/Templates/DemoWeb/src/Models/Post.php.tpl @@ -9,20 +9,20 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Models; use Quantum\Libraries\Database\Enums\Relation; use Quantum\Model\Traits\SoftDeletes; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class Post * @package Modules\{{MODULE_NAME}} */ -class Post extends QtModel +class Post extends DbModel { use SoftDeletes; @@ -31,19 +31,19 @@ class Post extends QtModel * ID column of table * @var string */ - public $idColumn = 'id'; + public string $idColumn = 'id'; /** * The table name * @var string */ - public $table = 'posts'; + public string $table = 'posts'; /** * Fillable properties * @var array */ - public $fillable = [ + public array $fillable = [ 'uuid', 'user_uuid', 'title', diff --git a/src/Module/Templates/DemoWeb/src/Models/User.php.tpl b/src/Module/Templates/DemoWeb/src/Models/User.php.tpl index c796eb17..b4331053 100644 --- a/src/Module/Templates/DemoWeb/src/Models/User.php.tpl +++ b/src/Module/Templates/DemoWeb/src/Models/User.php.tpl @@ -9,37 +9,37 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Models; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class User * @package Modules\{{MODULE_NAME}} */ -class User extends QtModel +class User extends DbModel { /** * ID column of table * @var string */ - public $idColumn = 'id'; + public string $idColumn = 'id'; /** * The table name * @var string */ - public $table = 'users'; + public string $table = 'users'; /** * Fillable properties * @var array */ - public $fillable = [ + public array $fillable = [ 'uuid', 'firstname', 'lastname', diff --git a/src/Module/Templates/DemoWeb/src/Services/AuthService.php.tpl b/src/Module/Templates/DemoWeb/src/Services/AuthService.php.tpl index eb1881d3..4af8dd04 100644 --- a/src/Module/Templates/DemoWeb/src/Services/AuthService.php.tpl +++ b/src/Module/Templates/DemoWeb/src/Services/AuthService.php.tpl @@ -9,7 +9,7 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Services; @@ -23,8 +23,6 @@ use Quantum\Di\Exceptions\DiException; use Quantum\Model\ModelCollection; use Quantum\Service\QtService; use {{MODULE_NAMESPACE}}\Models\User; -use Quantum\Model\QtModel; -use ReflectionException; /** * Class AuthService @@ -34,12 +32,11 @@ class AuthService extends QtService implements AuthServiceInterface { /** - * @var QtModel + * @var User */ - private $model; + private User $model; /** - * @throws BaseException * @throws ModelException */ public function __construct() @@ -50,6 +47,7 @@ class AuthService extends QtService implements AuthServiceInterface /** * Get users * @return ModelCollection + * @throws BaseException */ public function getAll(): ModelCollection { @@ -60,6 +58,7 @@ class AuthService extends QtService implements AuthServiceInterface * Get user * @param string $uuid * @return User + * @throws BaseException */ public function getUserByUuid(string $uuid): User { @@ -71,6 +70,7 @@ class AuthService extends QtService implements AuthServiceInterface * @param string $field * @param $value * @return AuthUser|null + * @throws BaseException */ public function get(string $field, $value): ?AuthUser { @@ -100,7 +100,7 @@ class AuthService extends QtService implements AuthServiceInterface $this->createUserDirectory($data['uuid']); $user = $this->model->create(); - $user->fillObjectProps($data); + $user->fill($data); $user->save(); return (new AuthUser())->setData($data); @@ -112,6 +112,8 @@ class AuthService extends QtService implements AuthServiceInterface * @param string|null $value * @param array $data * @return AuthUser|null + * @throws BaseException + * @throws ModelException */ public function update(string $field, ?string $value, array $data): ?AuthUser { @@ -123,7 +125,7 @@ class AuthService extends QtService implements AuthServiceInterface $data['updated_at'] = date('Y-m-d H:i:s'); - $user->fillObjectProps($data); + $user->fill($data); $user->save(); return (new AuthUser())->setData($this->model->findOneBy($field, $value)->asArray()); diff --git a/src/Module/Templates/DemoWeb/src/Services/CommentService.php.tpl b/src/Module/Templates/DemoWeb/src/Services/CommentService.php.tpl index 83e66250..c93291d7 100644 --- a/src/Module/Templates/DemoWeb/src/Services/CommentService.php.tpl +++ b/src/Module/Templates/DemoWeb/src/Services/CommentService.php.tpl @@ -9,7 +9,7 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Services; @@ -31,17 +31,16 @@ class CommentService extends QtService /** * @var Comment */ - private $model; + private Comment $model; /** * @var CommentTransformer */ - private $transformer; + private CommentTransformer $transformer; /** * @param CommentTransformer $transformer * @throws ModelException - * @throws BaseException */ public function __construct(CommentTransformer $transformer) { @@ -97,7 +96,7 @@ class CommentService extends QtService $data['created_at'] = date('Y-m-d H:i:s'); $comment = $this->model->create(); - $comment->fillObjectProps($data); + $comment->fill($data); $comment->save(); return $data; diff --git a/src/Module/Templates/DemoWeb/src/Services/PostService.php.tpl b/src/Module/Templates/DemoWeb/src/Services/PostService.php.tpl index a91b7081..efb2a65c 100644 --- a/src/Module/Templates/DemoWeb/src/Services/PostService.php.tpl +++ b/src/Module/Templates/DemoWeb/src/Services/PostService.php.tpl @@ -9,7 +9,7 @@ * @author Arman Ag. * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) * @link http://quantum.softberg.org/ - * @since 2.9.9 + * @since 3.0.0 */ namespace {{MODULE_NAMESPACE}}\Services; @@ -22,16 +22,12 @@ use {{MODULE_NAMESPACE}}\Transformers\PostTransformer; use Quantum\Model\Exceptions\ModelException; use Quantum\Libraries\Storage\UploadedFile; use Quantum\App\Exceptions\BaseException; -use Quantum\Model\Factories\ModelFactory; use {{MODULE_NAMESPACE}}\Models\User; use {{MODULE_NAMESPACE}}\Models\Post; use Quantum\Di\Exceptions\DiException; use Quantum\Model\ModelCollection; use Gumlet\ImageResizeException; -use Quantum\Paginator\Paginator; use Quantum\Service\QtService; -use Quantum\Model\QtModel; -use ReflectionException; /** * Class PostService @@ -41,18 +37,17 @@ class PostService extends QtService { /** - * @var QtModel + * @var Post */ - private $model; + private Post $model; /** * @var PostTransformer */ - private $transformer; + private PostTransformer $transformer; /** * @param PostTransformer $transformer - * @throws BaseException * @throws ModelException */ public function __construct(PostTransformer $transformer) @@ -164,7 +159,7 @@ class PostService extends QtService $data['created_at'] = date('Y-m-d H:i:s'); $post = $this->model->create(); - $post->fillObjectProps($data); + $post->fill($data); $post->save(); return $this->getPost($post->uuid); @@ -183,7 +178,7 @@ class PostService extends QtService $data['updated_at'] = date('Y-m-d H:i:s'); $post = $this->model->findOneBy('uuid', $uuid); - $post->fillObjectProps($data); + $post->fill($data); $post->save(); return $this->getPost($post->uuid); @@ -193,7 +188,6 @@ class PostService extends QtService * Deletes post * @param string $uuid * @return bool - * @throws ModelException */ public function deletePost(string $uuid): bool { diff --git a/src/Paginator/Adapters/ModelPaginator.php b/src/Paginator/Adapters/ModelPaginator.php index 226b269d..d22af110 100644 --- a/src/Paginator/Adapters/ModelPaginator.php +++ b/src/Paginator/Adapters/ModelPaginator.php @@ -16,8 +16,9 @@ use Quantum\Paginator\Contracts\PaginatorInterface; use Quantum\Paginator\Traits\PaginatorTrait; +use Quantum\App\Exceptions\BaseException; use Quantum\Model\ModelCollection; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * Class ModelPaginator @@ -30,19 +31,19 @@ class ModelPaginator implements PaginatorInterface /** * @var string */ - private $modelClass; + private string $modelClass; /** - * @var QtModel + * @var DbModel */ - private $model; + private DbModel $model; /** - * @param QtModel $model + * @param DbModel $model * @param int $perPage * @param int $page */ - public function __construct(QtModel $model, int $perPage, int $page = 1) + public function __construct(DbModel $model, int $perPage, int $page = 1) { $this->initialize($perPage, $page); @@ -53,6 +54,7 @@ public function __construct(QtModel $model, int $perPage, int $page = 1) /** * @inheritDoc + * @throws BaseException */ public function data(): ModelCollection { @@ -70,6 +72,7 @@ public function data(): ModelCollection /** * @inheritDoc + * @throws BaseException */ public function firstItem() { @@ -84,6 +87,7 @@ public function firstItem() /** * @inheritDoc + * @throws BaseException */ public function lastItem() { diff --git a/src/Paginator/Traits/PaginatorTrait.php b/src/Paginator/Traits/PaginatorTrait.php index eae6ffa7..3c2e1234 100644 --- a/src/Paginator/Traits/PaginatorTrait.php +++ b/src/Paginator/Traits/PaginatorTrait.php @@ -25,22 +25,22 @@ trait PaginatorTrait /** * @var string */ - protected $baseUrl; + protected string $baseUrl; /** * @var int */ - protected $total; + protected int $total; /** * @var int */ - protected $perPage; + protected int $perPage; /** * @var int */ - protected $page; + protected int $page; /** * @param int $perPage @@ -111,7 +111,7 @@ public function nextPageNumber(): ?int */ public function lastPageNumber(): int { - return (int)ceil($this->total() / $this->perPage); + return (int) ceil($this->total() / $this->perPage); } /** diff --git a/tests/Unit/Console/Commands/CronRunCommandTest.php b/tests/Unit/Console/Commands/CronRunCommandTest.php index 9adf5854..965bc661 100644 --- a/tests/Unit/Console/Commands/CronRunCommandTest.php +++ b/tests/Unit/Console/Commands/CronRunCommandTest.php @@ -267,7 +267,7 @@ public function testCommandHandlesUnexpectedError() private function createTaskFile(string $filename, array $definition): void { - $body = $definition['body'] ?? "echo 'Test task executed';"; + $body = $definition['body'] ?? 'return true;'; $content = " '{$definition['name']}',\n"; diff --git a/tests/Unit/Environment/Helpers/EnvHelperTest.php b/tests/Unit/Environment/Helpers/EnvHelperTest.php index 0f037b62..c933aa85 100644 --- a/tests/Unit/Environment/Helpers/EnvHelperTest.php +++ b/tests/Unit/Environment/Helpers/EnvHelperTest.php @@ -8,10 +8,10 @@ class EnvHelperTest extends AppTestCase { public function testGetEnvValue() { - $this->assertNull(env('NEW_ENV_KEY')); + $this->assertNotNull(env('APP_KEY')); - putenv('NEW_ENV_KEY=New value'); + $this->assertNotNull(env('DEBUG')); - $this->assertEquals('New value', env('NEW_ENV_KEY')); + $this->assertEquals('TRUE', env('DEBUG')); } } diff --git a/tests/Unit/Libraries/Captcha/Adapters/HcaptchaAdapterTest.php b/tests/Unit/Libraries/Captcha/Adapters/HcaptchaAdapterTest.php index ebe77abf..fbe08a9e 100644 --- a/tests/Unit/Libraries/Captcha/Adapters/HcaptchaAdapterTest.php +++ b/tests/Unit/Libraries/Captcha/Adapters/HcaptchaAdapterTest.php @@ -117,7 +117,7 @@ public function testHcaptchaVerifySuccess() $this->httpClientMock ->shouldReceive('getResponseBody') - ->andReturn((object)[ + ->andReturn((object) [ 'success' => true, ]); @@ -143,7 +143,7 @@ public function testHcaptchaVerifyFailure() $this->httpClientMock ->shouldReceive('getResponseBody') - ->andReturn((object)[ + ->andReturn((object) [ 'success' => false, 'error-codes' => ['invalid-input-response'], ]); diff --git a/tests/Unit/Libraries/Captcha/Adapters/RecaptchaAdapterTest.php b/tests/Unit/Libraries/Captcha/Adapters/RecaptchaAdapterTest.php index a7255f5e..fbf579a8 100644 --- a/tests/Unit/Libraries/Captcha/Adapters/RecaptchaAdapterTest.php +++ b/tests/Unit/Libraries/Captcha/Adapters/RecaptchaAdapterTest.php @@ -118,7 +118,7 @@ public function testRecaptchaVerifySuccess() $this->httpClientMock ->shouldReceive('getResponseBody') - ->andReturn((object)[ + ->andReturn((object) [ 'success' => true, ]); @@ -144,7 +144,7 @@ public function testRecaptchaVerifyFailure() $this->httpClientMock ->shouldReceive('getResponseBody') - ->andReturn((object)[ + ->andReturn((object) [ 'success' => false, 'error-codes' => ['invalid-input-response'], ]); diff --git a/tests/Unit/Libraries/Cron/CronLockTest.php b/tests/Unit/Libraries/Cron/CronLockTest.php index e577e4fb..75358e19 100644 --- a/tests/Unit/Libraries/Cron/CronLockTest.php +++ b/tests/Unit/Libraries/Cron/CronLockTest.php @@ -118,12 +118,12 @@ public function testRefreshUpdatesTimestamp() $lock = new CronLock('refresh-task', $this->lockDirectory); $lock->acquire(); - $lockFile = $this->lockDirectory . DS . 'refresh-task.lock'; - $initial = (int) file_get_contents($lockFile); + $initial = $lock->getTimestamp(); - sleep(1); + sleep(2); $this->assertTrue($lock->refresh()); - $updated = (int) file_get_contents($lockFile); + + $updated = $lock->getTimestamp(); $this->assertGreaterThan($initial, $updated); @@ -197,26 +197,6 @@ public function testConfigurableLockDirectoryIsUsed() $this->cleanupDirectory($customDirectory); } - public function testThrowsExceptionWhenDirectoryNotWritable() - { - if (function_exists('posix_getuid') && posix_getuid() === 0) { - $this->markTestSkipped('Skipping non-writable directory test as root.'); - } - - $this->expectException(CronException::class); - $this->expectExceptionMessage('not writable'); - - $readOnlyDir = $this->lockDirectory . DS . 'readonly'; - mkdir($this->lockDirectory, 0777, true); - mkdir($readOnlyDir, 0444); - - try { - new CronLock('test-task', $readOnlyDir); - } finally { - chmod($readOnlyDir, 0755); - } - } - public function testCronLockRefresh() { $lock = new CronLock('refresh-task', $this->lockDirectory); diff --git a/tests/Unit/Libraries/Database/Adapters/DatabaseSeeder.php b/tests/Unit/Libraries/Database/Adapters/DatabaseSeeder.php index 8f0fdd21..85e4837a 100644 --- a/tests/Unit/Libraries/Database/Adapters/DatabaseSeeder.php +++ b/tests/Unit/Libraries/Database/Adapters/DatabaseSeeder.php @@ -51,7 +51,7 @@ private function seedUsers(): void foreach (TestData::users() as $userData) { $this->userModel->create(); - $this->userModel->fillObjectProps($userData); + $this->userModel->fill($userData); $this->userModel->save(); } } @@ -60,7 +60,7 @@ private function seedProfiles(): void { foreach (TestData::profiles() as $profileData) { $this->profileModel->create(); - $this->profileModel->fillObjectProps($profileData); + $this->profileModel->fill($profileData); $this->profileModel->save(); } } @@ -69,7 +69,7 @@ private function seedUserProfessions(): void { foreach (TestData::userProfessions() as $professionData) { $this->userProfessionModel->create(); - $this->userProfessionModel->fillObjectProps($professionData); + $this->userProfessionModel->fill($professionData); $this->userProfessionModel->save(); } } @@ -78,7 +78,7 @@ private function seedEvents(): void { foreach (TestData::events() as $eventData) { $this->eventModel->create(); - $this->eventModel->fillObjectProps($eventData); + $this->eventModel->fill($eventData); $this->eventModel->save(); } } @@ -87,7 +87,7 @@ private function seedUserEvents(): void { foreach (TestData::userEvents() as $userEventData) { $this->userEventModel->create(); - $this->userEventModel->fillObjectProps($userEventData); + $this->userEventModel->fill($userEventData); $this->userEventModel->save(); } } @@ -96,7 +96,7 @@ private function seedUserMeetings(): void { foreach (TestData::userMeetings() as $meetingData) { $this->userMeetingModel->create(); - $this->userMeetingModel->fillObjectProps($meetingData); + $this->userMeetingModel->fill($meetingData); $this->userMeetingModel->save(); } } @@ -105,7 +105,7 @@ private function seedTickets(): void { foreach (TestData::tickets() as $ticketData) { $this->ticketModel->create(); - $this->ticketModel->fillObjectProps($ticketData); + $this->ticketModel->fill($ticketData); $this->ticketModel->save(); } } @@ -114,7 +114,7 @@ private function seedNotes(): void { foreach (TestData::notes() as $noteData) { $this->noteModel->create(); - $this->noteModel->fillObjectProps($noteData); + $this->noteModel->fill($noteData); $this->noteModel->save(); } } diff --git a/tests/Unit/Libraries/Database/Adapters/Idiorm/Statements/JoinIdiormTest.php b/tests/Unit/Libraries/Database/Adapters/Idiorm/Statements/JoinIdiormTest.php index 4cbbb6de..56648592 100644 --- a/tests/Unit/Libraries/Database/Adapters/Idiorm/Statements/JoinIdiormTest.php +++ b/tests/Unit/Libraries/Database/Adapters/Idiorm/Statements/JoinIdiormTest.php @@ -15,11 +15,11 @@ use Quantum\Model\Exceptions\ModelException; use Quantum\Model\Factories\ModelFactory; use Quantum\Model\ModelCollection; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class BrokenProfileMissingTypeModel extends QtModel +class BrokenProfileMissingTypeModel extends DbModel { - public $table = 'profiles'; + public string $table = 'profiles'; public function relations(): array { @@ -33,9 +33,9 @@ public function relations(): array } } -class BrokenProfileUnsupportedRelationModel extends QtModel +class BrokenProfileUnsupportedRelationModel extends DbModel { - public $table = 'profiles'; + public string $table = 'profiles'; public function relations(): array { diff --git a/tests/Unit/Libraries/Database/Adapters/Sleekdb/Statements/JoinSleekTest.php b/tests/Unit/Libraries/Database/Adapters/Sleekdb/Statements/JoinSleekTest.php index ca831079..c697f2ae 100644 --- a/tests/Unit/Libraries/Database/Adapters/Sleekdb/Statements/JoinSleekTest.php +++ b/tests/Unit/Libraries/Database/Adapters/Sleekdb/Statements/JoinSleekTest.php @@ -14,11 +14,11 @@ use Quantum\Model\Exceptions\ModelException; use Quantum\Model\Factories\ModelFactory; use Quantum\Model\ModelCollection; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class BrokenProfileMissingTypeModel extends QtModel +class BrokenProfileMissingTypeModel extends DbModel { - public $table = 'profiles'; + public string $table = 'profiles'; public function relations(): array { @@ -32,9 +32,9 @@ public function relations(): array } } -class BrokenProfileUnsupportedRelationModel extends QtModel +class BrokenProfileUnsupportedRelationModel extends DbModel { - public $table = 'profiles'; + public string $table = 'profiles'; public function relations(): array { diff --git a/tests/Unit/Libraries/HttpClient/HttpClientTest.php b/tests/Unit/Libraries/HttpClient/HttpClientTest.php index ae66acee..a799fd62 100644 --- a/tests/Unit/Libraries/HttpClient/HttpClientTest.php +++ b/tests/Unit/Libraries/HttpClient/HttpClientTest.php @@ -127,7 +127,7 @@ public function testHttpClientPostRequestWithData() $curl->shouldReceive('getId')->andReturn(0); $curl->shouldReceive('getResponseHeaders')->andReturn(new CaseInsensitiveArray()); $curl->shouldReceive('getResponseCookies')->andReturn([]); - $curl->shouldReceive('getResponse')->andReturn((object)['status' => 'ok']); + $curl->shouldReceive('getResponse')->andReturn((object) ['status' => 'ok']); $this->httpClient ->createRequest('https://example.com', $curl) diff --git a/tests/Unit/Libraries/JWToken/JWTokenTest.php b/tests/Unit/Libraries/JWToken/JWTokenTest.php index ec86cf16..5bd35f4a 100644 --- a/tests/Unit/Libraries/JWToken/JWTokenTest.php +++ b/tests/Unit/Libraries/JWToken/JWTokenTest.php @@ -131,6 +131,6 @@ public function testSetClaims() $this->assertIsObject($jwtToken->fetchPayload()); - $this->assertEquals($claims, (array)$jwtToken->fetchPayload()); + $this->assertEquals($claims, (array) $jwtToken->fetchPayload()); } } diff --git a/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxAppTest.php b/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxAppTest.php index e00727ee..3d5c91e5 100644 --- a/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxAppTest.php +++ b/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxAppTest.php @@ -107,7 +107,7 @@ public function testDropboxGetAuthUrl() public function testDropboxFetchTokens() { - $this->currentResponse = (object)$this->tokensGrantResponse; + $this->currentResponse = (object) $this->tokensGrantResponse; $response = $this->dropboxApp->fetchTokens($this->authCode, $this->redirectUrl); @@ -120,7 +120,7 @@ public function testDropboxFetchTokens() public function testDropboxRpcRequest() { - $this->currentResponse = (object)$this->profileDataResponse; + $this->currentResponse = (object) $this->profileDataResponse; $response = $this->dropboxApp->rpcRequest('/users/get_account'); @@ -144,26 +144,26 @@ public function testDropboxContentRequest() public function testDropboxSendRequest() { - $this->currentResponse = (object)$this->profileDataResponse; + $this->currentResponse = (object) $this->profileDataResponse; $response = $this->dropboxApp->sendRequest('https://api.dropboxapi.com/2/users/get_account'); $this->assertIsObject($response); - $this->assertEquals((object)$this->profileDataResponse, $response); + $this->assertEquals((object) $this->profileDataResponse, $response); } public function testDropboxRequestWithAccessTokenExpired() { $this->currentErrors = ['code' => 401]; - $this->currentResponse = (object)$this->errorResponse; + $this->currentResponse = (object) $this->errorResponse; $response = $this->dropboxApp->sendRequest('https://api.dropboxapi.com/2/users/get_account2'); $this->assertIsObject($response); - $this->assertEquals((object)$this->profileDataResponse, $response); + $this->assertEquals((object) $this->profileDataResponse, $response); } public function testDropboxPathNormalizer() diff --git a/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxTokenServiceTestCase.php b/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxTokenServiceTestCase.php index 6352dfd9..74bffb0c 100644 --- a/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxTokenServiceTestCase.php +++ b/tests/Unit/Libraries/Storage/Adapters/Dropbox/DropboxTokenServiceTestCase.php @@ -14,7 +14,7 @@ protected function mockTokenService() $tokenServiceMock ->shouldReceive('getRefreshToken') ->andReturnUsing(function () { - $this->currentResponse = (object)$this->tokensGrantResponse; + $this->currentResponse = (object) $this->tokensGrantResponse; return 'ref_tok_1234'; }); @@ -25,7 +25,7 @@ protected function mockTokenService() $tokenServiceMock ->shouldReceive('saveTokens') ->andReturnUsing(function ($tokens) { - $this->currentResponse = (object)$this->profileDataResponse; + $this->currentResponse = (object) $this->profileDataResponse; return true; }); diff --git a/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveAppTest.php b/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveAppTest.php index d9622007..33939383 100644 --- a/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveAppTest.php +++ b/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveAppTest.php @@ -91,7 +91,7 @@ public function testGoogleDriveGetAuthUrl() public function testGoogleDriveFetchTokens() { - $this->currentResponse = (object)$this->tokensGrantResponse; + $this->currentResponse = (object) $this->tokensGrantResponse; $response = $this->googleDriveApp->fetchTokens($this->authCode, $this->redirectUrl); @@ -104,7 +104,7 @@ public function testGoogleDriveFetchTokens() public function testGoogleDriveRpcRequest() { - $this->currentResponse = (object)$this->fileMetadataResponse; + $this->currentResponse = (object) $this->fileMetadataResponse; $response = $this->googleDriveApp->rpcRequest(GoogleDriveApp::FILE_METADATA_URL . '/' . $this->fileMetadataResponse['id']); @@ -134,13 +134,13 @@ public function testGoogleDriveRequestWithAccessTokenExpired() { $this->currentErrors = ['code' => 401]; - $this->currentResponse = (object)$this->errorResponse; + $this->currentResponse = (object) $this->errorResponse; $response = $this->googleDriveApp->sendRequest(GoogleDriveApp::FILE_METADATA_URL . '/' . $this->fileMetadataResponse['id']); $this->assertIsObject($response); - $this->assertEquals((object)$this->fileMetadataResponse, $response); + $this->assertEquals((object) $this->fileMetadataResponse, $response); } } diff --git a/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapterTest.php b/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapterTest.php index b35adfd9..5885c0ac 100644 --- a/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapterTest.php +++ b/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveFileSystemAdapterTest.php @@ -50,9 +50,9 @@ public function setUp(): void return self::$response[array_key_last(self::$response)]; } - self::$response = array_merge(self::$response, (array)$params); + self::$response = array_merge(self::$response, (array) $params); - return (object)self::$response; + return (object) self::$response; }); $this->fs = new GoogleDriveFileSystemAdapter($googleDrive); diff --git a/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveTokenServiceTestCase.php b/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveTokenServiceTestCase.php index 988bd309..63f1b78d 100644 --- a/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveTokenServiceTestCase.php +++ b/tests/Unit/Libraries/Storage/Adapters/GoogleDrive/GoogleDriveTokenServiceTestCase.php @@ -12,14 +12,14 @@ protected function mockTokenService() $tokenServiceMock = Mockery::mock(TokenServiceInterface::class); $tokenServiceMock->shouldReceive('getRefreshToken')->andReturnUsing(function () { - $this->currentResponse = (object)$this->tokensGrantResponse; + $this->currentResponse = (object) $this->tokensGrantResponse; return 'ref_tok_1234'; }); $tokenServiceMock->shouldReceive('getAccessToken')->andReturn('acc_tok_1234'); $tokenServiceMock->shouldReceive('saveTokens')->andReturnUsing(function ($tokens) { - $this->currentResponse = (object)$this->fileMetadataResponse; + $this->currentResponse = (object) $this->fileMetadataResponse; return true; }); diff --git a/tests/Unit/Libraries/Storage/HttpClientTestCase.php b/tests/Unit/Libraries/Storage/HttpClientTestCase.php index 3abd098b..ab3f7ffe 100644 --- a/tests/Unit/Libraries/Storage/HttpClientTestCase.php +++ b/tests/Unit/Libraries/Storage/HttpClientTestCase.php @@ -42,7 +42,7 @@ protected function mockHttpClient() return $httpClientMock; }); - $httpClientMock->shouldReceive('getErrors')->andReturnUsing(fn () => (array)$this->response[$this->url]['errors']); + $httpClientMock->shouldReceive('getErrors')->andReturnUsing(fn () => (array) $this->response[$this->url]['errors']); $httpClientMock->shouldReceive('getResponseBody')->andReturnUsing(fn () => $this->response[$this->url]['body']); diff --git a/tests/Unit/Model/QtModelTest.php b/tests/Unit/Model/DbModelTest.php similarity index 80% rename from tests/Unit/Model/QtModelTest.php rename to tests/Unit/Model/DbModelTest.php index b5364b3d..1d877be5 100644 --- a/tests/Unit/Model/QtModelTest.php +++ b/tests/Unit/Model/DbModelTest.php @@ -9,9 +9,9 @@ use Quantum\Tests\Unit\AppTestCase; use Quantum\Model\ModelCollection; use Quantum\Paginator\Paginator; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class QtModelTest extends AppTestCase +class DbModelTest extends AppTestCase { private $model; @@ -33,12 +33,12 @@ public function tearDown(): void IdiormDbal::execute('DROP TABLE profiles'); } - public function testQtModelInstance() + public function testDbModelInstance() { - $this->assertInstanceOf(QtModel::class, $this->model); + $this->assertInstanceOf(DbModel::class, $this->model); } - public function testQtModelSetAndGetOrmInstance() + public function testDbModelSetAndGetOrmInstance() { $ormInstance = new IdiormDbal('profiles'); @@ -47,14 +47,14 @@ public function testQtModelSetAndGetOrmInstance() $this->assertSame($ormInstance, $this->model->getOrmInstance()); } - public function testQtModelRelationsReturnsArray() + public function testDbModelRelationsReturnsArray() { $relations = $this->model->relations(); $this->assertIsArray($relations); } - public function testQtModelGetReturnsModelCollection() + public function testDbModelGetReturnsModelCollection() { $collection = $this->model->get(); @@ -65,7 +65,7 @@ public function testQtModelGetReturnsModelCollection() $this->assertInstanceOf(TestProfileModel::class, $collection->first()); } - public function testQtModelPaginateReturnsPaginator() + public function testDbModelPaginateReturnsPaginator() { $paginator = $this->model->paginate(1); @@ -80,14 +80,14 @@ public function testQtModelPaginateReturnsPaginator() $this->assertInstanceOf(TestProfileModel::class, $collection->first()); } - public function testQtModelIsEmptyReturnsFalse() + public function testDbModelIsEmptyReturnsFalse() { $record = $this->model->first(); $this->assertFalse($record->isEmpty()); } - public function testQtModelIsEmptyReturnsTrue() + public function testDbModelIsEmptyReturnsTrue() { $this->model->deleteMany(); @@ -96,9 +96,9 @@ public function testQtModelIsEmptyReturnsTrue() $this->assertTrue($record->isEmpty()); } - public function testQtModelFillObjectProps() + public function testDbModelFill() { - $this->model->fillObjectProps([ + $this->model->fill([ 'firstname' => 'Jane', 'lastname' => 'Due', 'age' => 35, @@ -111,16 +111,16 @@ public function testQtModelFillObjectProps() $this->assertEquals(35, $this->model->age); } - public function testQtModelFillObjectPropsWithUndefinedFillable() + public function testDbModelFillWithUndefinedFillable() { $this->expectException(ModelException::class); $this->expectExceptionMessage('Inappropriate property `currency` for fillable object'); - $this->model->fillObjectProps(['currency' => 'Ireland']); + $this->model->fill(['currency' => 'Ireland']); } - public function testQtModelSetterAndGetter() + public function testDbModelSetterAndGetter() { $this->assertNull($this->model->undefinedProperty); @@ -129,7 +129,7 @@ public function testQtModelSetterAndGetter() $this->assertEquals('Something', $this->model->undefinedProperty); } - public function testQtModelCallingUndefinedModelMethod() + public function testDbModelCallingUndefinedModelMethod() { $this->expectException(ModelException::class); @@ -138,7 +138,7 @@ public function testQtModelCallingUndefinedModelMethod() $this->model->undefinedMethod(); } - public function testQtModelCreateNewRecordByCallingOrmMethod() + public function testDbModelCreateNewRecordByCallingOrmMethod() { $userModel = $this->model->create(); @@ -163,7 +163,7 @@ public function testQtModelCreateNewRecordByCallingOrmMethod() $this->assertEquals('Smith', $userData['lastname']); } - public function testQtModelUpdatingExistingRecordByCallingOrmMethod() + public function testDbModelUpdatingExistingRecordByCallingOrmMethod() { $userModel = $this->model->findOne(1); @@ -190,7 +190,22 @@ public function testQtModelUpdatingExistingRecordByCallingOrmMethod() $this->assertEquals(35, $userModel->age); } - public function testQtModelCallingModelWithCriterias() + public function testDbModelPropUnknownColumnThrowsPdoExceptionOnSave() + { + $userModel = $this->model->create(); + + $userModel->firstname = 'Bypass'; + $userModel->lastname = 'Test'; + $userModel->age = 20; + + $userModel->currency = 'USD'; + + $this->expectException(\PDOException::class); + + $userModel->save(); + } + + public function testDbModelCallingModelWithCriterias() { $profileModel = ModelFactory::get(TestProfileModel::class); @@ -209,7 +224,7 @@ public function testQtModelCallingModelWithCriterias() $this->assertEquals('Jane', $userData['firstname']); } - public function testQtModelGetModelProperties() + public function tesDbModelGetModelProperties() { $expected = [ 'id' => '1', diff --git a/tests/Unit/Model/Factories/ModelFactoryTest.php b/tests/Unit/Model/Factories/ModelFactoryTest.php index 659b9af0..5af80ab4 100644 --- a/tests/Unit/Model/Factories/ModelFactoryTest.php +++ b/tests/Unit/Model/Factories/ModelFactoryTest.php @@ -7,7 +7,7 @@ use Quantum\Model\Exceptions\ModelException; use Quantum\Model\Factories\ModelFactory; use Quantum\Tests\Unit\AppTestCase; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; /** * @runTestsInSeparateProcesses @@ -24,7 +24,7 @@ public function testModelFactoryGet() { $userModel = ModelFactory::get(TestUserModel::class); - $this->assertInstanceOf(QtModel::class, $userModel); + $this->assertInstanceOf(DbModel::class, $userModel); $this->assertInstanceOf(TestUserModel::class, $userModel); } @@ -38,11 +38,11 @@ public function testModelFactoryGetNonExistingModel() ModelFactory::get(\NonExistentClass::class); } - public function testModelFactoryModelNotInstanceOfQtModel() + public function testModelFactoryModelNotInstanceOfDbModel() { $this->expectException(ModelException::class); - $this->expectExceptionMessage('The `Mockery\Undefined` is not instance of `Quantum\Model\QtModel`'); + $this->expectExceptionMessage('The `Mockery\Undefined` is not instance of `Quantum\Model\Model`'); ModelFactory::get(\Mockery\Undefined::class); } @@ -51,7 +51,7 @@ public function testModelFactoryCreateDynamicModel() { $dynamicModel = ModelFactory::createDynamicModel('test_table', TestUserModel::class); - $this->assertInstanceOf(QtModel::class, $dynamicModel); + $this->assertInstanceOf(DbModel::class, $dynamicModel); $this->assertStringContainsString('@anonymous', get_class($dynamicModel)); diff --git a/tests/Unit/Model/Helpers/ModelHelperFunctionsTest.php b/tests/Unit/Model/Helpers/ModelHelperFunctionsTest.php index 95e5a704..c297e082 100644 --- a/tests/Unit/Model/Helpers/ModelHelperFunctionsTest.php +++ b/tests/Unit/Model/Helpers/ModelHelperFunctionsTest.php @@ -6,18 +6,18 @@ use Quantum\Tests\_root\shared\Models\TestUserModel; use Quantum\Model\Exceptions\ModelException; use Quantum\Tests\Unit\AppTestCase; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; use Mockery; class ModelHelperFunctionsTest extends AppTestCase { - public function testModelReturnsQtModelInstance() + public function testModelReturnsDbModelInstance() { $model = model(TestUserModel::class); $this->assertInstanceOf(TestUserModel::class, $model); - $this->assertInstanceOf(QtModel::class, $model); + $this->assertInstanceOf(DbModel::class, $model); } public function testModelThrowsOnInvalidClass() @@ -27,11 +27,11 @@ public function testModelThrowsOnInvalidClass() model('NonExistentModelClass'); } - public function testDynamicModelReturnsAnonymousQtModel() + public function testDynamicModelReturnsAnonymousDbModel() { $dynamicModel = dynamicModel('test_table', TestUserModel::class); - $this->assertInstanceOf(QtModel::class, $dynamicModel); + $this->assertInstanceOf(DbModel::class, $dynamicModel); $this->assertStringContainsString('@anonymous', get_class($dynamicModel)); @@ -42,9 +42,11 @@ public function testWrapToModelReturnsModelInstance() { $dbal = Mockery::mock(DbalInterface::class); + $dbal->shouldReceive('asArray')->andReturn([]); + $model = wrapToModel($dbal, TestUserModel::class); - $this->assertInstanceOf(QtModel::class, $model); + $this->assertInstanceOf(DbModel::class, $model); } public function testWrapToModelThrowsOnInvalidClass() @@ -56,7 +58,7 @@ public function testWrapToModelThrowsOnInvalidClass() wrapToModel($dbal, 'NonExistentModelClass'); } - public function testWrapToModelThrowsIfNotQtModel() + public function testWrapToModelThrowsIfNotDbModel() { $dbal = Mockery::mock(DbalInterface::class); diff --git a/tests/Unit/Model/ModelTest.php b/tests/Unit/Model/ModelTest.php new file mode 100644 index 00000000..aefb6a27 --- /dev/null +++ b/tests/Unit/Model/ModelTest.php @@ -0,0 +1,152 @@ +model = new TestPlainModel(); + } + + public function testModelInstance() + { + $this->assertInstanceOf(Model::class, $this->model); + } + + public function testModelPropSetterAndGetter() + { + $this->assertNull($this->model->prop('firstname')); + + $this->model->prop('firstname', 'John'); + + $this->assertEquals('John', $this->model->prop('firstname')); + } + + public function testModelPropReturnsSelfWhenSettingValue() + { + $result = $this->model->prop('lastname', 'Doe'); + + $this->assertSame($this->model, $result); + } + + public function testModelFill() + { + $this->model->fill([ + 'firstname' => 'Jane', + 'lastname' => 'Due', + 'age' => 35, + ]); + + $this->assertEquals('Jane', $this->model->firstname); + $this->assertEquals('Due', $this->model->lastname); + $this->assertEquals(35, $this->model->age); + } + + public function testModelFillWithUndefinedFillable() + { + $this->expectException(ModelException::class); + + $this->expectExceptionMessage('Inappropriate property `country` for fillable object'); + + $this->model->fill([ + 'country' => 'Ireland', + ]); + } + + public function testModelAsArrayReturnsAttributes() + { + $this->model->prop('firstname', 'John'); + $this->model->prop('lastname', 'Doe'); + $this->model->prop('age', 45); + + $data = $this->model->asArray(); + + $this->assertIsArray($data); + + $this->assertEquals('John', $data['firstname']); + $this->assertEquals('Doe', $data['lastname']); + $this->assertEquals(45, $data['age']); + } + + public function testModelAsArrayHidesHiddenFields() + { + $this->model->prop('firstname', 'John'); + $this->model->prop('lastname', 'Doe'); + $this->model->prop('password', 'secret'); + + $this->model->hidden = ['password']; + + $data = $this->model->asArray(); + + $this->assertIsArray($data); + + $this->assertArrayHasKey('firstname', $data); + $this->assertArrayHasKey('lastname', $data); + + $this->assertArrayNotHasKey('password', $data); + } + + public function testModelIsEmptyReturnsTrue() + { + $this->assertTrue($this->model->isEmpty()); + } + + public function testModelIsEmptyReturnsFalse() + { + $this->model->prop('firstname', 'John'); + + $this->assertFalse($this->model->isEmpty()); + } + + public function testModelMagicGetterAndSetter() + { + $this->assertNull($this->model->undefinedProperty); + + $this->model->undefinedProperty = 'Something'; + + $this->assertEquals('Something', $this->model->undefinedProperty); + } + + public function testModelMagicIsset() + { + $this->assertFalse(isset($this->model->firstname)); + + $this->model->firstname = 'John'; + + $this->assertTrue(isset($this->model->firstname)); + } + + public function testModelMagicUnset() + { + $this->model->firstname = 'John'; + + $this->assertTrue(isset($this->model->firstname)); + + unset($this->model->firstname); + + $this->assertFalse(isset($this->model->firstname)); + + $this->assertNull($this->model->firstname); + } +} + +/** + * Concrete model stub for testing Quantum\Model\Model + */ +class TestPlainModel extends Model +{ + protected array $fillable = [ + 'firstname', + 'lastname', + 'age', + ]; +} diff --git a/tests/Unit/Paginator/Adapters/ModelPaginatorTest.php b/tests/Unit/Paginator/Adapters/ModelPaginatorTest.php index 97b69e17..204f0710 100644 --- a/tests/Unit/Paginator/Adapters/ModelPaginatorTest.php +++ b/tests/Unit/Paginator/Adapters/ModelPaginatorTest.php @@ -7,7 +7,7 @@ use Quantum\Paginator\Adapters\ModelPaginator; use Quantum\Model\Factories\ModelFactory; use Quantum\Model\ModelCollection; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; class ModelPaginatorTest extends PaginatorTestCase { @@ -43,7 +43,7 @@ public function testModelPaginatorData() $record = $data->first(); - $this->assertInstanceOf(QtModel::class, $record); + $this->assertInstanceOf(DbModel::class, $record); $this->assertInstanceOf(TestPostModel::class, $record); @@ -68,7 +68,7 @@ public function testModelPaginatorDataWithAnonymousModel() $record = $data->first(); - $this->assertInstanceOf(QtModel::class, $record); + $this->assertInstanceOf(DbModel::class, $record); $this->assertStringContainsString('@anonymous', get_class($record)); diff --git a/tests/Unit/Service/Factories/ServiceFactoryTest.php b/tests/Unit/Service/Factories/ServiceFactoryTest.php index ec359a11..3ef243f6 100644 --- a/tests/Unit/Service/Factories/ServiceFactoryTest.php +++ b/tests/Unit/Service/Factories/ServiceFactoryTest.php @@ -27,9 +27,9 @@ public function hello() namespace Quantum\Models { - use Quantum\Model\QtModel; + use Quantum\Model\DbModel; - class TestModel extends QtModel + class TestModel extends DbModel { } } @@ -41,7 +41,7 @@ class TestModel extends QtModel use Quantum\Tests\Unit\AppTestCase; use Quantum\Services\TestService; use Quantum\Service\QtService; - use Quantum\Model\QtModel; + use Quantum\Model\DbModel; class ServiceFactoryTest extends AppTestCase { @@ -103,7 +103,7 @@ public function testServiceFactoryVerifyConstructorDependencyResolved() { $testService = ServiceFactory::get(TestService::class); - $this->assertInstanceOf(QtModel::class, $testService->model); + $this->assertInstanceOf(DbModel::class, $testService->model); } public function testServiceFactoryServiceMethodCall() diff --git a/tests/Unit/View/RawParamTest.php b/tests/Unit/View/RawParamTest.php index cd2622fa..df5523b6 100644 --- a/tests/Unit/View/RawParamTest.php +++ b/tests/Unit/View/RawParamTest.php @@ -28,7 +28,7 @@ public function testStoresAndReturnsArray() public function testStoresAndReturnsObject() { - $value = (object)['foo' => 'bar']; + $value = (object) ['foo' => 'bar']; $raw = new RawParam($value); $this->assertSame($value, $raw->getValue()); } diff --git a/tests/_root/shared/Models/TestEventModel.php b/tests/_root/shared/Models/TestEventModel.php index 677064c6..57e520ef 100644 --- a/tests/_root/shared/Models/TestEventModel.php +++ b/tests/_root/shared/Models/TestEventModel.php @@ -3,15 +3,15 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Libraries\Database\Enums\Relation; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestEventModel extends QtModel +class TestEventModel extends DbModel { - public $table = 'events'; + public string $table = 'events'; - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $fillable = [ + public array $fillable = [ 'title', 'country', 'started_at', diff --git a/tests/_root/shared/Models/TestNotesModel.php b/tests/_root/shared/Models/TestNotesModel.php index 8d08a0e6..7adb2b05 100644 --- a/tests/_root/shared/Models/TestNotesModel.php +++ b/tests/_root/shared/Models/TestNotesModel.php @@ -2,15 +2,15 @@ namespace Quantum\Tests\_root\shared\Models; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestNotesModel extends QtModel +class TestNotesModel extends DbModel { - public $table = 'notes'; + public string $table = 'notes'; - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $fillable = [ + public array $fillable = [ 'ticket_id', 'note', ]; diff --git a/tests/_root/shared/Models/TestPostModel.php b/tests/_root/shared/Models/TestPostModel.php index 66c07831..11534960 100644 --- a/tests/_root/shared/Models/TestPostModel.php +++ b/tests/_root/shared/Models/TestPostModel.php @@ -2,15 +2,15 @@ namespace Quantum\Tests\_root\shared\Models; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestPostModel extends QtModel +class TestPostModel extends DbModel { - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $table = 'posts'; + public string $table = 'posts'; - public $fillable = [ + public array $fillable = [ 'title', 'content', 'author', diff --git a/tests/_root/shared/Models/TestProductsModel.php b/tests/_root/shared/Models/TestProductsModel.php index a3adee89..05969a95 100644 --- a/tests/_root/shared/Models/TestProductsModel.php +++ b/tests/_root/shared/Models/TestProductsModel.php @@ -3,17 +3,17 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Model\Traits\SoftDeletes; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestProductsModel extends QtModel +class TestProductsModel extends DbModel { use SoftDeletes; - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $table = 'products'; + public string $table = 'products'; - public $fillable = [ + public array $fillable = [ 'title', 'description', 'price', diff --git a/tests/_root/shared/Models/TestProfileModel.php b/tests/_root/shared/Models/TestProfileModel.php index 934d60b1..cee6dfef 100644 --- a/tests/_root/shared/Models/TestProfileModel.php +++ b/tests/_root/shared/Models/TestProfileModel.php @@ -3,15 +3,15 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Libraries\Database\Enums\Relation; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestProfileModel extends QtModel +class TestProfileModel extends DbModel { - public $table = 'profiles'; + public string $table = 'profiles'; - public $idColumn = 'id'; + public string $idColumn = 'id'; - protected $fillable = [ + protected array $fillable = [ 'user_id', 'firstname', 'lastname', diff --git a/tests/_root/shared/Models/TestTicketModel.php b/tests/_root/shared/Models/TestTicketModel.php index 7e07e7d2..60a2131c 100644 --- a/tests/_root/shared/Models/TestTicketModel.php +++ b/tests/_root/shared/Models/TestTicketModel.php @@ -3,15 +3,15 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Libraries\Database\Enums\Relation; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestTicketModel extends QtModel +class TestTicketModel extends DbModel { - public $table = 'tickets'; + public string $table = 'tickets'; - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $fillable = [ + public array $fillable = [ 'meeting_id', 'type', 'number', diff --git a/tests/_root/shared/Models/TestUserEventModel.php b/tests/_root/shared/Models/TestUserEventModel.php index 59d2cedb..833d1a3a 100644 --- a/tests/_root/shared/Models/TestUserEventModel.php +++ b/tests/_root/shared/Models/TestUserEventModel.php @@ -3,15 +3,15 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Libraries\Database\Enums\Relation; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestUserEventModel extends QtModel +class TestUserEventModel extends DbModel { - public $table = 'user_events'; + public string $table = 'user_events'; - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $fillable = [ + public array $fillable = [ 'user_id', 'event_id', 'confirmed', diff --git a/tests/_root/shared/Models/TestUserMeetingModel.php b/tests/_root/shared/Models/TestUserMeetingModel.php index 4c91f9b6..e906431e 100644 --- a/tests/_root/shared/Models/TestUserMeetingModel.php +++ b/tests/_root/shared/Models/TestUserMeetingModel.php @@ -3,15 +3,15 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Libraries\Database\Enums\Relation; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestUserMeetingModel extends QtModel +class TestUserMeetingModel extends DbModel { - public $table = 'user_meetings'; + public string $table = 'user_meetings'; - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $fillable = [ + public array $fillable = [ 'user_id', 'title', 'start_date', diff --git a/tests/_root/shared/Models/TestUserModel.php b/tests/_root/shared/Models/TestUserModel.php index 4987c0a1..2cdfd69e 100644 --- a/tests/_root/shared/Models/TestUserModel.php +++ b/tests/_root/shared/Models/TestUserModel.php @@ -3,20 +3,20 @@ namespace Quantum\Tests\_root\shared\Models; use Quantum\Libraries\Database\Enums\Relation; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestUserModel extends QtModel +class TestUserModel extends DbModel { - public $idColumn = 'id'; + public string $idColumn = 'id'; - public $table = 'users'; + public string $table = 'users'; - public $fillable = [ + public array $fillable = [ 'email', 'password', ]; - public $hidden = [ + public array $hidden = [ 'password', ]; diff --git a/tests/_root/shared/Models/TestUserProfessionModel.php b/tests/_root/shared/Models/TestUserProfessionModel.php index d780a0bb..e0d642dc 100644 --- a/tests/_root/shared/Models/TestUserProfessionModel.php +++ b/tests/_root/shared/Models/TestUserProfessionModel.php @@ -2,15 +2,15 @@ namespace Quantum\Tests\_root\shared\Models; -use Quantum\Model\QtModel; +use Quantum\Model\DbModel; -class TestUserProfessionModel extends QtModel +class TestUserProfessionModel extends DbModel { - public $table = 'user_professions'; + public string $table = 'user_professions'; - public $primaryKey = 'id'; + public string $idColumn = 'id'; - public $fillable = [ + public array $fillable = [ 'user_id', 'title', ]; diff --git a/tests/_root/shared/config/cron.php b/tests/_root/shared/config/cron.php index 7d837613..bd61ce99 100644 --- a/tests/_root/shared/config/cron.php +++ b/tests/_root/shared/config/cron.php @@ -3,5 +3,5 @@ return [ 'path' => env('CRON_PATH'), 'lock_path' => env('CRON_LOCK_PATH'), - 'max_lock_age' => (int)env('CRON_MAX_LOCK_AGE', 86400), + 'max_lock_age' => (int) env('CRON_MAX_LOCK_AGE', 86400), ];