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