]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/ExtendedProfile/actions/profiledetailsettings.php
Merge branch 'strict-warnings' into 'nightly'
[quix0rs-gnu-social.git] / plugins / ExtendedProfile / actions / profiledetailsettings.php
1 <?php
2 /*
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2011, StatusNet, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 if (!defined('GNUSOCIAL')) { exit(1); }
21
22 class ProfileDetailSettingsAction extends ProfileSettingsAction
23 {
24     function title()
25     {
26         // TRANS: Title for extended profile settings.
27         return _m('Extended profile settings');
28     }
29
30     function showStylesheets() {
31         parent::showStylesheets();
32         $this->cssLink('plugins/ExtendedProfile/css/profiledetail.css');
33         return true;
34     }
35
36     function  showScripts() {
37         parent::showScripts();
38         $this->script('plugins/ExtendedProfile/js/profiledetail.js');
39         return true;
40     }
41
42     protected function doPost()
43     {
44         if ($this->arg('save')) {
45             return $this->saveDetails();
46         }
47
48         // TRANS: Message given submitting a form with an unknown action.
49         throw new ClientException(_m('Unexpected form submission.'));
50     }
51
52     function showContent()
53     {
54         $widget = new ExtendedProfileWidget(
55             $this,
56             $this->scoped,
57             ExtendedProfileWidget::EDITABLE
58         );
59         $widget->show();
60     }
61
62     function saveDetails()
63     {
64         common_debug(var_export($_POST, true));
65
66         $this->saveStandardProfileDetails();
67
68         $simpleFieldNames = array('title', 'spouse', 'kids', 'manager');
69         $dateFieldNames   = array('birthday');
70
71         foreach ($simpleFieldNames as $name) {
72             $value = $this->trimmed('extprofile-' . $name);
73             if (!empty($value)) {
74                 $this->saveField($name, $value);
75             }
76         }
77
78         foreach ($dateFieldNames as $name) {
79             $value = $this->trimmed('extprofile-' . $name);
80             $dateVal = $this->parseDate($name, $value);
81             $this->saveField(
82                 $name,
83                 null,
84                 null,
85                 null,
86                 $dateVal
87             );
88         }
89
90         $this->savePhoneNumbers();
91         $this->saveIms();
92         $this->saveWebsites();
93         $this->saveExperiences();
94         $this->saveEducations();
95
96         // TRANS: Success message after saving extended profile details.
97         return _m('Details saved.');
98
99     }
100
101     function parseDate($fieldname, $datestr, $required = false)
102     {
103         if (empty($datestr)) {
104             if ($required) {
105                 $msg = sprintf(
106                     // TRANS: Exception thrown when no date was entered in a required date field.
107                     // TRANS: %s is the field name.
108                     _m('You must supply a date for "%s".'),
109                     $fieldname
110                 );
111                 throw new Exception($msg);
112             }
113         } else {
114             $ts = strtotime($datestr);
115             if ($ts === false) {
116                 throw new Exception(
117                     sprintf(
118                         // TRANS: Exception thrown on incorrect data input.
119                         // TRANS: %1$s is a field name, %2$s is the incorrect input.
120                         _m('Invalid date entered for "%1$s": %2$s.'),
121                         $fieldname,
122                         $ts
123                     )
124                 );
125             }
126             return common_sql_date($ts);
127         }
128         return null;
129     }
130
131     function savePhoneNumbers() {
132         $phones = $this->findPhoneNumbers();
133         $this->removeAll('phone');
134         $i = 0;
135         foreach($phones as $phone) {
136             if (!empty($phone['value'])) {
137                 ++$i;
138                 $this->saveField(
139                     'phone',
140                     $phone['value'],
141                     $phone['rel'],
142                     $i
143                 );
144             }
145         }
146     }
147
148     function findPhoneNumbers() {
149
150         // Form vals look like this:
151         // 'extprofile-phone-1' => '11332',
152         // 'extprofile-phone-1-rel' => 'mobile',
153
154         $phones     = $this->sliceParams('phone', 2);
155         $phoneArray = array();
156
157         foreach ($phones as $phone) {
158             list($number, $rel) = array_values($phone);
159             $phoneArray[] = array(
160                 'value' => $number,
161                 'rel'   => $rel
162             );
163         }
164
165         return $phoneArray;
166     }
167
168     function findIms() {
169
170         //  Form vals look like this:
171         // 'extprofile-im-0' => 'jed',
172         // 'extprofile-im-0-rel' => 'yahoo',
173
174         $ims     = $this->sliceParams('im', 2);
175         $imArray = array();
176
177         foreach ($ims as $im) {
178             list($id, $rel) = array_values($im);
179             $imArray[] = array(
180                 'value' => $id,
181                 'rel'   => $rel
182             );
183         }
184
185         return $imArray;
186     }
187
188     function saveIms() {
189         $ims = $this->findIms();
190         $this->removeAll('im');
191         $i = 0;
192         foreach($ims as $im) {
193             if (!empty($im['value'])) {
194                 ++$i;
195                 $this->saveField(
196                     'im',
197                     $im['value'],
198                     $im['rel'],
199                     $i
200                 );
201             }
202         }
203     }
204
205     function findWebsites() {
206
207         //  Form vals look like this:
208
209         $sites = $this->sliceParams('website', 2);
210         $wsArray = array();
211
212         foreach ($sites as $site) {
213             list($id, $rel) = array_values($site);
214             $wsArray[] = array(
215                 'value' => $id,
216                 'rel'   => $rel
217             );
218         }
219
220         return $wsArray;
221     }
222
223     function saveWebsites() {
224         $sites = $this->findWebsites();
225         $this->removeAll('website');
226         $i = 0;
227         foreach($sites as $site) {
228             if (!empty($site['value']) && !common_valid_http_url($site['value'])) {
229                 // TRANS: Exception thrown when entering an invalid URL.
230                 // TRANS: %s is the invalid URL.
231                 throw new Exception(sprintf(_m('Invalid URL: %s.'), $site['value']));
232             }
233
234             if (!empty($site['value'])) {
235                 ++$i;
236                 $this->saveField(
237                     'website',
238                     $site['value'],
239                     $site['rel'],
240                     $i
241                 );
242             }
243         }
244     }
245
246     function findExperiences() {
247
248         // Form vals look like this:
249         // 'extprofile-experience-0'         => 'Bozotronix',
250         // 'extprofile-experience-0-current' => 'true'
251         // 'extprofile-experience-0-start'   => '1/5/10',
252         // 'extprofile-experience-0-end'     => '2/3/11',
253
254         $experiences = $this->sliceParams('experience', 4);
255         $expArray = array();
256
257         foreach ($experiences as $exp) {
258             if (sizeof($experiences) == 4) {
259                 list($company, $current, $end, $start) = array_values($exp);
260             } else {
261                 $end = null;
262                 list($company, $current, $start) = array_values($exp);
263             }
264             if (!empty($company)) {
265                 $expArray[] = array(
266                     'company' => $company,
267                     'start'   => $this->parseDate('Start', $start, true),
268                     'end'     => ($current == 'false') ? $this->parseDate('End', $end, true) : null,
269                     'current' => ($current == 'false') ? false : true
270                 );
271             }
272         }
273
274         return $expArray;
275     }
276
277     function saveExperiences() {
278         common_debug('save experiences');
279         $experiences = $this->findExperiences();
280
281         $this->removeAll('company');
282         $this->removeAll('start');
283         $this->removeAll('end'); // also stores 'current'
284
285         $i = 0;
286         foreach($experiences as $experience) {
287             if (!empty($experience['company'])) {
288                 ++$i;
289                 $this->saveField(
290                     'company',
291                     $experience['company'],
292                     null,
293                     $i
294                 );
295
296                 $this->saveField(
297                     'start',
298                     null,
299                     null,
300                     $i,
301                     $experience['start']
302                 );
303
304                 // Save "current" employer indicator in rel
305                 if ($experience['current']) {
306                     $this->saveField(
307                         'end',
308                         null,
309                         'current', // rel
310                         $i
311                     );
312                 } else {
313                     $this->saveField(
314                         'end',
315                         null,
316                         null,
317                         $i,
318                         $experience['end']
319                     );
320                 }
321
322             }
323         }
324     }
325
326     function findEducations() {
327
328         // Form vals look like this:
329         // 'extprofile-education-0-school' => 'Pigdog',
330         // 'extprofile-education-0-degree' => 'BA',
331         // 'extprofile-education-0-description' => 'Blar',
332         // 'extprofile-education-0-start' => '05/22/99',
333         // 'extprofile-education-0-end' => '05/22/05',
334
335         $edus = $this->sliceParams('education', 5);
336         $eduArray = array();
337
338         foreach ($edus as $edu) {
339             list($school, $degree, $description, $end, $start) = array_values($edu);
340             if (!empty($school)) {
341                 $eduArray[] = array(
342                     'school'      => $school,
343                     'degree'      => $degree,
344                     'description' => $description,
345                     'start'       => $this->parseDate('Start', $start, true),
346                     'end'         => $this->parseDate('End', $end, true)
347                 );
348             }
349         }
350
351         return $eduArray;
352     }
353
354
355     function saveEducations() {
356          common_debug('save education');
357          $edus = $this->findEducations();
358          common_debug(var_export($edus, true));
359
360          $this->removeAll('school');
361          $this->removeAll('degree');
362          $this->removeAll('degree_descr');
363          $this->removeAll('school_start');
364          $this->removeAll('school_end');
365
366          $i = 0;
367          foreach($edus as $edu) {
368              if (!empty($edu['school'])) {
369                  ++$i;
370                  $this->saveField(
371                      'school',
372                      $edu['school'],
373                      null,
374                      $i
375                  );
376                  $this->saveField(
377                      'degree',
378                      $edu['degree'],
379                      null,
380                      $i
381                  );
382                  $this->saveField(
383                      'degree_descr',
384                      $edu['description'],
385                      null,
386                      $i
387                  );
388                  $this->saveField(
389                      'school_start',
390                      null,
391                      null,
392                      $i,
393                      $edu['start']
394                  );
395
396                  $this->saveField(
397                      'school_end',
398                      null,
399                      null,
400                      $i,
401                      $edu['end']
402                  );
403             }
404          }
405      }
406
407     function arraySplit($array, $pieces)
408     {
409         if ($pieces < 2) {
410             return array($array);
411         }
412
413         $newCount = ceil(count($array) / $pieces);
414         $a = array_slice($array, 0, $newCount);
415         $b = $this->arraySplit(array_slice($array, $newCount), $pieces - 1);
416
417         return array_merge(array($a), $b);
418     }
419
420     function findMultiParams($type) {
421         $formVals = array();
422         $target   = $type;
423         foreach ($_POST as $key => $val) {
424             if (strrpos('extprofile-' . $key, $target) !== false) {
425                 $formVals[$key] = $val;
426             }
427         }
428         return $formVals;
429     }
430
431     function sliceParams($key, $size) {
432         $slice = array();
433         $params = $this->findMultiParams($key);
434         ksort($params);
435         $slice = $this->arraySplit($params, sizeof($params) / $size);
436         return $slice;
437     }
438
439     /**
440      * Save an extended profile field as a Profile_detail
441      *
442      * @param string $name    field name
443      * @param string $value   field value
444      * @param string $rel     field rel (type)
445      * @param int    $index   index (fields can have multiple values)
446      * @param date   $date    related date
447      */
448     function saveField($name, $value, $rel = null, $index = null, $date = null)
449     {
450         $detail  = new Profile_detail();
451
452         $detail->profile_id  = $this->scoped->getID();
453         $detail->field_name  = $name;
454         $detail->value_index = $index;
455
456         $result = $detail->find(true);
457
458         if (!$result instanceof Profile_detail) {
459             $detail->value_index = $index;
460             $detail->rel         = $rel;
461             $detail->field_value = $value;
462             $detail->date        = $date;
463             $detail->created     = common_sql_now();
464             $result = $detail->insert();
465             if ($result === false) {
466                 common_log_db_error($detail, 'INSERT', __FILE__);
467                 // TRANS: Server error displayed when a field could not be saved in the database.
468                 throw new ServerException(_m('Could not save profile details.'));
469             }
470         } else {
471             $orig = clone($detail);
472
473             $detail->field_value = $value;
474             $detail->rel         = $rel;
475             $detail->date        = $date;
476
477             $result = $detail->update($orig);
478             if ($result === false) {
479                 common_log_db_error($detail, 'UPDATE', __FILE__);
480                 // TRANS: Server error displayed when a field could not be saved in the database.
481                 throw new ServerException(_m('Could not save profile details.'));
482             }
483         }
484
485         $detail->free();
486     }
487
488     function removeAll($name)
489     {
490         $detail  = new Profile_detail();
491         $detail->profile_id  = $this->scoped->getID();
492         $detail->field_name  = $name;
493         $detail->delete();
494         $detail->free();
495     }
496
497     /**
498      * Save fields that should be stored in the main profile object
499      *
500      * XXX: There's a lot of dupe code here from ProfileSettingsAction.
501      *      Do not want.
502      */
503     function saveStandardProfileDetails()
504     {
505         $fullname  = $this->trimmed('extprofile-fullname');
506         $location  = $this->trimmed('extprofile-location');
507         $tagstring = $this->trimmed('extprofile-tags');
508         $bio       = $this->trimmed('extprofile-bio');
509
510         if ($tagstring) {
511             $tags = array_map(
512                 'common_canonical_tag',
513                 preg_split('/[\s,]+/', $tagstring)
514             );
515         } else {
516             $tags = array();
517         }
518
519         foreach ($tags as $tag) {
520             if (!common_valid_profile_tag($tag)) {
521                 // TRANS: Validation error in form for profile settings.
522                 // TRANS: %s is an invalid tag.
523                 throw new Exception(sprintf(_m('Invalid tag: "%s".'), $tag));
524             }
525         }
526
527         $oldTags = Profile_tag::getSelfTagsArray($this->scoped);
528         $newTags = array_diff($tags, $oldTags);
529
530         if ($fullname    != $this->scoped->getFullname()
531             || $location != $this->scoped->location
532             || !empty($newTags)
533             || $bio      != $this->scoped->getDescription()) {
534
535             $orig = clone($this->scoped);
536
537             // Skipping nickname change here until we add logic for when the site allows it or not
538             // old Profilesettings will still let us do that.
539
540             $this->scoped->fullname = $fullname;
541             $this->scoped->bio      = $bio;
542             $this->scoped->location = $location;
543
544             $loc = Location::fromName($location);
545
546             if (empty($loc)) {
547                 $this->scoped->lat         = null;
548                 $this->scoped->lon         = null;
549                 $this->scoped->location_id = null;
550                 $this->scoped->location_ns = null;
551             } else {
552                 $this->scoped->lat         = $loc->lat;
553                 $this->scoped->lon         = $loc->lon;
554                 $this->scoped->location_id = $loc->location_id;
555                 $this->scoped->location_ns = $loc->location_ns;
556             }
557
558             $result = $this->scoped->update($orig);
559
560             if ($result === false) {
561                 common_log_db_error($this->scoped, 'UPDATE', __FILE__);
562                 // TRANS: Server error thrown when user profile settings could not be saved.
563                 throw new ServerException(_m('Could not save profile.'));
564             }
565
566             // Set the user tags
567             $result = Profile_tag::setSelfTags($this->scoped, $tags);
568
569             Event::handle('EndProfileSaveForm', array($this));
570         }
571     }
572
573 }