3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 use Friendica\Database\Database;
25 use Friendica\Database\DBA;
26 use Friendica\Network\HTTPException;
27 use Psr\Log\LoggerInterface;
30 * Repositories are Factories linked to one or more database tables.
35 abstract class BaseRepository extends BaseFactory
43 protected static $table_name;
46 protected static $model_class;
48 /** @var BaseCollection */
49 protected static $collection_class;
51 public function __construct(Database $dba, LoggerInterface $logger)
53 parent::__construct($logger);
56 $this->logger = $logger;
60 * Fetches a single model record. The condition array is expected to contain a unique index (primary or otherwise).
64 * @param array $condition
66 * @throws HTTPException\NotFoundException
68 public function selectFirst(array $condition)
70 $data = $this->dba->selectFirst(static::$table_name, [], $condition);
73 throw new HTTPException\NotFoundException(static::class . ' record not found.');
76 return $this->create($data);
80 * Populates a Collection according to the condition.
84 * @param array $condition
85 * @param array $params
86 * @return BaseCollection
89 public function select(array $condition = [], array $params = [])
91 $models = $this->selectModels($condition, $params);
93 return new static::$collection_class($models);
97 * Populates the collection according to the condition. Retrieves a limited subset of models depending on the boundaries
98 * and the limit. The total count of rows matching the condition is stored in the collection.
102 * @param array $condition
103 * @param array $params
104 * @param int? $max_id
105 * @param int? $since_id
107 * @return BaseCollection
110 public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT)
112 $condition = DBA::collapseCondition($condition);
114 $boundCondition = $condition;
116 if (isset($max_id)) {
117 $boundCondition[0] .= " AND `id` < ?";
118 $boundCondition[] = $max_id;
121 if (isset($since_id)) {
122 $boundCondition[0] .= " AND `id` > ?";
123 $boundCondition[] = $since_id;
126 $params['limit'] = $limit;
128 $models = $this->selectModels($boundCondition, $params);
130 $totalCount = DBA::count(static::$table_name, $condition);
132 return new static::$collection_class($models, $totalCount);
136 * This method updates the database row from the model.
138 * @param BaseModel $model
142 public function update(BaseModel $model)
144 if ($this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData())) {
145 $model->resetOriginalData();
153 * This method creates a new database row and returns a model if it was successful.
155 * @param array $fields
156 * @return BaseModel|bool
159 public function insert(array $fields)
161 $return = $this->dba->insert(static::$table_name, $fields);
164 throw new HTTPException\InternalServerErrorException('Unable to insert new row in table "' . static::$table_name . '"');
167 $fields['id'] = $this->dba->lastInsertId();
168 $return = $this->create($fields);
174 * Deletes the model record from the database.
176 * @param BaseModel $model
180 public function delete(BaseModel &$model)
182 if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) {
190 * Base instantiation method, can be overriden to add specific dependencies
195 protected function create(array $data)
197 return new static::$model_class($this->dba, $this->logger, $data);
201 * @param array $condition Query condition
202 * @param array $params Additional query parameters
203 * @return BaseModel[]
206 protected function selectModels(array $condition, array $params = [])
208 $result = $this->dba->select(static::$table_name, [], $condition, $params);
210 /** @var BaseModel $prototype */
215 while ($record = $this->dba->fetch($result)) {
216 if ($prototype === null) {
217 $prototype = $this->create($record);
218 $models[] = $prototype;
220 $models[] = static::$model_class::createFromPrototype($prototype, $record);
228 * @param BaseCollection $collection
230 public function saveCollection(BaseCollection $collection)
232 $collection->map([$this, 'update']);