]> git.mxchange.org Git - friendica.git/blob - src/BaseRepository.php
c0bcab18f92fbafc37a8e96b23561eecb1899c66
[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                 return $this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData());
126         }
127
128         /**
129          * This method creates a new database row and returns a model if it was successful.
130          *
131          * @param array $fields
132          * @return BaseModel|bool
133          * @throws \Exception
134          */
135         public function insert(array $fields)
136         {
137                 $return = $this->dba->insert(static::$table_name, $fields);
138
139                 if (!$return) {
140                         throw new HTTPException\InternalServerErrorException('Unable to insert new row in table "' . static::$table_name . '"');
141                 }
142
143                 $fields['id'] = $this->dba->lastInsertId();
144                 $return = $this->create($fields);
145
146                 return $return;
147         }
148
149         /**
150          * Deletes the model record from the database.
151          *
152          * @param BaseModel $model
153          * @return bool
154          * @throws \Exception
155          */
156         public function delete(BaseModel &$model)
157         {
158                 if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) {
159                         $model = null;
160                 }
161
162                 return $success;
163         }
164
165         /**
166          * Base instantiation method, can be overriden to add specific dependencies
167          *
168          * @param array $data
169          * @return BaseModel
170          */
171         protected function create(array $data)
172         {
173                 return new static::$model_class($this->dba, $this->logger, $data);
174         }
175
176         /**
177          * @param array $condition Query condition
178          * @param array $params    Additional query parameters
179          * @return BaseModel[]
180          * @throws \Exception
181          */
182         protected function selectModels(array $condition, array $params = [])
183         {
184                 $result = $this->dba->select(static::$table_name, [], $condition, $params);
185
186                 /** @var BaseModel $prototype */
187                 $prototype = null;
188
189                 $models = [];
190
191                 while ($record = $this->dba->fetch($result)) {
192                         if ($prototype === null) {
193                                 $prototype = $this->create($record);
194                                 $models[] = $prototype;
195                         } else {
196                                 $models[] = static::$model_class::createFromPrototype($prototype, $record);
197                         }
198                 }
199
200                 return $models;
201         }
202
203         /**
204          * @param BaseCollection $collection
205          */
206         public function saveCollection(BaseCollection $collection)
207         {
208                 $collection->map([$this, 'update']);
209         }
210 }