Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions src/Model/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ public static function connectDb(string $dsn, string $username, string $password
{
static::$_db = new \PDO($dsn, $username, $password, $driverOptions);
static::$_db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); // Set Errorhandling to Exception
static::$_identifier_quote_character = null;
static::$_stmt = array();
self::$_tableColumns = array();
static::_setup_identifier_quote_character();
}

Expand Down Expand Up @@ -443,29 +446,29 @@ public function toArray()
*
* @param int|string $id
*
* @return static
* @return static|null
*/
public static function getById(int|string $id): static
public static function getById(int|string $id): ?static
{
return static::fetchOneWhere(static::_quote_identifier(static::$_primary_column_name) . ' = ?', array($id));
}

/**
* Get the first record in the table
*
* @return static
* @return static|null
*/
public static function first(): static
public static function first(): ?static
{
return static::fetchOneWhere('1=1 ORDER BY ' . static::_quote_identifier(static::$_primary_column_name) . ' ASC');
}

/**
* Get the last record in the table
*
* @return static
* @return static|null
*/
public static function last(): static
public static function last(): ?static
{
return static::fetchOneWhere('1=1 ORDER BY ' . static::_quote_identifier(static::$_primary_column_name) . ' DESC');
}
Expand Down Expand Up @@ -539,7 +542,7 @@ public static function __callStatic($name, $arguments)
* @param string|array $match
* @param string $order ASC|DESC
*
* @return object of calling class
* @return static|null object of calling class
*/
public static function fetchOneWhereMatchingSingleField($fieldname, $match, $order)
{
Expand Down Expand Up @@ -626,9 +629,9 @@ protected static function addWherePrefix($SQLfragment)
* @param array $params optional params to be escaped and injected into the SQL query (standrd PDO syntax)
* @param bool $limitOne if true the first match will be returned
*
* @return array|static object[]|object of objects of calling class
* @return array|static|null object[]|object of objects of calling class
*/
public static function fetchWhere($SQLfragment = '', $params = array(), $limitOne = false): array|static
public static function fetchWhere($SQLfragment = '', $params = array(), $limitOne = false): array|static|null
{
$class = get_called_class();
$SQLfragment = self::addWherePrefix($SQLfragment);
Expand All @@ -638,7 +641,11 @@ public static function fetchWhere($SQLfragment = '', $params = array(), $limitOn
);
$st->setFetchMode(\PDO::FETCH_ASSOC);
if ($limitOne) {
$instance = new $class($st->fetch());
$row = $st->fetch();
if ($row === false) {
return null;
}
$instance = new $class($row);
$instance->clearDirtyFields();
return $instance;
}
Expand Down Expand Up @@ -672,9 +679,9 @@ public static function fetchAllWhere($SQLfragment = '', $params = array()): arra
* @param string $SQLfragment conditions, sorting, grouping and limit to apply (to right of WHERE keywords)
* @param array $params optional params to be escaped and injected into the SQL query (standrd PDO syntax)
*
* @return static object of calling class
* @return static|null object of calling class
*/
public static function fetchOneWhere($SQLfragment = '', $params = array()): static
public static function fetchOneWhere($SQLfragment = '', $params = array()): ?static
{
/** @var static $result */
$result = static::fetchWhere($SQLfragment, $params, true);
Expand Down Expand Up @@ -780,8 +787,18 @@ public function insert($autoTimestamp = true, $allowSetPrimaryKey = false)
return false;
}

$query = 'INSERT INTO ' . static::_quote_identifier(static::$_tableName) . ' SET ' . $set['sql'];
$st = static::execute($query, $set['params']);
if ($set['sql'] === '') {
if ($driver === 'sqlite' || $driver === 'sqlite2') {
$query = 'INSERT INTO ' . static::_quote_identifier(static::$_tableName) . ' DEFAULT VALUES';
$st = static::execute($query);
} else {
$query = 'INSERT INTO ' . static::_quote_identifier(static::$_tableName) . ' () VALUES ()';
$st = static::execute($query);
}
} else {
$query = 'INSERT INTO ' . static::_quote_identifier(static::$_tableName) . ' SET ' . $set['sql'];
$st = static::execute($query, $set['params']);
}
if ($st->rowCount() == 1) {
if ($allowSetPrimaryKey !== true) {
$db = static::$_db;
Expand Down Expand Up @@ -809,6 +826,9 @@ public function update($autoTimestamp = true)
}
$this->validate();
$set = $this->setString();
if ($set['sql'] === '') {
return false;
}
$limitClause = static::supportsUpdateLimit() ? ' LIMIT 1' : '';
$query = 'UPDATE ' . static::_quote_identifier(static::$_tableName) . ' SET ' . $set['sql'] . ' WHERE ' . static::_quote_identifier(static::$_primary_column_name) . ' = ?' . $limitClause;
$set['params'][] = $this->{static::$_primary_column_name};
Expand Down
36 changes: 36 additions & 0 deletions tests/Model/CategoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,22 @@ public function testCreateAndGetById(): void

// read category back into a new object
$read_category = App\Model\Category::getById($category->id);
$this->assertNotNull($read_category);
$this->assertEquals($read_category->name, $_name);
$this->assertEquals($read_category->id, $category->id);
$this->assertNotEmpty($category->created_at);
$this->assertNotEmpty($category->updated_at);
}

/**
* @covers ::fetchOneWhere
*/
public function testFetchOneWhereReturnsNullWhenMissing(): void
{
$missing = App\Model\Category::fetchOneWhere('name = ?', ['__missing__' . uniqid('', true)]);
$this->assertNull($missing);
}

/**
* @covers ::save
*/
Expand Down Expand Up @@ -147,6 +157,32 @@ public function testCreateAndModify(): void

}

/**
* @covers ::insert
*/
public function testInsertWithDefaultValuesWhenNoDirtyFields(): void
{
$category = new App\Model\Category();
$category->clearDirtyFields();

$this->assertTrue($category->insert(false));
$this->assertNotEmpty($category->id);
}

/**
* @covers ::update
*/
public function testUpdateWithoutDirtyFieldsReturnsFalse(): void
{
$category = new App\Model\Category(array(
'name' => 'Nonfiction'
));
$category->save();
$category->clearDirtyFields();

$this->assertFalse($category->update(false));
}

/**
* @covers ::__callStatic
* @covers ::fetchAllWhereMatchingSingleField
Expand Down