]> git.mxchange.org Git - friendica.git/blob - src/Repository/ProfileField.php
Rework profile setting page with custom fields
[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\DI;
10 use Friendica\Model;
11 use Friendica\Util\DateTimeFormat;
12 use Psr\Log\LoggerInterface;
13
14 class ProfileField extends BaseRepository
15 {
16         protected static $table_name = 'profile_field';
17
18         protected static $model_class = Model\ProfileField::class;
19
20         protected static $collection_class = Collection\ProfileFields::class;
21
22         /** @var PermissionSet */
23         private $permissionSet;
24
25         public function __construct(Database $dba, LoggerInterface $logger, PermissionSet $permissionSet)
26         {
27                 parent::__construct($dba, $logger);
28
29                 $this->permissionSet = $permissionSet;
30         }
31
32         /**
33          * @param array $data
34          * @return Model\ProfileField
35          */
36         protected function create(array $data)
37         {
38                 return new Model\ProfileField($this->dba, $this->logger, $this->permissionSet, $data);
39         }
40
41         /**
42          * @param array $condition
43          * @return Model\ProfileField
44          * @throws \Friendica\Network\HTTPException\NotFoundException
45          */
46         public function selectFirst(array $condition)
47         {
48                 return parent::selectFirst($condition);
49         }
50
51         /**
52          * @param array $condition
53          * @param array $params
54          * @return Collection\ProfileFields
55          * @throws \Exception
56          */
57         public function select(array $condition = [], array $params = [])
58         {
59                 return parent::select($condition, $params);
60         }
61
62         /**
63          * @param array $condition
64          * @param array $params
65          * @param int|null $max_id
66          * @param int|null $since_id
67          * @param int $limit
68          * @return Collection\ProfileFields
69          * @throws \Exception
70          */
71         public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT)
72         {
73                 return parent::selectByBoundaries($condition, $params, $max_id, $since_id, $limit);
74         }
75
76         /**
77          * @param int $uid Field owner user Id
78          * @return Collection\ProfileFields
79          * @throws \Exception
80          */
81         public function selectByUserId(int $uid)
82         {
83                 return $this->select(
84                         ['uid' => $uid],
85                         ['order' => ['order']]
86                 );
87         }
88
89         /**
90          * Retrieve all custom profile field a given contact is able to access to, including public profile fields.
91          *
92          * @param int $cid Private contact id, must be owned by $uid
93          * @param int $uid Field owner user id
94          * @return Collection\ProfileFields
95          * @throws \Exception
96          */
97         public function selectByContactId(int $cid, int $uid)
98         {
99                 $permissionSets = $this->permissionSet->selectByContactId($cid, $uid);
100
101                 $psids = $permissionSets->column('id');
102
103                 // Includes public custom fields
104                 $psids[] = 0;
105
106                 return $this->select(
107                         ['uid' => $uid, 'psid' => $psids],
108                         ['order' => ['order']]
109                 );
110         }
111
112         /**
113          * @param array $fields
114          * @return Model\ProfileField|bool
115          * @throws \Exception
116          */
117         public function insert(array $fields)
118         {
119                 $fields['created'] = DateTimeFormat::utcNow();
120                 $fields['edited']  = DateTimeFormat::utcNow();
121
122                 return parent::insert($fields);
123         }
124
125         /**
126          * @param Model\ProfileField $model
127          * @return bool
128          * @throws \Exception
129          */
130         public function update(BaseModel $model)
131         {
132                 $model->edited = DateTimeFormat::utcNow();
133
134                 return parent::update($model);
135         }
136         
137         /**
138          * @param int                      $uid                User Id
139          * @param Collection\ProfileFields $profileFields      Collection of existing profile fields
140          * @param array                    $profileFieldInputs Array of profile field form inputs indexed by profile field id
141          * @param array                    $profileFieldOrder  List of profile field id in order
142          * @return Collection\ProfileFields
143          * @throws \Exception
144          */
145         public function updateCollectionFromForm(int $uid, Collection\ProfileFields $profileFields, array $profileFieldInputs, array $profileFieldOrder)
146         {
147                 $aclFormatter = DI::aclFormatter();
148
149                 // Returns an associative array of id => order values
150                 $profileFieldOrder = array_flip($profileFieldOrder);
151
152                 // Creation of the new field
153                 if (!empty($profileFieldInputs['new']['label'])) {
154                         $psid = $this->permissionSet->getIdFromACL(
155                                 $uid,
156                                 $aclFormatter->toString($profileFieldInputs['new']['contact_allow'] ?? ''),
157                                 $aclFormatter->toString($profileFieldInputs['new']['group_allow'] ?? ''),
158                                 $aclFormatter->toString($profileFieldInputs['new']['contact_deny'] ?? ''),
159                                 $aclFormatter->toString($profileFieldInputs['new']['group_deny'] ?? '')
160                         );
161
162                         $newProfileField = $this->insert([
163                                 'uid' => $uid,
164                                 'label' => $profileFieldInputs['new']['label'],
165                                 'value' => $profileFieldInputs['new']['value'],
166                                 'psid' => $psid,
167                                 'order' => $profileFieldOrder['new'],
168                         ]);
169
170                         $profileFieldInputs[$newProfileField->id] = $profileFieldInputs['new'];
171                         $profileFieldOrder[$newProfileField->id] = $profileFieldOrder['new'];
172
173                         $profileFields[] = $newProfileField;
174                 }
175
176                 unset($profileFieldInputs['new']);
177                 unset($profileFieldOrder['new']);
178
179                 // Prunes profile field whose label has been emptied
180                 $profileFields = $profileFields->filter(function (Model\ProfileField $profileField) use (&$profileFieldInputs, &$profileFieldOrder) {
181                         $keepModel = !isset($profileFieldInputs[$profileField->id]) || !empty($profileFieldInputs[$profileField->id]['label']);
182
183                         if (!$keepModel) {
184                                 unset($profileFieldInputs[$profileField->id]);
185                                 unset($profileFieldOrder[$profileField->id]);
186                                 $this->delete($profileField);
187                         }
188
189                         return $keepModel;
190                 });
191
192                 // Regenerates the order values if items were deleted
193                 $profileFieldOrder = array_flip(array_keys($profileFieldOrder));
194
195                 // Update existing profile fields from form values
196                 $profileFields = $profileFields->map(function (Model\ProfileField $profileField) use ($uid, $aclFormatter, &$profileFieldInputs, &$profileFieldOrder) {
197                         if (isset($profileFieldInputs[$profileField->id]) && isset($profileFieldOrder[$profileField->id])) {
198                                 $psid = $this->permissionSet->getIdFromACL(
199                                         $uid,
200                                         $aclFormatter->toString($profileFieldInputs[$profileField->id]['contact_allow'] ?? ''),
201                                         $aclFormatter->toString($profileFieldInputs[$profileField->id]['group_allow'] ?? ''),
202                                         $aclFormatter->toString($profileFieldInputs[$profileField->id]['contact_deny'] ?? ''),
203                                         $aclFormatter->toString($profileFieldInputs[$profileField->id]['group_deny'] ?? '')
204                                 );
205
206                                 $profileField->psid  = $psid;
207                                 $profileField->label = $profileFieldInputs[$profileField->id]['label'];
208                                 $profileField->value = $profileFieldInputs[$profileField->id]['value'];
209                                 $profileField->order = $profileFieldOrder[$profileField->id];
210
211                                 unset($profileFieldInputs[$profileField->id]);
212                                 unset($profileFieldOrder[$profileField->id]);
213                         }
214
215                         return $profileField;
216                 });
217
218                 return $profileFields;
219         }
220 }