5 use Friendica\Database\Database;
6 use Friendica\Database\DBA;
7 use Friendica\Network\HTTPException;
8 use Psr\Log\LoggerInterface;
11 * Repositories are Factories linked to one or more database tables.
16 abstract class BaseRepository extends BaseFactory
24 protected static $table_name;
27 protected static $model_class;
29 /** @var BaseCollection */
30 protected static $collection_class;
32 public function __construct(Database $dba, LoggerInterface $logger)
34 parent::__construct($logger);
37 $this->logger = $logger;
41 * Fetches a single model record. The condition array is expected to contain a unique index (primary or otherwise).
45 * @param array $condition
47 * @throws HTTPException\NotFoundException
49 public function selectFirst(array $condition)
51 $data = $this->dba->selectFirst(static::$table_name, [], $condition);
54 throw new HTTPException\NotFoundException(static::class . ' record not found.');
57 return $this->create($data);
61 * Populates a Collection according to the condition.
65 * @param array $condition
66 * @param array $params
67 * @return BaseCollection
70 public function select(array $condition = [], array $params = [])
72 $models = $this->selectModels($condition, $params);
74 return new static::$collection_class($models);
78 * Populates the collection according to the condition. Retrieves a limited subset of models depending on the boundaries
79 * and the limit. The total count of rows matching the condition is stored in the collection.
83 * @param array $condition
84 * @param array $params
86 * @param int? $since_id
88 * @return BaseCollection
91 public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT)
93 $condition = DBA::collapseCondition($condition);
95 $boundCondition = $condition;
98 $boundCondition[0] .= " AND `id` < ?";
99 $boundCondition[] = $max_id;
102 if (isset($since_id)) {
103 $boundCondition[0] .= " AND `id` > ?";
104 $boundCondition[] = $since_id;
107 $params['limit'] = $limit;
109 $models = $this->selectModels($boundCondition, $params);
111 $totalCount = DBA::count(static::$table_name, $condition);
113 return new static::$collection_class($models, $totalCount);
117 * This method updates the database row from the model.
119 * @param BaseModel $model
123 public function update(BaseModel $model)
125 if ($this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData())) {
126 $model->resetOriginalData();
134 * This method creates a new database row and returns a model if it was successful.
136 * @param array $fields
137 * @return BaseModel|bool
140 public function insert(array $fields)
142 $return = $this->dba->insert(static::$table_name, $fields);
145 throw new HTTPException\InternalServerErrorException('Unable to insert new row in table "' . static::$table_name . '"');
148 $fields['id'] = $this->dba->lastInsertId();
149 $return = $this->create($fields);
155 * Deletes the model record from the database.
157 * @param BaseModel $model
161 public function delete(BaseModel &$model)
163 if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) {
171 * Base instantiation method, can be overriden to add specific dependencies
176 protected function create(array $data)
178 return new static::$model_class($this->dba, $this->logger, $data);
182 * @param array $condition Query condition
183 * @param array $params Additional query parameters
184 * @return BaseModel[]
187 protected function selectModels(array $condition, array $params = [])
189 $result = $this->dba->select(static::$table_name, [], $condition, $params);
191 /** @var BaseModel $prototype */
196 while ($record = $this->dba->fetch($result)) {
197 if ($prototype === null) {
198 $prototype = $this->create($record);
199 $models[] = $prototype;
201 $models[] = static::$model_class::createFromPrototype($prototype, $record);
209 * @param BaseCollection $collection
211 public function saveCollection(BaseCollection $collection)
213 $collection->map([$this, 'update']);