diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 83393500ee81..7d3c61851717 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -26,7 +26,6 @@ parameters: - '#Call to an undefined method CodeIgniter\\Database\\ConnectionInterface::(tableExists|protectIdentifiers|setAliasedTables|escapeIdentifiers|affectedRows|addTableAlias)\(\)#' - '#Call to an undefined method CodeIgniter\\HTTP\\Request::(getPath|getSegments|getMethod|setLocale|getPost)\(\)#' - '#Call to an undefined method CodeIgniter\\Router\\RouteCollectionInterface::(getDefaultNamespace|isFiltered|getFilterForRoute|getRoutesOptions)\(\)#' - - '#Call to an undefined method CodeIgniter\\Validation\\ValidationInterface::loadRuleGroup\(\)#' - '#Call to function is_null\(\) with mysqli_stmt\|resource will always evaluate to false#' - '#Cannot access property [\$a-z_]+ on ((bool\|)?object\|resource)#' - '#Cannot call method [a-zA-Z_]+\(\) on ((bool\|)?object\|resource)#' diff --git a/system/Model.php b/system/Model.php index a31817e11c64..0870ad598b91 100644 --- a/system/Model.php +++ b/system/Model.php @@ -73,12 +73,10 @@ * - allow specifying the return type (array, object, etc) with each call * - ensure validation is run against objects when saving items * - * @package CodeIgniter - * @mixin BaseBuilder + * @mixin BaseBuilder */ class Model { - /** * Pager instance. * Populated after calling $this->paginate() @@ -166,8 +164,6 @@ class Model */ protected $dateFormat = 'datetime'; - //-------------------------------------------------------------------- - /** * The column used for insert timestamps * @@ -268,11 +264,14 @@ class Model protected $validation; /* - * Callbacks. Each array should contain the method - * names (within the model) that should be called - * when those events are triggered. "Update" and "delete" - * methods are passed the same items that are given to - * their respecitve method. + * Callbacks. + * + * Each array should contain the method names (within the model) + * that should be called when those events are triggered. + * + * "Update" and "delete" methods are passed the same items that + * are given to their respective method. + * * "Find" methods receive the ID searched for (if present), and * 'afterFind' additionally receives the results that were found. */ @@ -298,42 +297,49 @@ class Model * @var array */ protected $beforeInsert = []; + /** * Callbacks for afterInsert * * @var array */ protected $afterInsert = []; + /** * Callbacks for beforeUpdate * * @var array */ protected $beforeUpdate = []; + /** * Callbacks for afterUpdate * * @var array */ protected $afterUpdate = []; + /** * Callbacks for beforeFind * * @var array */ protected $beforeFind = []; + /** * Callbacks for afterFind * * @var array */ protected $afterFind = []; + /** * Callbacks for beforeDelete * * @var array */ protected $beforeDelete = []; + /** * Callbacks for afterDelete * @@ -350,38 +356,23 @@ class Model */ protected $tempData = []; - //-------------------------------------------------------------------- - /** * Model constructor. * - * @param ConnectionInterface $db - * @param ValidationInterface $validation + * @param ConnectionInterface|null $db + * @param ValidationInterface|null $validation */ public function __construct(ConnectionInterface &$db = null, ValidationInterface $validation = null) { - if ($db instanceof ConnectionInterface) - { - $this->db = & $db; - } - else - { - $this->db = Database::connect($this->DBGroup); - } + $db = $db ?? Database::connect($this->DBGroup); + $this->db = &$db; $this->tempReturnType = $this->returnType; $this->tempUseSoftDeletes = $this->useSoftDeletes; $this->tempAllowCallbacks = $this->allowCallbacks; - - if (is_null($validation)) - { - $validation = Services::validation(null, false); - } - - $this->validation = $validation; + $this->validation = $validation ?? Services::validation(null, false); } - //-------------------------------------------------------------------- //-------------------------------------------------------------------- // CRUD & FINDERS //-------------------------------------------------------------------- @@ -390,7 +381,7 @@ public function __construct(ConnectionInterface &$db = null, ValidationInterface * Fetches the row of database from $this->table with a primary key * matching $id. * - * @param mixed|array|null $id One primary key or an array of primary keys + * @param array|integer|string|null $id One primary key or an array of primary keys * * @return array|object|null The resulting row of data, or null. */ @@ -412,9 +403,10 @@ public function find($id = null) return $eventData['data']; } } + $builder = $this->builder(); - if ($this->tempUseSoftDeletes === true) + if ($this->tempUseSoftDeletes) { $builder->where($this->table . '.' . $this->deletedField, null); } @@ -422,21 +414,18 @@ public function find($id = null) if (is_array($id)) { $row = $builder->whereIn($this->table . '.' . $this->primaryKey, $id) - ->get(); - $row = $row->getResult($this->tempReturnType); + ->get() + ->getResult($this->tempReturnType); } elseif ($singleton) { $row = $builder->where($this->table . '.' . $this->primaryKey, $id) - ->get(); - - $row = $row->getFirstRow($this->tempReturnType); + ->get() + ->getFirstRow($this->tempReturnType); } else { - $row = $builder->get(); - - $row = $row->getResult($this->tempReturnType); + $row = $builder->get()->getResult($this->tempReturnType); } $eventData = [ @@ -445,6 +434,7 @@ public function find($id = null) 'method' => 'find', 'singleton' => $singleton, ]; + if ($this->tempAllowCallbacks) { $eventData = $this->trigger('afterFind', $eventData); @@ -457,8 +447,6 @@ public function find($id = null) return $eventData['data']; } - //-------------------------------------------------------------------- - /** * Fetches the column of database from $this->table * @@ -474,15 +462,11 @@ public function findColumn(string $columnName) throw DataException::forFindColumnHaveMultipleColumns(); } - $resultSet = $this->select($columnName) - ->asArray() - ->find(); + $resultSet = $this->select($columnName)->asArray()->find(); - return (! empty($resultSet)) ? array_column($resultSet, $columnName) : null; + return $resultSet ? array_column($resultSet, $columnName) : null; } - //-------------------------------------------------------------------- - /** * Works with the current Query Builder instance to return * all results, while optionally limiting them. @@ -503,6 +487,7 @@ public function findAll(int $limit = 0, int $offset = 0) 'offset' => $offset, 'singleton' => false, ]); + if (! empty($eventData['returnData'])) { return $eventData['data']; @@ -511,15 +496,14 @@ public function findAll(int $limit = 0, int $offset = 0) $builder = $this->builder(); - if ($this->tempUseSoftDeletes === true) + if ($this->tempUseSoftDeletes) { $builder->where($this->table . '.' . $this->deletedField, null); } $row = $builder->limit($limit, $offset) - ->get(); - - $row = $row->getResult($this->tempReturnType); + ->get() + ->getResult($this->tempReturnType); $eventData = [ 'data' => $row, @@ -528,6 +512,7 @@ public function findAll(int $limit = 0, int $offset = 0) 'method' => 'findAll', 'singleton' => false, ]; + if ($this->tempAllowCallbacks) { $eventData = $this->trigger('afterFind', $eventData); @@ -540,8 +525,6 @@ public function findAll(int $limit = 0, int $offset = 0) return $eventData['data']; } - //-------------------------------------------------------------------- - /** * Returns the first row of the result set. Will take any previous * Query Builder calls into account when determining the result set. @@ -566,13 +549,13 @@ public function first() $builder = $this->builder(); - if ($this->tempUseSoftDeletes === true) + if ($this->tempUseSoftDeletes) { $builder->where($this->table . '.' . $this->deletedField, null); } else { - if ($this->useSoftDeletes === true && empty($builder->QBGroupBy) && ! empty($this->primaryKey)) + if ($this->useSoftDeletes && empty($builder->QBGroupBy) && $this->primaryKey) { $builder->groupBy($this->table . '.' . $this->primaryKey); } @@ -580,21 +563,17 @@ public function first() // Some databases, like PostgreSQL, need order // information to consistently return correct results. - if (! empty($builder->QBGroupBy) && empty($builder->QBOrderBy) && ! empty($this->primaryKey)) + if ($builder->QBGroupBy && empty($builder->QBOrderBy) && $this->primaryKey) { $builder->orderBy($this->table . '.' . $this->primaryKey, 'asc'); } - $row = $builder->limit(1, 0) - ->get(); - - $row = $row->getFirstRow($this->tempReturnType); - $eventData = [ - 'data' => $row, + 'data' => $builder->limit(1, 0)->get()->getFirstRow($this->tempReturnType), 'method' => 'first', 'singleton' => true, ]; + if ($this->tempAllowCallbacks) { $eventData = $this->trigger('afterFind', $eventData); @@ -607,8 +586,6 @@ public function first() return $eventData['data']; } - //-------------------------------------------------------------------- - /** * Captures the builder's set() method so that we can validate the * data here. This allows it to be used with any of the other @@ -622,9 +599,7 @@ public function first() */ public function set($key, ?string $value = '', bool $escape = null) { - $data = is_array($key) - ? $key - : [$key => $value]; + $data = is_array($key) ? $key : [$key => $value]; $this->tempData['escape'] = $escape; $this->tempData['data'] = array_merge($this->tempData['data'] ?? [], $data); @@ -632,8 +607,6 @@ public function set($key, ?string $value = '', bool $escape = null) return $this; } - //-------------------------------------------------------------------- - /** * A convenience method that will attempt to determine whether the * data should be inserted or updated. Will work with either @@ -736,8 +709,7 @@ public static function classToArray($data, $primaryKey = null, string $dateForma { // Must make protected values accessible. $prop->setAccessible(true); - $propName = $prop->getName(); - $properties[$propName] = $prop->getValue($data); + $properties[$prop->getName()] = $prop->getValue($data); } } @@ -760,7 +732,7 @@ public static function classToArray($data, $primaryKey = null, string $dateForma $converted = $value->getTimestamp(); break; default: - $converted = (string)$value; + $converted = (string) $value; } $properties[$key] = $converted; @@ -771,8 +743,6 @@ public static function classToArray($data, $primaryKey = null, string $dateForma return $properties; } - //-------------------------------------------------------------------- - /** * Returns last insert ID or 0. * @@ -783,8 +753,6 @@ public function getInsertID() return is_numeric($this->insertID) ? (int) $this->insertID : $this->insertID; } - //-------------------------------------------------------------------- - /** * Inserts data into the current table. If an object is provided, * it will attempt to convert it to an array. @@ -835,12 +803,9 @@ public function insert($data = null, bool $returnID = true) } // Validate data before saving. - if ($this->skipValidation === false) + if (! $this->skipValidation && ! $this->cleanRules()->validate($data)) { - if ($this->cleanRules()->validate($data) === false) - { - return false; - } + return false; } // Must be called first so we don't @@ -850,17 +815,18 @@ public function insert($data = null, bool $returnID = true) // Set created_at and updated_at with same time $date = $this->setDate(); - if ($this->useTimestamps && ! empty($this->createdField) && ! array_key_exists($this->createdField, $data)) + if ($this->useTimestamps && $this->createdField && ! array_key_exists($this->createdField, $data)) { $data[$this->createdField] = $date; } - if ($this->useTimestamps && ! empty($this->updatedField) && ! array_key_exists($this->updatedField, $data)) + if ($this->useTimestamps && $this->updatedField && ! array_key_exists($this->updatedField, $data)) { $data[$this->updatedField] = $date; } $eventData = ['data' => $data]; + if ($this->tempAllowCallbacks) { $eventData = $this->trigger('beforeInsert', $eventData); @@ -875,8 +841,8 @@ public function insert($data = null, bool $returnID = true) // Must use the set() method to ensure objects get converted to arrays $result = $this->builder() - ->set($eventData['data'], '', $escape) - ->insert(); + ->set($eventData['data'], '', $escape) + ->insert(); // If insertion succeeded then save the insert ID if ($result->resultID) @@ -896,11 +862,13 @@ public function insert($data = null, bool $returnID = true) 'data' => $eventData['data'], 'result' => $result, ]; + if ($this->tempAllowCallbacks) { // Trigger afterInsert events with the inserted data and new ID $this->trigger('afterInsert', $eventData); } + $this->tempAllowCallbacks = $this->allowCallbacks; // If insertion failed, get out of here @@ -913,8 +881,6 @@ public function insert($data = null, bool $returnID = true) return $returnID ? $this->insertID : $result; } - //-------------------------------------------------------------------- - /** * Compiles batch insert strings and runs the queries, validating each row prior. * @@ -948,7 +914,7 @@ public function insertBatch(array $set = null, bool $escape = null, int $batchSi } // Validate every row.. - if ($this->skipValidation === false && $this->cleanRules()->validate($row) === false) + if (! $this->skipValidation && ! $this->cleanRules()->validate($row)) { return false; } @@ -967,12 +933,12 @@ public function insertBatch(array $set = null, bool $escape = null, int $batchSi // Set created_at and updated_at with same time $date = $this->setDate(); - if ($this->useTimestamps && ! empty($this->createdField) && ! array_key_exists($this->createdField, $row)) + if ($this->useTimestamps && $this->createdField && ! array_key_exists($this->createdField, $row)) { $row[$this->createdField] = $date; } - if ($this->useTimestamps && ! empty($this->updatedField) && ! array_key_exists($this->updatedField, $row)) + if ($this->useTimestamps && $this->updatedField && ! array_key_exists($this->updatedField, $row)) { $row[$this->updatedField] = $date; } @@ -982,14 +948,12 @@ public function insertBatch(array $set = null, bool $escape = null, int $batchSi return $this->builder()->testMode($testing)->insertBatch($set, $escape, $batchSize); } - //-------------------------------------------------------------------- - /** * Updates a single record in $this->table. If an object is provided, * it will attempt to convert it into an array. * - * @param integer|array|string $id - * @param array|object $data + * @param integer|array|string|null $id + * @param array|object|null $data * * @return boolean * @throws ReflectionException @@ -1038,19 +1002,16 @@ public function update($id = null, $data = null): bool } // Validate data before saving. - if ($this->skipValidation === false) + if (! $this->skipValidation && ! $this->cleanRules(true)->validate($data)) { - if ($this->cleanRules(true)->validate($data) === false) - { - return false; - } + return false; } // Must be called first so we don't // strip out updated_at values. $data = $this->doProtectFields($data); - if ($this->useTimestamps && ! empty($this->updatedField) && ! array_key_exists($this->updatedField, $data)) + if ($this->useTimestamps && $this->updatedField && ! array_key_exists($this->updatedField, $data)) { $data[$this->updatedField] = $this->setDate(); } @@ -1059,6 +1020,7 @@ public function update($id = null, $data = null): bool 'id' => $id, 'data' => $data, ]; + if ($this->tempAllowCallbacks) { $eventData = $this->trigger('beforeUpdate', $eventData); @@ -1073,25 +1035,25 @@ public function update($id = null, $data = null): bool // Must use the set() method to ensure objects get converted to arrays $result = $builder - ->set($eventData['data'], '', $escape) - ->update(); + ->set($eventData['data'], '', $escape) + ->update(); $eventData = [ 'id' => $id, 'data' => $eventData['data'], 'result' => $result, ]; + if ($this->tempAllowCallbacks) { $this->trigger('afterUpdate', $eventData); } + $this->tempAllowCallbacks = $this->allowCallbacks; return $result; } - //-------------------------------------------------------------------- - /** * Update_Batch * @@ -1128,7 +1090,7 @@ public function updateBatch(array $set = null, string $index = null, int $batchS } // Validate data before saving. - if ($this->skipValidation === false && $this->cleanRules(true)->validate($row) === false) + if (! $this->skipValidation && ! $this->cleanRules(true)->validate($row)) { return false; } @@ -1146,7 +1108,7 @@ public function updateBatch(array $set = null, string $index = null, int $batchS $row[$index] = $updateIndex; } - if ($this->useTimestamps && ! empty($this->updatedField) && ! array_key_exists($this->updatedField, $row)) + if ($this->useTimestamps && $this->updatedField && ! array_key_exists($this->updatedField, $row)) { $row[$this->updatedField] = $this->setDate(); } @@ -1156,8 +1118,6 @@ public function updateBatch(array $set = null, string $index = null, int $batchS return $this->builder()->testMode($returnSQL)->updateBatch($set, $index, $batchSize); } - //-------------------------------------------------------------------- - /** * Deletes a single record from $this->table where $id matches * the table's primaryKey @@ -1170,13 +1130,14 @@ public function updateBatch(array $set = null, string $index = null, int $batchS */ public function delete($id = null, bool $purge = false) { - if (! empty($id) && (is_numeric($id) || is_string($id))) + if ($id && (is_numeric($id) || is_string($id))) { $id = [$id]; } $builder = $this->builder(); - if (! empty($id)) + + if ($id) { $builder = $builder->whereIn($this->primaryKey, $id); } @@ -1185,6 +1146,7 @@ public function delete($id = null, bool $purge = false) 'id' => $id, 'purge' => $purge, ]; + if ($this->tempAllowCallbacks) { $this->trigger('beforeDelete', $eventData); @@ -1198,13 +1160,13 @@ public function delete($id = null, bool $purge = false) { throw new DatabaseException('Deletes are not allowed unless they contain a "where" or "like" clause.'); } - // @codeCoverageIgnoreStart - return false; - // @codeCoverageIgnoreEnd + + return false; // @codeCoverageIgnore } + $set[$this->deletedField] = $this->setDate(); - if ($this->useTimestamps && ! empty($this->updatedField)) + if ($this->useTimestamps && $this->updatedField) { $set[$this->updatedField] = $this->setDate(); } @@ -1222,17 +1184,17 @@ public function delete($id = null, bool $purge = false) 'result' => $result, 'data' => null, ]; + if ($this->tempAllowCallbacks) { $this->trigger('afterDelete', $eventData); } + $this->tempAllowCallbacks = $this->allowCallbacks; return $result; } - //-------------------------------------------------------------------- - /** * Permanently deletes all rows that have been marked as deleted * through soft deletes (deleted = 1) @@ -1247,66 +1209,55 @@ public function purgeDeleted() } return $this->builder() - ->where($this->table . '.' . $this->deletedField . ' IS NOT NULL') - ->delete(); + ->where($this->table . '.' . $this->deletedField . ' IS NOT NULL') + ->delete(); } - //-------------------------------------------------------------------- - /** * Sets $useSoftDeletes value so that we can temporarily override * the softdeletes settings. Can be used for all find* methods. * * @param boolean $val * - * @return Model + * @return $this */ - public function withDeleted($val = true) + public function withDeleted(bool $val = true) { $this->tempUseSoftDeletes = ! $val; return $this; } - //-------------------------------------------------------------------- - /** * Works with the find* methods to return only the rows that * have been deleted. * - * @return Model + * @return $this */ public function onlyDeleted() { $this->tempUseSoftDeletes = false; - - $this->builder() - ->where($this->table . '.' . $this->deletedField . ' IS NOT NULL'); + $this->builder()->where($this->table . '.' . $this->deletedField . ' IS NOT NULL'); return $this; } - //-------------------------------------------------------------------- - /** * Replace * - * Compiles an replace into string and runs the query + * Compiles a replace into string and runs the query * - * @param null $data - * @param boolean $returnSQL + * @param array|null $data + * @param boolean $returnSQL * * @return mixed */ - public function replace($data = null, bool $returnSQL = false) + public function replace(array $data = null, bool $returnSQL = false) { // Validate data before saving. - if (! empty($data) && $this->skipValidation === false) + if ($data && ! $this->skipValidation && ! $this->cleanRules(true)->validate($data)) { - if ($this->cleanRules(true)->validate($data) === false) - { - return false; - } + return false; } return $this->builder()->testMode($returnSQL)->replace($data); @@ -1319,7 +1270,7 @@ public function replace($data = null, bool $returnSQL = false) /** * Sets the return type of the results to be as an associative array. * - * @return Model + * @return $this */ public function asArray() { @@ -1328,8 +1279,6 @@ public function asArray() return $this; } - //-------------------------------------------------------------------- - /** * Sets the return type to be of the specified type of object. * Defaults to a simple object, but can be any class that has @@ -1338,7 +1287,7 @@ public function asArray() * * @param string $class * - * @return Model + * @return $this */ public function asObject(string $class = 'object') { @@ -1347,8 +1296,6 @@ public function asObject(string $class = 'object') return $this; } - //-------------------------------------------------------------------- - /** * Loops over records in batches, allowing you to operate on them. * Works with $this->builder to get the Compiled select to @@ -1361,18 +1308,15 @@ public function asObject(string $class = 'object') */ public function chunk(int $size, Closure $userFunc) { - $total = $this->builder() - ->countAllResults(false); - + $total = $this->builder()->countAllResults(false); $offset = 0; while ($offset <= $total) { - $builder = clone($this->builder()); + $builder = clone $this->builder(); + $rows = $builder->get($size, $offset); - $rows = $builder->get($size, $offset); - - if ($rows === false) + if (! $rows) { throw DataException::forEmptyDataset('chunk'); } @@ -1396,18 +1340,15 @@ public function chunk(int $size, Closure $userFunc) } } - //-------------------------------------------------------------------- - /** * Works with $this->builder to get the Compiled Select to operate on. * Expects a GET variable (?page=2) that specifies the page of results * to display. * - * @param integer $perPage - * @param string $group Will be used by the pagination library - * to identify a unique pagination set. - * @param integer $page Optional page number (useful when the page number is provided in different way) - * @param integer $segment Optional URI segment number (if page number is provided by URI segment) + * @param integer|null $perPage + * @param string $group Will be used by the pagination library to identify a unique pagination set. + * @param integer|null $page Optional page number (useful when the page number is provided in different way) + * @param integer $segment Optional URI segment number (if page number is provided by URI segment) * * @return array|null */ @@ -1420,8 +1361,7 @@ public function paginate(int $perPage = null, string $group = 'default', int $pa $pager->setSegment($segment); } - $page = $page >= 1 ? $page : $pager->getCurrentPage($group); - + $page = $page >= 1 ? $page : $pager->getCurrentPage($group); $total = $this->countAllResults(false); // Store it in the Pager library so it can be @@ -1433,15 +1373,13 @@ public function paginate(int $perPage = null, string $group = 'default', int $pa return $this->findAll($perPage, $offset); } - //-------------------------------------------------------------------- - /** * Sets whether or not we should whitelist data set during * updates or inserts against $this->availableFields. * * @param boolean $protect * - * @return Model + * @return $this */ public function protect(bool $protect = true) { @@ -1450,8 +1388,6 @@ public function protect(bool $protect = true) return $this; } - //-------------------------------------------------------------------- - /** * Provides a shared instance of the Query Builder. * @@ -1472,7 +1408,7 @@ protected function builder(string $table = null) // and future features are likely to require them. if (empty($this->primaryKey)) { - throw ModelException::forNoPrimaryKey(get_class($this)); + throw ModelException::forNoPrimaryKey(static::class); } $table = empty($table) ? $this->table : $table; @@ -1488,8 +1424,6 @@ protected function builder(string $table = null) return $this->builder; } - //-------------------------------------------------------------------- - /** * Ensures that only the fields that are allowed to be updated * are in the data array. @@ -1504,7 +1438,7 @@ protected function builder(string $table = null) */ protected function doProtectFields(array $data): array { - if ($this->protectFields === false) + if (! $this->protectFields) { return $data; } @@ -1525,8 +1459,6 @@ protected function doProtectFields(array $data): array return $data; } - //-------------------------------------------------------------------- - /** * A utility function to allow child models to use the type of * date/time format that they prefer. This is primarily used for @@ -1545,7 +1477,7 @@ protected function doProtectFields(array $data): array */ protected function setDate(int $userData = null) { - $currentDate = is_numeric($userData) ? (int) $userData : time(); + $currentDate = $userData ?? time(); switch ($this->dateFormat) { @@ -1556,18 +1488,16 @@ protected function setDate(int $userData = null) case 'date': return date('Y-m-d', $currentDate); default: - throw ModelException::forNoDateFormat(get_class($this)); + throw ModelException::forNoDateFormat(static::class); } } - //-------------------------------------------------------------------- - /** * Specify the table associated with a model * * @param string $table * - * @return Model + * @return $this */ public function setTable(string $table) { @@ -1576,8 +1506,6 @@ public function setTable(string $table) return $this; } - //-------------------------------------------------------------------- - /** * Grabs the last error(s) that occurred. If data was validated, * it will first check for errors there, otherwise will try to @@ -1590,7 +1518,7 @@ public function setTable(string $table) public function errors(bool $forceDB = false) { // Do we have validation errors? - if ($forceDB === false && $this->skipValidation === false) + if (! $forceDB && ! $this->skipValidation) { $errors = $this->validation->getErrors(); @@ -1600,27 +1528,25 @@ public function errors(bool $forceDB = false) } } - // Still here? Grab the database-specific error, if any. $error = $this->db->error(); return $error['message'] ?? null; } - //-------------------------------------------------------------------- - /** * It could be used when you have to change default or override current allowed fields. * * @param array $allowedFields * - * @return void + * @return $this */ public function setAllowedFields(array $allowedFields) { $this->allowedFields = $allowedFields; + + return $this; } - //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Validation //-------------------------------------------------------------------- @@ -1630,7 +1556,7 @@ public function setAllowedFields(array $allowedFields) * * @param boolean $skip * - * @return Model + * @return $this */ public function skipValidation(bool $skip = true) { @@ -1639,21 +1565,20 @@ public function skipValidation(bool $skip = true) return $this; } - //-------------------------------------------------------------------- - /** * Allows to set validation messages. * It could be used when you have to change default or override current validate messages. * * @param array $validationMessages * - * @return void + * @return $this */ public function setValidationMessages(array $validationMessages) { $this->validationMessages = $validationMessages; + + return $this; } - //-------------------------------------------------------------------- /** * Allows to set field wise validation message. @@ -1662,14 +1587,14 @@ public function setValidationMessages(array $validationMessages) * @param string $field * @param array $fieldMessages * - * @return void + * @return $this */ public function setValidationMessage(string $field, array $fieldMessages) { $this->validationMessages[$field] = $fieldMessages; - } - //-------------------------------------------------------------------- + return $this; + } /** * Allows to set validation rules. @@ -1677,14 +1602,14 @@ public function setValidationMessage(string $field, array $fieldMessages) * * @param array $validationRules * - * @return void + * @return $this */ public function setValidationRules(array $validationRules) { $this->validationRules = $validationRules; - } - //-------------------------------------------------------------------- + return $this; + } /** * Allows to set field wise validation rules. @@ -1693,14 +1618,14 @@ public function setValidationRules(array $validationRules) * @param string $field * @param string|array $fieldRules * - * @return void + * @return $this */ public function setValidationRule(string $field, $fieldRules) { $this->validationRules[$field] = $fieldRules; - } - //-------------------------------------------------------------------- + return $this; + } /** * Should validation rules be removed before saving? @@ -1717,8 +1642,6 @@ public function cleanRules(bool $choice = false) return $this; } - //-------------------------------------------------------------------- - /** * Validate the data against the validation rules (or the validation group) * specified in the class property, $validationRules. @@ -1731,7 +1654,7 @@ public function validate($data): bool { $rules = $this->getValidationRules(); - if ($this->skipValidation === true || empty($rules) || empty($data)) + if ($this->skipValidation || empty($rules) || empty($data)) { return true; } @@ -1743,9 +1666,7 @@ public function validate($data): bool $data = (array) $data; } - $rules = $this->cleanValidationRules - ? $this->cleanValidationRules($rules, $data) - : $rules; + $rules = $this->cleanValidationRules ? $this->cleanValidationRules($rules, $data) : $rules; // If no data existed that needs validation // our job is done here. @@ -1754,19 +1675,17 @@ public function validate($data): bool return true; } - return $this->validation->setRules($rules, $this->validationMessages) - ->run($data, null, $this->DBGroup); + return $this->validation + ->setRules($rules, $this->validationMessages) + ->run($data, null, $this->DBGroup); } - //-------------------------------------------------------------------- - /** * Removes any rules that apply to fields that have not been set * currently so that rules don't block updating when only updating * a partial row. * * @param array $rules - * * @param array|null $data * * @return array @@ -1839,6 +1758,7 @@ protected function fillPlaceholders(array $rules, array $data): array $row = strtr($row, $replacements); } + continue; } @@ -1849,8 +1769,6 @@ protected function fillPlaceholders(array $rules, array $data): array return $rules; } - //-------------------------------------------------------------------- - /** * Returns the model's defined validation rules so that they * can be used elsewhere, if needed. @@ -1867,7 +1785,7 @@ public function getValidationRules(array $options = []): array // or an array of rules. if (is_string($rules)) { - $rules = $this->validation->loadRuleGroup($rules); + $rules = $this->validation->loadRuleGroup($rules); // @phpstan-ignore-line } if (isset($options['except'])) @@ -1882,8 +1800,6 @@ public function getValidationRules(array $options = []): array return $rules; } - //-------------------------------------------------------------------- - /** * Returns the model's define validation messages so they * can be used elsewhere, if needed. @@ -1895,8 +1811,6 @@ public function getValidationMessages(): array return $this->validationMessages; } - //-------------------------------------------------------------------- - /** * Override countAllResults to account for soft deleted accounts. * @@ -1907,7 +1821,7 @@ public function getValidationMessages(): array */ public function countAllResults(bool $reset = true, bool $test = false) { - if ($this->tempUseSoftDeletes === true) + if ($this->tempUseSoftDeletes) { $this->builder()->where($this->table . '.' . $this->deletedField, null); } @@ -1915,11 +1829,9 @@ public function countAllResults(bool $reset = true, bool $test = false) // When $reset === false, the $tempUseSoftDeletes will be // dependant on $useSoftDeletes value because we don't // want to add the same "where" condition for the second time - $this->tempUseSoftDeletes = ($reset === true) + $this->tempUseSoftDeletes = $reset ? $this->useSoftDeletes - : ($this->useSoftDeletes === true - ? false - : $this->useSoftDeletes); + : ($this->useSoftDeletes ? false : $this->useSoftDeletes); return $this->builder()->testMode($test)->countAllResults($reset); } @@ -1930,7 +1842,7 @@ public function countAllResults(bool $reset = true, bool $test = false) * * @param boolean $val * - * @return Model + * @return $this */ public function allowCallbacks(bool $val = true) { @@ -1981,8 +1893,6 @@ protected function trigger(string $event, array $eventData) return $eventData; } - //-------------------------------------------------------------------- - //-------------------------------------------------------------------- // Magic //-------------------------------------------------------------------- @@ -1998,7 +1908,7 @@ public function __get(string $name) { if (property_exists($this, $name)) { - return $this->{$name}; + return $this->$name; } if (isset($this->db->$name)) @@ -2041,8 +1951,6 @@ public function __isset(string $name): bool return false; } - //-------------------------------------------------------------------- - /** * Provides direct access to method in the builder (if available) * and the database connection. @@ -2050,7 +1958,7 @@ public function __isset(string $name): bool * @param string $name * @param array $params * - * @return Model|null + * @return $this|null */ public function __call(string $name, array $params) { @@ -2058,11 +1966,11 @@ public function __call(string $name, array $params) if (method_exists($this->db, $name)) { - $result = $this->db->$name(...$params); + $result = $this->db->{$name}(...$params); } elseif (method_exists($builder = $this->builder(), $name)) { - $result = $builder->$name(...$params); + $result = $builder->{$name}(...$params); } // Don't return the builder object unless specifically requested @@ -2072,11 +1980,14 @@ public function __call(string $name, array $params) { if (! method_exists($this->builder(), $name)) { - $className = get_class($this); + $className = static::class; + throw new BadMethodCallException("Call to undefined method $className::$name"); } + return $result; } + if ($name !== 'builder' && ! $result instanceof BaseBuilder) { return $result; @@ -2084,6 +1995,4 @@ public function __call(string $name, array $params) return $this; } - - //-------------------------------------------------------------------- }