diff --git a/LICENSE b/LICENSE index f18f60f..a86e8ad 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 WebFiori Framework +Copyright (c) 2020-present WebFiori Framework Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/WebFiori/Database/Attributes/AttributeTableBuilder.php b/WebFiori/Database/Attributes/AttributeTableBuilder.php index b80b5b1..fc8920b 100644 --- a/WebFiori/Database/Attributes/AttributeTableBuilder.php +++ b/WebFiori/Database/Attributes/AttributeTableBuilder.php @@ -13,7 +13,7 @@ public static function build(string $entityClass, string $dbType = 'mysql'): Tab $tableAttr = $reflection->getAttributes(Table::class)[0] ?? null; if (!$tableAttr) { - throw new \RuntimeException("Class $entityClass must have #[Table] attribute"); + throw new InvalidAttributeException("Class $entityClass must have #[Table] attribute"); } $tableConfig = $tableAttr->newInstance(); @@ -25,7 +25,7 @@ public static function build(string $entityClass, string $dbType = 'mysql'): Tab if (!empty($classColumnAttrs)) { foreach ($classColumnAttrs as $columnAttr) { $columnConfig = $columnAttr->newInstance(); - $columnKey = $columnConfig->name ?? throw new \RuntimeException("Column name is required for class-level attributes"); + $columnKey = $columnConfig->name ?? throw new InvalidAttributeException("Column name is required for class-level attributes"); $columns[$columnKey] = self::columnConfigToArray($columnConfig); } diff --git a/WebFiori/Database/Attributes/ForeignKey.php b/WebFiori/Database/Attributes/ForeignKey.php index aaafa40..4a83fbf 100644 --- a/WebFiori/Database/Attributes/ForeignKey.php +++ b/WebFiori/Database/Attributes/ForeignKey.php @@ -2,7 +2,6 @@ namespace WebFiori\Database\Attributes; use Attribute; -use InvalidArgumentException; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] class ForeignKey { @@ -15,7 +14,7 @@ public function __construct( public string $onDelete = 'set null' ) { if ($column !== null && !empty($columns)) { - throw new InvalidArgumentException( + throw new InvalidAttributeException( "ForeignKey: Use either 'column' or 'columns', not both" ); } diff --git a/WebFiori/Database/Attributes/InvalidAttributeException.php b/WebFiori/Database/Attributes/InvalidAttributeException.php new file mode 100644 index 0000000..f93052b --- /dev/null +++ b/WebFiori/Database/Attributes/InvalidAttributeException.php @@ -0,0 +1,8 @@ +isAutoInc()) { + if ($col->isAutoInc() || $col->isNull()) { return ' = null'; } - if ($col->isNull()) { - return ' = null'; - } - - $default = $col->getDefault(); - - if ($default !== null) { - $phpType = $col->getPHPType(); - - if ($phpType === 'string') { - return " = '".addslashes($default)."'"; - } - - if ($phpType === 'int' || $phpType === 'float') { - return " = {$default}"; - } - - if ($phpType === 'bool') { - return $default ? ' = true' : ' = false'; - } - } - - // Required field with no default $phpType = $col->getPHPType(); + $default = $col->getDefault(); - if ($phpType === 'string') { - return " = ''"; - } - - if ($phpType === 'int') { - return ' = 0'; - } - - if ($phpType === 'float') { - return ' = 0.0'; - } + $typeDefaults = [ + 'string' => " = ''", + 'int' => ' = 0', + 'float' => ' = 0.0', + 'bool' => ' = false' + ]; - if ($phpType === 'bool') { - return ' = false'; + if ($default !== null) { + return match ($phpType) { + 'string' => " = '" . addslashes($default) . "'", + 'int', 'float' => " = {$default}", + 'bool' => $default ? ' = true' : ' = false', + default => '' + }; } - return ''; + return $typeDefaults[$phpType] ?? ''; } /** diff --git a/WebFiori/Database/Entity/RecordMapper.php b/WebFiori/Database/Entity/RecordMapper.php index ad61e6a..c435455 100644 --- a/WebFiori/Database/Entity/RecordMapper.php +++ b/WebFiori/Database/Entity/RecordMapper.php @@ -128,11 +128,8 @@ public function map(array $record) { foreach ($this->getSettersMap() as $method => $colsNames) { if (is_callable([$instance, $method])) { foreach ($colsNames as $colName) { - try { - if (isset($record[$colName])) { - $instance->$method($record[$colName]); - } - } catch (\Throwable $ex) { + if (isset($record[$colName])) { + $instance->$method($record[$colName]); } } } diff --git a/WebFiori/Database/Query/InsertBuilder.php b/WebFiori/Database/Query/InsertBuilder.php index 6fb4db6..c18f601 100644 --- a/WebFiori/Database/Query/InsertBuilder.php +++ b/WebFiori/Database/Query/InsertBuilder.php @@ -206,17 +206,16 @@ private function build() { } private function buildColsArr() { $colsArr = []; - $colsStr = ''; - $table = $this->getTable(); + $tableObj = $this->getTable(); foreach ($this->cols as $colKey) { - $colObj = $table->getColByKey($colKey); + $colObj = $tableObj->getColByKey($colKey); if ($colObj === null) { - $table->addColumns([ + $tableObj->addColumns([ $colKey => [] ]); - $colObj = $table->getColByKey($colKey); + $colObj = $tableObj->getColByKey($colKey); } $colObj->setWithTablePrefix(false); $colsArr[] = $colObj->getName(); @@ -266,7 +265,7 @@ private function initValsArr() { $colsAndVals = $this->data; if (isset($colsAndVals['cols']) && isset($colsAndVals['values'])) { - $cols = $colsAndVals['cols']; + $colsArr = $colsAndVals['cols']; $tempVals = $colsAndVals['values']; $temp = []; $topIndex = 0; @@ -275,14 +274,14 @@ private function initValsArr() { $index = 0; $temp[] = []; - foreach ($cols as $colKey) { + foreach ($colsArr as $colKey) { $temp[$topIndex][$colKey] = $valsArr[$index]; $index++; } $topIndex++; } $this->vals = $temp; - $this->cols = $cols; + $this->cols = $colsArr; } else { $this->cols = array_keys($colsAndVals); $this->vals = [$colsAndVals]; diff --git a/WebFiori/Database/Repository/AbstractRepository.php b/WebFiori/Database/Repository/AbstractRepository.php index eb9cbfc..c49cd24 100644 --- a/WebFiori/Database/Repository/AbstractRepository.php +++ b/WebFiori/Database/Repository/AbstractRepository.php @@ -61,7 +61,7 @@ public function deleteAll(): void { public function deleteById(mixed $id = null): void { $id = $id ?? $this->getEntityId(); if ($id === null) { - throw new \InvalidArgumentException('Cannot delete: no ID provided'); + throw new RepositoryException('Cannot delete: no ID provided'); } $this->db->table($this->getTableName()) ->delete() @@ -94,7 +94,7 @@ public function findAll(): array { public function findById(mixed $id = null): ?object { $id = $id ?? $this->getEntityId(); if ($id === null) { - throw new \InvalidArgumentException('Cannot find: no ID provided'); + throw new RepositoryException('Cannot find: no ID provided'); } $result = $this->db->table($this->getTableName()) ->select() @@ -225,7 +225,7 @@ public function paginateByCursor( */ public function save(?object $entity = null): void { if ($entity === null && !property_exists($this, $this->getIdField())) { - throw new \InvalidArgumentException('Cannot save: no entity provided'); + throw new RepositoryException('Cannot save: no entity provided'); } $entity = $entity ?? $this; $data = $this->toArray($entity); diff --git a/WebFiori/Database/Repository/RepositoryException.php b/WebFiori/Database/Repository/RepositoryException.php new file mode 100644 index 0000000..8a5d1d5 --- /dev/null +++ b/WebFiori/Database/Repository/RepositoryException.php @@ -0,0 +1,8 @@ +path)) { - throw new \RuntimeException('Path not set. Call setPath() first.'); + throw new DatabaseException('Path not set. Call setPath() first.'); } if (!is_dir($this->path)) { diff --git a/WebFiori/Database/Schema/SchemaException.php b/WebFiori/Database/Schema/SchemaException.php new file mode 100644 index 0000000..c8740d2 --- /dev/null +++ b/WebFiori/Database/Schema/SchemaException.php @@ -0,0 +1,8 @@ +expectException(InvalidArgumentException::class); + $this->expectException(InvalidAttributeException::class); $this->expectExceptionMessage("ForeignKey: Use either 'column' or 'columns', not both"); new ForeignKey(table: 'users', column: 'id', columns: ['local_id' => 'id']); diff --git a/tests/WebFiori/Tests/Database/Repository/AbstractRepositoryTest.php b/tests/WebFiori/Tests/Database/Repository/AbstractRepositoryTest.php index 91dd92b..e9eeabe 100644 --- a/tests/WebFiori/Tests/Database/Repository/AbstractRepositoryTest.php +++ b/tests/WebFiori/Tests/Database/Repository/AbstractRepositoryTest.php @@ -8,6 +8,7 @@ use WebFiori\Database\ColOption; use WebFiori\Database\DataType; use WebFiori\Database\Repository\AbstractRepository; +use WebFiori\Database\Repository\RepositoryException; class TestEntity { public ?int $id = null; @@ -176,14 +177,14 @@ public function testSaveAllMixed() { } public function testFindByIdWithNullThrowsException() { - $this->expectException(\InvalidArgumentException::class); + $this->expectException(RepositoryException::class); $this->expectExceptionMessage('Cannot find: no ID provided'); self::$repo->findById(null); } public function testDeleteByIdWithNullThrowsException() { - $this->expectException(\InvalidArgumentException::class); + $this->expectException(RepositoryException::class); $this->expectExceptionMessage('Cannot delete: no ID provided'); self::$repo->deleteById(null); @@ -211,7 +212,7 @@ public function testDeleteByIdWithValidId() { } public function testSaveWithNullOnPureRepoThrowsException() { - $this->expectException(\InvalidArgumentException::class); + $this->expectException(RepositoryException::class); $this->expectExceptionMessage('Cannot save: no entity provided'); self::$repo->save(); @@ -234,7 +235,7 @@ public function testReloadWithEntity() { } public function testReloadWithNullOnPureRepoThrowsException() { - $this->expectException(\InvalidArgumentException::class); + $this->expectException(RepositoryException::class); $this->expectExceptionMessage('Cannot find: no ID provided'); self::$repo->reload(); diff --git a/tests/WebFiori/Tests/Database/Schema/DatabaseChangeGeneratorTest.php b/tests/WebFiori/Tests/Database/Schema/DatabaseChangeGeneratorTest.php index 38d2576..a50d9fa 100644 --- a/tests/WebFiori/Tests/Database/Schema/DatabaseChangeGeneratorTest.php +++ b/tests/WebFiori/Tests/Database/Schema/DatabaseChangeGeneratorTest.php @@ -174,7 +174,7 @@ public function testCreateWithoutNamespace() { public function testCreateWithoutPathThrows() { $generator = new DatabaseChangeGenerator(); - $this->expectException(\RuntimeException::class); + $this->expectException(\WebFiori\Database\DatabaseException::class); $this->expectExceptionMessage('Path not set'); $generator->createMigration('CreateUsersTable');