]> git.mxchange.org Git - friendica.git/blob - src/BaseRepository.php
Introduce "order" and "limit" argument instead of "param" array for BaseRepository...
[friendica.git] / src / BaseRepository.php
1 <?php
2
3 namespace Friendica;
4
5 use Friendica\Database\Database;
6 use Friendica\Database\DBA;
7 use Friendica\Network\HTTPException;
8 use Psr\Log\LoggerInterface;
9
10 /**
11  * Repositories are Factories linked to one or more database tables.
12  *
13  * @see BaseModel
14  * @see BaseCollection
15  */
16 abstract class BaseRepository extends BaseFactory
17 {
18         const LIMIT = 30;
19
20         /** @var Database */
21         protected $dba;
22
23         /** @var string */
24         protected static $table_name;
25
26         /** @var BaseModel */
27         protected static $model_class;
28
29         /** @var BaseCollection */
30         protected static $collection_class;
31
32         public function __construct(Database $dba, LoggerInterface $logger)
33         {
34                 parent::__construct($logger);
35
36                 $this->dba = $dba;
37                 $this->logger = $logger;
38         }
39
40         /**
41          * Fetches a single model record. The condition array is expected to contain a unique index (primary or otherwise).
42          *
43          * Chainable.
44          *
45          * @param array $condition
46          * @return BaseModel
47          * @throws HTTPException\NotFoundException
48          */
49         public function selectFirst(array $condition)
50         {
51                 $data = $this->dba->selectFirst(static::$table_name, [], $condition);
52
53                 if (!$data) {
54                         throw new HTTPException\NotFoundException(static::class . ' record not found.');
55                 }
56
57                 return $this->create($data);
58         }
59
60         /**
61          * Populates a Collection according to the condition.
62          *
63          * Chainable.
64          *
65          * @param array $condition
66          * @param array $order An optional array with order information
67          * @param int|array $limit Optional limit information
68          *
69          * @return BaseCollection
70          * @throws \Exception
71          */
72         public function select(array $condition = [], array $order = [], $limit = null)
73         {
74                 $models = $this->selectModels($condition, $order, $limit);
75
76                 return new static::$collection_class($models);
77         }
78
79         /**
80          * Populates the collection according to the condition. Retrieves a limited subset of models depending on the boundaries
81          * and the limit. The total count of rows matching the condition is stored in the collection.
82          *
83          * Chainable.
84          *
85          * @param array $condition
86          * @param array $order
87          * @param int?  $max_id
88          * @param int?  $since_id
89          * @param int   $limit
90          *
91          * @return BaseCollection
92          * @throws \Exception
93          */
94         public function selectByBoundaries(array $condition = [], array $order = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT)
95         {
96                 $condition = DBA::collapseCondition($condition);
97
98                 $boundCondition = $condition;
99
100                 if (isset($max_id)) {
101                         $boundCondition[0] .= " AND `id` < ?";
102                         $boundCondition[] = $max_id;
103                 }
104
105                 if (isset($since_id)) {
106                         $boundCondition[0] .= " AND `id` > ?";
107                         $boundCondition[] = $since_id;
108                 }
109
110                 $models = $this->selectModels($boundCondition, $order, $limit);
111
112                 $totalCount = DBA::count(static::$table_name, $condition);
113
114                 return new static::$collection_class($models, $totalCount);
115         }
116
117         /**
118          * This method updates the database row from the model.
119          *
120          * @param BaseModel $model
121          * @return bool
122          * @throws \Exception
123          */
124         public function update(BaseModel $model)
125         {
126                 return $this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData());
127         }
128
129         /**
130          * This method creates a new database row and returns a model if it was successful.
131          *
132          * @param array $fields
133          * @return BaseModel|bool
134          * @throws \Exception
135          */
136         public function insert(array $fields)
137         {
138                 $return = $this->dba->insert(static::$table_name, $fields);
139
140                 if (!$return) {
141                         throw new HTTPException\InternalServerErrorException('Unable to insert new row in table "' . static::$table_name . '"');
142                 }
143
144                 $fields['id'] = $this->dba->lastInsertId();
145                 $return = $this->create($fields);
146
147                 return $return;
148         }
149
150         /**
151          * Deletes the model record from the database.
152          *
153          * @param BaseModel $model
154          * @return bool
155          * @throws \Exception
156          */
157         public function delete(BaseModel &$model)
158         {
159                 if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) {
160                         $model = null;
161                 }
162
163                 return $success;
164         }
165
166         /**
167          * Base instantiation method, can be overriden to add specific dependencies
168          *
169          * @param array $data
170          * @return BaseModel
171          */
172         protected function create(array $data)
173         {
174                 return new static::$model_class($this->dba, $this->logger, $data);
175         }
176
177         /**
178          * @param array $condition Query condition
179          * @param array $order An optional array with order information
180          * @param int|array $limit Optional limit information
181          *
182          * @return BaseModel[]
183          * @throws \Exception
184          */
185         protected function selectModels(array $condition, array $order = [], $limit = null)
186         {
187                 $params = [];
188
189                 if (!empty($order)) {
190                         $params['order'] = $order;
191                 }
192
193                 if (!empty($limit)) {
194                         $params['limit'] = $limit;
195                 }
196
197                 $result = $this->dba->select(static::$table_name, [], $condition, $params);
198
199                 /** @var BaseModel $prototype */
200                 $prototype = null;
201
202                 $models = [];
203
204                 while ($record = $this->dba->fetch($result)) {
205                         if ($prototype === null) {
206                                 $prototype = $this->create($record);
207                                 $models[] = $prototype;
208                         } else {
209                                 $models[] = static::$model_class::createFromPrototype($prototype, $record);
210                         }
211                 }
212
213                 return $models;
214         }
215
216         /**
217          * @param BaseCollection $collection
218          */
219         public function saveCollection(BaseCollection $collection)
220         {
221                 $collection->map([$this, 'update']);
222         }
223 }