]> git.mxchange.org Git - friendica.git/blob - src/Profile/ProfileField/Repository/ProfileField.php
Added comment
[friendica.git] / src / Profile / ProfileField / Repository / ProfileField.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Profile\ProfileField\Repository;
23
24 use Friendica\BaseRepository;
25 use Friendica\Database\Database;
26 use Friendica\Profile\ProfileField\Exception\ProfileFieldNotFoundException;
27 use Friendica\Profile\ProfileField\Exception\ProfileFieldPersistenceException;
28 use Friendica\Profile\ProfileField\Exception\UnexpectedPermissionSetException;
29 use Friendica\Profile\ProfileField\Factory;
30 use Friendica\Profile\ProfileField\Entity;
31 use Friendica\Profile\ProfileField\Collection;
32 use Friendica\Security\PermissionSet\Repository\PermissionSet as PermissionSetRepository;
33 use Friendica\Util\DateTimeFormat;
34 use Psr\Log\LoggerInterface;
35
36 class ProfileField extends BaseRepository
37 {
38         /** @var  Factory\ProfileField */
39         protected $factory;
40
41         protected static $table_name = 'profile_field';
42
43         protected static $view_name = 'profile_field-view';
44
45         /** @var PermissionSetRepository */
46         protected $permissionSetRepository;
47
48         public function __construct(Database $database, LoggerInterface $logger, Factory\ProfileField $factory, PermissionSetRepository $permissionSetRepository)
49         {
50                 parent::__construct($database, $logger, $factory);
51
52                 $this->permissionSetRepository = $permissionSetRepository;
53         }
54
55         /**
56          * @param array $condition
57          * @param array $params
58          *
59          * @return Entity\ProfileField
60          *
61          * @throws ProfileFieldNotFoundException
62          * @throws UnexpectedPermissionSetException
63          */
64         private function selectOne(array $condition, array $params = []): Entity\ProfileField
65         {
66                 $fields = $this->db->selectFirst(static::$view_name, [], $condition, $params);
67                 if (!$this->db->isResult($fields)) {
68                         throw new ProfileFieldNotFoundException();
69                 }
70
71                 return $this->factory->createFromTableRow($fields);
72         }
73
74         /**
75          * @param array $condition
76          * @param array $params
77          *
78          * @return Collection\ProfileFields
79          *
80          * @throws ProfileFieldPersistenceException In case of underlying persistence exceptions
81          * @throws UnexpectedPermissionSetException
82          */
83         private function select(array $condition, array $params = []): Collection\ProfileFields
84         {
85                 $rows = $this->db->selectToArray(static::$view_name, [], $condition, $params);
86
87                 $Entities = new Collection\ProfileFields();
88                 foreach ($rows as $fields) {
89                         $Entities[] = $this->factory->createFromTableRow($fields);
90                 }
91
92                 return $Entities;
93         }
94
95         /**
96          * Converts a given ProfileField into a DB compatible row array
97          *
98          * @param Entity\ProfileField $profileField
99          *
100          * @return array
101          */
102         protected function convertToTableRow(Entity\ProfileField $profileField): array
103         {
104                 return [
105                         'uid'     => $profileField->uid,
106                         'label'   => $profileField->label,
107                         'value'   => $profileField->value,
108                         'order'   => $profileField->order,
109                         'created' => $profileField->created->format(DateTimeFormat::MYSQL),
110                         'edited'  => $profileField->edited->format(DateTimeFormat::MYSQL),
111                         'psid'    => $profileField->permissionSet->id
112                 ];
113         }
114
115         /**
116          * Returns all public available ProfileFields for a specific user
117          *
118          * @param int $uid the user id
119          *
120          * @return Collection\ProfileFields
121          *
122          * @throws ProfileFieldPersistenceException In case of underlying persistence exceptions
123          */
124         public function selectPublicFieldsByUserId(int $uid): Collection\ProfileFields
125         {
126                 try {
127                         $publicPermissionSet = $this->permissionSetRepository->selectPublicForUser($uid);
128
129                         return $this->select([
130                                 'uid'  => $uid,
131                                 'psid' => $publicPermissionSet->id
132                         ]);
133                 } catch (\Exception $exception) {
134                         throw new ProfileFieldPersistenceException(sprintf('Cannot select public ProfileField for user "%d"', $uid), $exception);
135                 }
136         }
137
138         /**
139          * @param int $uid Field owner user Id
140          *
141          * @throws ProfileFieldPersistenceException In case of underlying persistence exceptions
142          */
143         public function selectByUserId(int $uid): Collection\ProfileFields
144         {
145                 try {
146                         return $this->select(
147                                 ['uid' => $uid],
148                                 ['order' => ['order']]
149                         );
150                 } catch (\Exception $exception) {
151                         throw new ProfileFieldPersistenceException(sprintf('Cannot select ProfileField for user "%d"', $uid), $exception);
152                 }
153         }
154
155         /**
156          * Retrieve all custom profile field a given contact is able to access to, including public profile fields.
157          *
158          * @param int $cid Private contact id, must be owned by $uid
159          * @param int $uid Field owner user id
160          *
161          * @throws \Exception
162          */
163         public function selectByContactId(int $cid, int $uid): Collection\ProfileFields
164         {
165                 $permissionSets = $this->permissionSetRepository->selectByContactId($cid, $uid);
166
167                 $permissionSetIds = $permissionSets->column('id');
168
169                 // Includes public custom fields
170                 $permissionSetIds[] = $this->permissionSetRepository->selectPublicForUser($uid)->id;
171
172                 return $this->select(
173                         ['uid' => $uid, 'psid' => $permissionSetIds],
174                         ['order' => ['order']]
175                 );
176         }
177
178         /**
179          * @param int $id
180          *
181          * @return Entity\ProfileField
182          *
183          * @ProfileFieldNotFoundException In case there is no ProfileField found
184          */
185         public function selectOneById(int $id): Entity\ProfileField
186         {
187                 try {
188                         return $this->selectOne(['id' => $id]);
189                 } catch (\Exception $exception) {
190                         throw new ProfileFieldNotFoundException(sprintf('Cannot find Profile "%s"', $id), $exception);
191                 }
192         }
193
194         /**
195          * Delets a whole collection of ProfileFields
196          *
197          * @param Collection\ProfileFields $profileFields
198          *
199          * @return bool
200          * @throws ProfileFieldPersistenceException in case the persistence layer cannot delete the ProfileFields
201          */
202         public function deleteCollection(Collection\ProfileFields $profileFields): bool
203         {
204                 try {
205                         return $this->db->delete(self::$table_name, ['id' => $profileFields->column('id')]);
206                 } catch (\Exception $exception) {
207                         throw new ProfileFieldPersistenceException('Cannot delete ProfileFields', $exception);
208                 }
209         }
210
211         /**
212          * @param Entity\ProfileField $profileField
213          *
214          * @return Entity\ProfileField
215          * @throws ProfileFieldPersistenceException in case the persistence layer cannot save the ProfileField
216          */
217         public function save(Entity\ProfileField $profileField): Entity\ProfileField
218         {
219                 if ($profileField->permissionSet->id === null) {
220                         throw new ProfileFieldPersistenceException('PermissionSet needs to be saved first.');
221                 }
222
223                 $fields = $this->convertToTableRow($profileField);
224
225                 try {
226                         if ($profileField->id) {
227                                 $this->db->update(self::$table_name, $fields, ['id' => $profileField->id]);
228                         } else {
229                                 $this->db->insert(self::$table_name, $fields);
230
231                                 $profileField = $this->selectOneById($this->db->lastInsertId());
232                         }
233                 } catch (\Exception $exception) {
234                         throw new ProfileFieldPersistenceException(sprintf('Cannot save ProfileField with id "%d" and label "%s"', $profileField->id, $profileField->label), $exception);
235                 }
236
237                 return $profileField;
238         }
239
240         public function saveCollectionForUser(int $uid, Collection\ProfileFields $profileFields): Collection\ProfileFields
241         {
242                 $savedProfileFields = new Collection\ProfileFields();
243
244                 $profileFieldsOld = $this->selectByUserId($uid);
245
246                 // Prunes profile field whose label has been emptied
247                 $labels                 = $profileFields->column('label');
248                 $prunedProfileFieldsOld = $profileFieldsOld->filter(function (Entity\ProfileField $profileFieldOld) use ($labels) {
249                         return array_search($profileFieldOld->label, $labels) === false;
250                 });
251                 $this->deleteCollection($prunedProfileFieldsOld);
252
253                 // Update the order based on the new Profile Field Collection
254                 $order                 = 0;
255                 $labelProfileFieldsOld = array_flip($profileFieldsOld->column('label'));
256
257                 foreach ($profileFields as $profileField) {
258                         // Update existing field (preserve
259                         if (array_key_exists($profileField->label, $labelProfileFieldsOld)) {
260                                 $profileFieldOldId = $labelProfileFieldsOld[$profileField->label];
261                                 /** @var Entity\ProfileField $foundProfileFieldOld */
262                                 $foundProfileFieldOld = $profileFieldsOld[$profileFieldOldId];
263                                 $foundProfileFieldOld->update(
264                                         $profileField->value,
265                                         $order,
266                                         $profileField->permissionSet
267                                 );
268
269                                 $savedProfileFields->append($this->save($foundProfileFieldOld));
270                         } else {
271                                 $profileField->setOrder($order);
272                                 $savedProfileFields->append($this->save($profileField));
273                         }
274
275                         $order++;
276                 }
277
278                 return $savedProfileFields;
279         }
280 }