X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FBaseRepository.php;h=1ffe82b0b59371b794a43ea491a38f910d4ec3f0;hb=cab469621d173015ade7846344f5051b600d640d;hp=abec4c119b3f21c834cc73ba34017184ded8f94f;hpb=fb7f7435c080e15bdafbbcbb5a3dfd94ef8dd952;p=friendica.git diff --git a/src/BaseRepository.php b/src/BaseRepository.php index abec4c119b..1ffe82b0b5 100644 --- a/src/BaseRepository.php +++ b/src/BaseRepository.php @@ -1,6 +1,6 @@ dba = $dba; - $this->logger = $logger; - } - - /** - * Fetches a single model record. The condition array is expected to contain a unique index (primary or otherwise). - * - * Chainable. - * - * @param array $condition - * @return BaseModel - * @throws HTTPException\NotFoundException - */ - public function selectFirst(array $condition) + public function __construct(Database $database, LoggerInterface $logger, ICanCreateFromTableRow $factory) { - $data = $this->dba->selectFirst(static::$table_name, [], $condition); - - if (!$data) { - throw new HTTPException\NotFoundException(static::class . ' record not found.'); - } - - return $this->create($data); + $this->db = $database; + $this->logger = $logger; + $this->factory = $factory; } /** - * Populates a Collection according to the condition. + * Populates the collection according to the condition. Retrieves a limited subset of entities depending on the + * boundaries and the limit. The total count of rows matching the condition is stored in the collection. * - * Chainable. + * Depends on the corresponding table featuring a numerical auto incremented column called `id`. * - * @param array $condition - * @param array $params - * @return BaseCollection - * @throws \Exception - */ - public function select(array $condition = [], array $params = []) - { - $models = $this->selectModels($condition, $params); - - return new static::$collection_class($models); - } - - /** - * Populates the collection according to the condition. Retrieves a limited subset of models depending on the boundaries - * and the limit. The total count of rows matching the condition is stored in the collection. + * max_id and min_id are susceptible to the query order: + * - min_id alone only reliably works with ASC order + * - max_id alone only reliably works with DESC order + * If the wrong order is detected in either case, we reverse the query order and the entity list order after the query * * Chainable. * - * @param array $condition - * @param array $params - * @param int? $max_id - * @param int? $since_id - * @param int $limit + * @param array $condition + * @param array $params + * @param int|null $min_id Retrieve models with an id no fewer than this, as close to it as possible + * @param int|null $max_id Retrieve models with an id no greater than this, as close to it as possible + * @param int $limit * @return BaseCollection * @throws \Exception */ - public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT) - { - $totalCount = DBA::count(static::$table_name, $condition); + protected function _selectByBoundaries( + array $condition = [], + array $params = [], + int $min_id = null, + int $max_id = null, + int $limit = self::LIMIT + ): BaseCollection { + $totalCount = $this->count($condition); $boundCondition = $condition; - if (isset($max_id)) { - $boundCondition = DBA::mergeConditions($boundCondition, ['`id` < ?', $max_id]); - } + $reverseOrder = false; - if (isset($since_id)) { - $boundCondition = DBA::mergeConditions($boundCondition, ['`id` > ?', $since_id]); + if (isset($min_id)) { + $boundCondition = DBA::mergeConditions($boundCondition, ['`id` > ?', $min_id]); + if (!isset($max_id) && isset($params['order']['id']) && ($params['order']['id'] === true || $params['order']['id'] === 'DESC')) { + $reverseOrder = true; + + $params['order']['id'] = 'ASC'; + } } - $params['limit'] = $limit; + if (isset($max_id) && $max_id > 0) { + $boundCondition = DBA::mergeConditions($boundCondition, ['`id` < ?', $max_id]); + if (!isset($min_id) && (!isset($params['order']['id']) || $params['order']['id'] === false || $params['order']['id'] === 'ASC')) { + $reverseOrder = true; - $models = $this->selectModels($boundCondition, $params); + $params['order']['id'] = 'DESC'; + } + } - return new static::$collection_class($models, $totalCount); - } + $params['limit'] = $limit; - /** - * This method updates the database row from the model. - * - * @param BaseModel $model - * @return bool - * @throws \Exception - */ - public function update(BaseModel $model) - { - if ($this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData())) { - $model->resetOriginalData(); - return true; + $Entities = $this->_select($boundCondition, $params); + if ($reverseOrder) { + $Entities->reverse(); } - return false; + return new BaseCollection($Entities->getArrayCopy(), $totalCount); } /** - * This method creates a new database row and returns a model if it was successful. - * - * @param array $fields - * @return BaseModel|bool - * @throws \Exception + * @param array $condition + * @param array $params + * @return BaseCollection + * @throws Exception */ - public function insert(array $fields) + protected function _select(array $condition, array $params = []): BaseCollection { - $return = $this->dba->insert(static::$table_name, $fields); + $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params); - if (!$return) { - throw new HTTPException\InternalServerErrorException('Unable to insert new row in table "' . static::$table_name . '"'); + $Entities = new BaseCollection(); + foreach ($rows as $fields) { + $Entities[] = $this->factory->createFromTableRow($fields); } - $fields['id'] = $this->dba->lastInsertId(); - $return = $this->create($fields); - - return $return; + return $Entities; } /** - * Deletes the model record from the database. - * - * @param BaseModel $model - * @return bool - * @throws \Exception + * @param array $condition + * @param array $params + * @return BaseEntity + * @throws NotFoundException */ - public function delete(BaseModel &$model) + protected function _selectOne(array $condition, array $params = []): BaseEntity { - if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) { - $model = null; + $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params); + if (!$this->db->isResult($fields)) { + throw new NotFoundException(); } - return $success; - } - - /** - * Base instantiation method, can be overriden to add specific dependencies - * - * @param array $data - * @return BaseModel - */ - protected function create(array $data) - { - return new static::$model_class($this->dba, $this->logger, $data); + return $this->factory->createFromTableRow($fields); } /** - * @param array $condition Query condition - * @param array $params Additional query parameters - * @return BaseModel[] - * @throws \Exception + * @param array $condition + * @param array $params + * @return int + * @throws Exception */ - protected function selectModels(array $condition, array $params = []) + public function count(array $condition, array $params = []): int { - $result = $this->dba->select(static::$table_name, [], $condition, $params); - - /** @var BaseModel $prototype */ - $prototype = null; - - $models = []; - - while ($record = $this->dba->fetch($result)) { - if ($prototype === null) { - $prototype = $this->create($record); - $models[] = $prototype; - } else { - $models[] = static::$model_class::createFromPrototype($prototype, $record); - } - } - - return $models; + return $this->db->count(static::$table_name, $condition, $params); } /** - * @param BaseCollection $collection + * @param array $condition + * @return bool + * @throws Exception */ - public function saveCollection(BaseCollection $collection) + public function exists(array $condition): bool { - $collection->map([$this, 'update']); + return $this->db->exists(static::$table_name, $condition); } }