]> git.mxchange.org Git - friendica.git/blob - src/BaseRepository.php
cce1c50c17bc77f1cdc905a30297b8686f0c7b28
[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 $params
67          * @return BaseCollection
68          * @throws \Exception
69          */
70         public function select(array $condition = [], array $params = [])
71         {
72                 $models = $this->selectModels($condition, $params);
73
74                 return new static::$collection_class($models);
75         }
76
77         /**
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.
80          *
81          * Chainable.
82          *
83          * @param array $condition
84          * @param array $params
85          * @param int?  $max_id
86          * @param int?  $since_id
87          * @param int   $limit
88          * @return BaseCollection
89          * @throws \Exception
90          */
91         public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT)
92         {
93                 $condition = DBA::collapseCondition($condition);
94
95                 $boundCondition = $condition;
96
97                 if (isset($max_id)) {
98                         $boundCondition[0] .= " AND `id` < ?";
99                         $boundCondition[] = $max_id;
100                 }
101
102                 if (isset($since_id)) {
103                         $boundCondition[0] .= " AND `id` > ?";
104                         $boundCondition[] = $since_id;
105                 }
106
107                 $params['limit'] = $limit;
108
109                 $models = $this->selectModels($boundCondition, $params);
110
111                 $totalCount = DBA::count(static::$table_name, $condition);
112
113                 return new static::$collection_class($models, $totalCount);
114         }
115
116         /**
117          * This method updates the database row from the model.
118          *
119          * @param BaseModel $model
120          * @return bool
121          * @throws \Exception
122          */
123         public function update(BaseModel $model)
124         {
125                 if ($this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData())) {
126                         $model->resetOriginalData();
127                         return true;
128                 }
129
130                 return false;
131         }
132
133         /**
134          * This method creates a new database row and returns a model if it was successful.
135          *
136          * @param array $fields
137          * @return BaseModel|bool
138          * @throws \Exception
139          */
140         public function insert(array $fields)
141         {
142                 $return = $this->dba->insert(static::$table_name, $fields);
143
144                 if (!$return) {
145                         throw new HTTPException\InternalServerErrorException('Unable to insert new row in table "' . static::$table_name . '"');
146                 }
147
148                 $fields['id'] = $this->dba->lastInsertId();
149                 $return = $this->create($fields);
150
151                 return $return;
152         }
153
154         /**
155          * Deletes the model record from the database.
156          *
157          * @param BaseModel $model
158          * @return bool
159          * @throws \Exception
160          */
161         public function delete(BaseModel &$model)
162         {
163                 if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) {
164                         $model = null;
165                 }
166
167                 return $success;
168         }
169
170         /**
171          * Base instantiation method, can be overriden to add specific dependencies
172          *
173          * @param array $data
174          * @return BaseModel
175          */
176         protected function create(array $data)
177         {
178                 return new static::$model_class($this->dba, $this->logger, $data);
179         }
180
181         /**
182          * @param array $condition Query condition
183          * @param array $params    Additional query parameters
184          * @return BaseModel[]
185          * @throws \Exception
186          */
187         protected function selectModels(array $condition, array $params = [])
188         {
189                 $result = $this->dba->select(static::$table_name, [], $condition, $params);
190
191                 /** @var BaseModel $prototype */
192                 $prototype = null;
193
194                 $models = [];
195
196                 while ($record = $this->dba->fetch($result)) {
197                         if ($prototype === null) {
198                                 $prototype = $this->create($record);
199                                 $models[] = $prototype;
200                         } else {
201                                 $models[] = static::$model_class::createFromPrototype($prototype, $record);
202                         }
203                 }
204
205                 return $models;
206         }
207
208         /**
209          * @param BaseCollection $collection
210          */
211         public function saveCollection(BaseCollection $collection)
212         {
213                 $collection->map([$this, 'update']);
214         }
215 }