]> git.mxchange.org Git - friendica.git/blob - src/BaseRepository.php
Introduce Repository, Factory, Collection, Model base classes
[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], true);
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                         $fields['id'] = $this->dba->lastInsertId();
141                         $return = $this->create($fields);
142                 }
143
144                 return $return;
145         }
146
147         /**
148          * Deletes the model record from the database.
149          *
150          * @param BaseModel $model
151          * @return bool
152          * @throws \Exception
153          */
154         public function delete(BaseModel &$model)
155         {
156                 if ($success = $this->dba->delete(static::$table_name, ['id' => $model->id])) {
157                         $model = null;
158                 }
159
160                 return $success;
161         }
162
163         /**
164          * Base instantiation method, can be overriden to add specific dependencies
165          *
166          * @param array $data
167          * @return BaseModel
168          */
169         protected function create(array $data)
170         {
171                 return new static::$model_class($this->dba, $this->logger, $data);
172         }
173
174         /**
175          * @param array $condition Query condition
176          * @param array $params    Additional query parameters
177          * @return BaseModel[]
178          * @throws \Exception
179          */
180         protected function selectModels(array $condition, array $params = [])
181         {
182                 $result = $this->dba->select(static::$table_name, [], $condition, $params);
183
184                 /** @var BaseModel $prototype */
185                 $prototype = null;
186
187                 $models = [];
188
189                 while ($record = $this->dba->fetch($result)) {
190                         if ($prototype === null) {
191                                 $prototype = $this->create($record);
192                                 $models[] = $prototype;
193                         } else {
194                                 $models[] = static::$model_class::createFromPrototype($prototype, $record);
195                         }
196                 }
197
198                 return $models;
199         }
200 }