]> git.mxchange.org Git - friendica.git/blob - src/Repository/ProfileField.php
replace "p" with higher level database functions
[friendica.git] / src / Repository / ProfileField.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, 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\Repository;
23
24 use Friendica\BaseModel;
25 use Friendica\BaseRepository;
26 use Friendica\Collection;
27 use Friendica\Core\L10n;
28 use Friendica\Database\Database;
29 use Friendica\Database\DBA;
30 use Friendica\Model;
31 use Friendica\Security\PermissionSet\Depository\PermissionSet;
32 use Friendica\Util\DateTimeFormat;
33 use Psr\Log\LoggerInterface;
34
35 class ProfileField extends BaseRepository
36 {
37         protected static $table_name = 'profile_field';
38
39         protected static $model_class = Model\ProfileField::class;
40
41         protected static $collection_class = Collection\ProfileFields::class;
42
43         /** @var PermissionSet */
44         private $permissionSet;
45         /** @var \Friendica\Security\PermissionSet\Factory\PermissionSet */
46         private $permissionSetFactory;
47         /** @var L10n */
48         private $l10n;
49
50         public function __construct(Database $dba, LoggerInterface $logger, PermissionSet $permissionSet, \Friendica\Security\PermissionSet\Factory\PermissionSet $permissionSetFactory, L10n $l10n)
51         {
52                 parent::__construct($dba, $logger);
53
54                 $this->permissionSet        = $permissionSet;
55                 $this->permissionSetFactory = $permissionSetFactory;
56                 $this->l10n                 = $l10n;
57         }
58
59         /**
60          * @param array $data
61          * @return Model\ProfileField
62          */
63         protected function create(array $data)
64         {
65                 return new Model\ProfileField($this->dba, $this->logger, $this->permissionSet, $data);
66         }
67
68         /**
69          * @param array $condition
70          * @return Model\ProfileField
71          * @throws \Friendica\Network\HTTPException\NotFoundException
72          */
73         public function selectFirst(array $condition)
74         {
75                 return parent::selectFirst($condition);
76         }
77
78         /**
79          * @param array $condition
80          * @param array $params
81          * @return Collection\ProfileFields
82          * @throws \Exception
83          */
84         public function select(array $condition = [], array $params = [])
85         {
86                 return parent::select($condition, $params);
87         }
88
89         /**
90          * @param array    $condition
91          * @param array    $params
92          * @param int|null $min_id
93          * @param int|null $max_id
94          * @param int      $limit
95          * @return Collection\ProfileFields
96          * @throws \Exception
97          */
98         public function selectByBoundaries(array $condition = [], array $params = [], int $min_id = null, int $max_id = null, int $limit = self::LIMIT)
99         {
100                 return parent::selectByBoundaries($condition, $params, $min_id, $max_id, $limit);
101         }
102
103         /**
104          * @param int $uid Field owner user Id
105          * @return Collection\ProfileFields
106          * @throws \Exception
107          */
108         public function selectByUserId(int $uid)
109         {
110                 return $this->select(
111                         ['uid' => $uid],
112                         ['order' => ['order']]
113                 );
114         }
115
116         /**
117          * Retrieve all custom profile field a given contact is able to access to, including public profile fields.
118          *
119          * @param int $cid Private contact id, must be owned by $uid
120          * @param int $uid Field owner user id
121          * @return Collection\ProfileFields
122          * @throws \Exception
123          */
124         public function selectByContactId(int $cid, int $uid)
125         {
126                 $permissionSets = $this->permissionSet->selectByContactId($cid, $uid);
127
128                 $psids = $permissionSets->column('id');
129
130                 // Includes public custom fields
131                 $psids[] = 0;
132
133                 return $this->select(
134                         ['uid' => $uid, 'psid' => $psids],
135                         ['order' => ['order']]
136                 );
137         }
138
139         /**
140          * @param array $fields
141          * @return Model\ProfileField|bool
142          * @throws \Exception
143          */
144         public function insert(array $fields)
145         {
146                 $fields['created'] = DateTimeFormat::utcNow();
147                 $fields['edited']  = DateTimeFormat::utcNow();
148
149                 return parent::insert($fields);
150         }
151
152         /**
153          * @param Model\ProfileField $model
154          * @return bool
155          * @throws \Exception
156          */
157         public function update(BaseModel $model)
158         {
159                 $model->edited = DateTimeFormat::utcNow();
160
161                 return parent::update($model);
162         }
163
164         /**
165          * @param int                      $uid                User Id
166          * @param Collection\ProfileFields $profileFields      Collection of existing profile fields
167          * @param array                    $profileFieldInputs Array of profile field form inputs indexed by profile field id
168          * @param array                    $profileFieldOrder  List of profile field id in order
169          * @return Collection\ProfileFields
170          * @throws \Exception
171          */
172         public function updateCollectionFromForm(int $uid, Collection\ProfileFields $profileFields, array $profileFieldInputs, array $profileFieldOrder)
173         {
174                 // Returns an associative array of id => order values
175                 $profileFieldOrder = array_flip($profileFieldOrder);
176
177                 // Creation of the new field
178                 if (!empty($profileFieldInputs['new']['label'])) {
179                         $psid = $this->permissionSet->selectOrCreate($this->permissionSetFactory->createFromString(
180                                 $uid,
181                                 $profileFieldInputs['new']['contact_allow'] ?? '',
182                                 $profileFieldInputs['new']['group_allow'] ?? '',
183                                 $profileFieldInputs['new']['contact_deny'] ?? '',
184                                 $profileFieldInputs['new']['group_deny'] ?? ''
185                         ))->id;
186
187                         $newProfileField = $this->insert([
188                                 'uid'   => $uid,
189                                 'label' => $profileFieldInputs['new']['label'],
190                                 'value' => $profileFieldInputs['new']['value'],
191                                 'psid'  => $psid,
192                                 'order' => $profileFieldOrder['new'],
193                         ]);
194
195                         $profileFieldInputs[$newProfileField->id] = $profileFieldInputs['new'];
196                         $profileFieldOrder[$newProfileField->id]  = $profileFieldOrder['new'];
197
198                         $profileFields[] = $newProfileField;
199                 }
200
201                 unset($profileFieldInputs['new']);
202                 unset($profileFieldOrder['new']);
203
204                 // Prunes profile field whose label has been emptied
205                 $profileFields = $profileFields->filter(function (Model\ProfileField $profileField) use (&$profileFieldInputs, &$profileFieldOrder) {
206                         $keepModel = !isset($profileFieldInputs[$profileField->id]) || !empty($profileFieldInputs[$profileField->id]['label']);
207
208                         if (!$keepModel) {
209                                 unset($profileFieldInputs[$profileField->id]);
210                                 unset($profileFieldOrder[$profileField->id]);
211                                 $this->delete($profileField);
212                         }
213
214                         return $keepModel;
215                 });
216
217                 // Regenerates the order values if items were deleted
218                 $profileFieldOrder = array_flip(array_keys($profileFieldOrder));
219
220                 // Update existing profile fields from form values
221                 $profileFields = $profileFields->map(function (Model\ProfileField $profileField) use ($uid, &$profileFieldInputs, &$profileFieldOrder) {
222                         if (isset($profileFieldInputs[$profileField->id]) && isset($profileFieldOrder[$profileField->id])) {
223                                 $psid = $this->permissionSet->selectOrCreate($this->permissionSetFactory->createFromString(
224                                         $uid,
225                                         $profileFieldInputs[$profileField->id]['contact_allow'] ?? '',
226                                         $profileFieldInputs[$profileField->id]['group_allow'] ?? '',
227                                         $profileFieldInputs[$profileField->id]['contact_deny'] ?? '',
228                                         $profileFieldInputs[$profileField->id]['group_deny'] ?? ''
229                                 ))->id;
230
231                                 $profileField->psid = $psid;
232                                 $profileField->label = $profileFieldInputs[$profileField->id]['label'];
233                                 $profileField->value = $profileFieldInputs[$profileField->id]['value'];
234                                 $profileField->order = $profileFieldOrder[$profileField->id];
235
236                                 unset($profileFieldInputs[$profileField->id]);
237                                 unset($profileFieldOrder[$profileField->id]);
238                         }
239
240                         return $profileField;
241                 });
242
243                 return $profileFields;
244         }
245
246         /**
247          * Migrates a legacy profile to the new slimmer profile with extra custom fields.
248          * Multi profiles are converted to ACl-protected custom fields and deleted.
249          *
250          * @param array $profile Profile table row
251          * @throws \Exception
252          */
253         public function migrateFromLegacyProfile(array $profile)
254         {
255                 // Already processed, aborting
256                 if ($profile['is-default'] === null) {
257                         return;
258                 }
259
260                 $contacts = [];
261
262                 if (!$profile['is-default']) {
263                         $contacts = Model\Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'profile-id' => $profile['id']]);
264                         if (!count($contacts)) {
265                                 // No contact visibility selected defaults to user-only permission
266                                 $contacts = Model\Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'self' => true]);
267                         }
268                 }
269
270                 $psid = $this->permissionSet->selectOrCreate(
271                         new \Friendica\Security\PermissionSet\Entity\PermissionSet(
272                                 $profile['uid'],
273                                 array_column($contacts, 'id') ?? []
274                         )
275                 )->id;
276
277                 $order = 1;
278
279                 $custom_fields = [
280                         'hometown'  => $this->l10n->t('Hometown:'),
281                         'marital'   => $this->l10n->t('Marital Status:'),
282                         'with'      => $this->l10n->t('With:'),
283                         'howlong'   => $this->l10n->t('Since:'),
284                         'sexual'    => $this->l10n->t('Sexual Preference:'),
285                         'politic'   => $this->l10n->t('Political Views:'),
286                         'religion'  => $this->l10n->t('Religious Views:'),
287                         'likes'     => $this->l10n->t('Likes:'),
288                         'dislikes'  => $this->l10n->t('Dislikes:'),
289                         'pdesc'     => $this->l10n->t('Title/Description:'),
290                         'summary'   => $this->l10n->t('Summary'),
291                         'music'     => $this->l10n->t('Musical interests'),
292                         'book'      => $this->l10n->t('Books, literature'),
293                         'tv'        => $this->l10n->t('Television'),
294                         'film'      => $this->l10n->t('Film/dance/culture/entertainment'),
295                         'interest'  => $this->l10n->t('Hobbies/Interests'),
296                         'romance'   => $this->l10n->t('Love/romance'),
297                         'work'      => $this->l10n->t('Work/employment'),
298                         'education' => $this->l10n->t('School/education'),
299                         'contact'   => $this->l10n->t('Contact information and Social Networks'),
300                 ];
301
302                 foreach ($custom_fields as $field => $label) {
303                         if (!empty($profile[$field]) && $profile[$field] > DBA::NULL_DATE && $profile[$field] > DBA::NULL_DATETIME) {
304                                 $this->insert([
305                                         'uid'   => $profile['uid'],
306                                         'psid'  => $psid,
307                                         'order' => $order++,
308                                         'label' => trim($label, ':'),
309                                         'value' => $profile[$field],
310                                 ]);
311                         }
312
313                         $profile[$field] = null;
314                 }
315
316                 if ($profile['is-default']) {
317                         $profile['profile-name'] = null;
318                         $profile['is-default']   = null;
319                         $this->dba->update('profile', $profile, ['id' => $profile['id']]);
320                 } elseif (!empty($profile['id'])) {
321                         $this->dba->delete('profile', ['id' => $profile['id']]);
322                 }
323         }
324 }