]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/ExtendedProfile/actions/profiledetailsettings.php
Validate::uri replaced with filter_var for HTTP[S] URL checks
[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('STATUSNET')) {
21     exit(1);
22 }
23
24 class ProfileDetailSettingsAction extends ProfileSettingsAction
25 {
26     function title()
27     {
28         // TRANS: Title for extended profile settings.
29         return _m('Extended profile settings');
30     }
31
32     /**
33      * Instructions for use
34      *
35      * @return instructions for use
36      */
37     function getInstructions()
38     {
39         // TRANS: Usage instructions for profile settings.
40         return _m('You can update your personal profile info here '.
41                  'so people know more about you.');
42     }
43
44     function showStylesheets() {
45         parent::showStylesheets();
46         $this->cssLink('plugins/ExtendedProfile/css/profiledetail.css');
47         return true;
48     }
49
50     function  showScripts() {
51         parent::showScripts();
52         $this->script('plugins/ExtendedProfile/js/profiledetail.js');
53         return true;
54     }
55
56     function handlePost()
57     {
58         // CSRF protection
59         $token = $this->trimmed('token');
60         if (!$token || $token != common_session_token()) {
61             $this->showForm(
62                 // TRANS: Client error displayed when the session token does not match or is not given.
63                 _m('There was a problem with your session token. '
64                     .   'Try again, please.'
65                   )
66             );
67             return;
68         }
69
70         if ($this->arg('save')) {
71             $this->saveDetails();
72         } else {
73             // TRANS: Message given submitting a form with an unknown action.
74             $this->showForm(_m('Unexpected form submission.'));
75         }
76     }
77
78     function showContent()
79     {
80         $cur = common_current_user();
81         $profile = $cur->getProfile();
82
83         $widget = new ExtendedProfileWidget(
84             $this,
85             $profile,
86             ExtendedProfileWidget::EDITABLE
87         );
88         $widget->show();
89     }
90
91     function saveDetails()
92     {
93         common_debug(var_export($_POST, true));
94
95         $user = common_current_user();
96
97         try {
98             $this->saveStandardProfileDetails($user);
99
100             $profile = $user->getProfile();
101
102             $simpleFieldNames = array('title', 'spouse', 'kids', 'manager');
103             $dateFieldNames   = array('birthday');
104
105             foreach ($simpleFieldNames as $name) {
106                 $value = $this->trimmed('extprofile-' . $name);
107                 if (!empty($value)) {
108                     $this->saveField($user, $name, $value);
109                 }
110             }
111
112             foreach ($dateFieldNames as $name) {
113                 $value = $this->trimmed('extprofile-' . $name);
114                 $dateVal = $this->parseDate($name, $value);
115                 $this->saveField(
116                     $user,
117                     $name,
118                     null,
119                     null,
120                     null,
121                     $dateVal
122                 );
123             }
124
125             $this->savePhoneNumbers($user);
126             $this->saveIms($user);
127             $this->saveWebsites($user);
128             $this->saveExperiences($user);
129             $this->saveEducations($user);
130
131         } catch (Exception $e) {
132             $this->showForm($e->getMessage(), false);
133             return;
134         }
135
136         // TRANS: Success message after saving extended profile details.
137         $this->showForm(_m('Details saved.'), true);
138
139     }
140
141     function parseDate($fieldname, $datestr, $required = false)
142     {
143         if (empty($datestr)) {
144             if ($required) {
145                 $msg = sprintf(
146                     // TRANS: Exception thrown when no date was entered in a required date field.
147                     // TRANS: %s is the field name.
148                     _m('You must supply a date for "%s".'),
149                     $fieldname
150                 );
151                 throw new Exception($msg);
152             }
153         } else {
154             $ts = strtotime($datestr);
155             if ($ts === false) {
156                 throw new Exception(
157                     sprintf(
158                         // TRANS: Exception thrown on incorrect data input.
159                         // TRANS: %1$s is a field name, %2$s is the incorrect input.
160                         _m('Invalid date entered for "%1$s": %2$s.'),
161                         $fieldname,
162                         $ts
163                     )
164                 );
165             }
166             return common_sql_date($ts);
167         }
168         return null;
169     }
170
171     function savePhoneNumbers($user) {
172         $phones = $this->findPhoneNumbers();
173         $this->removeAll($user, 'phone');
174         $i = 0;
175         foreach($phones as $phone) {
176             if (!empty($phone['value'])) {
177                 ++$i;
178                 $this->saveField(
179                     $user,
180                     'phone',
181                     $phone['value'],
182                     $phone['rel'],
183                     $i
184                 );
185             }
186         }
187     }
188
189     function findPhoneNumbers() {
190
191         // Form vals look like this:
192         // 'extprofile-phone-1' => '11332',
193         // 'extprofile-phone-1-rel' => 'mobile',
194
195         $phones     = $this->sliceParams('phone', 2);
196         $phoneArray = array();
197
198         foreach ($phones as $phone) {
199             list($number, $rel) = array_values($phone);
200             $phoneArray[] = array(
201                 'value' => $number,
202                 'rel'   => $rel
203             );
204         }
205
206         return $phoneArray;
207     }
208
209     function findIms() {
210
211         //  Form vals look like this:
212         // 'extprofile-im-0' => 'jed',
213         // 'extprofile-im-0-rel' => 'yahoo',
214
215         $ims     = $this->sliceParams('im', 2);
216         $imArray = array();
217
218         foreach ($ims as $im) {
219             list($id, $rel) = array_values($im);
220             $imArray[] = array(
221                 'value' => $id,
222                 'rel'   => $rel
223             );
224         }
225
226         return $imArray;
227     }
228
229     function saveIms($user) {
230         $ims = $this->findIms();
231         $this->removeAll($user, 'im');
232         $i = 0;
233         foreach($ims as $im) {
234             if (!empty($im['value'])) {
235                 ++$i;
236                 $this->saveField(
237                     $user,
238                     'im',
239                     $im['value'],
240                     $im['rel'],
241                     $i
242                 );
243             }
244         }
245     }
246
247     function findWebsites() {
248
249         //  Form vals look like this:
250
251         $sites = $this->sliceParams('website', 2);
252         $wsArray = array();
253
254         foreach ($sites as $site) {
255             list($id, $rel) = array_values($site);
256             $wsArray[] = array(
257                 'value' => $id,
258                 'rel'   => $rel
259             );
260         }
261
262         return $wsArray;
263     }
264
265     function saveWebsites($user) {
266         $sites = $this->findWebsites();
267         $this->removeAll($user, 'website');
268         $i = 0;
269         foreach($sites as $site) {
270             if (!empty($site['value']) && !common_valid_http_url($site['value'])) {
271                 // TRANS: Exception thrown when entering an invalid URL.
272                 // TRANS: %s is the invalid URL.
273                 throw new Exception(sprintf(_m('Invalid URL: %s.'), $site['value']));
274             }
275
276             if (!empty($site['value'])) {
277                 ++$i;
278                 $this->saveField(
279                     $user,
280                     'website',
281                     $site['value'],
282                     $site['rel'],
283                     $i
284                 );
285             }
286         }
287     }
288
289     function findExperiences() {
290
291         // Form vals look like this:
292         // 'extprofile-experience-0'         => 'Bozotronix',
293         // 'extprofile-experience-0-current' => 'true'
294         // 'extprofile-experience-0-start'   => '1/5/10',
295         // 'extprofile-experience-0-end'     => '2/3/11',
296
297         $experiences = $this->sliceParams('experience', 4);
298         $expArray = array();
299
300         foreach ($experiences as $exp) {
301             if (sizeof($experiences) == 4) {
302                 list($company, $current, $end, $start) = array_values($exp);
303             } else {
304                 $end = null;
305                 list($company, $current, $start) = array_values($exp);
306             }
307             if (!empty($company)) {
308                 $expArray[] = array(
309                     'company' => $company,
310                     'start'   => $this->parseDate('Start', $start, true),
311                     'end'     => ($current == 'false') ? $this->parseDate('End', $end, true) : null,
312                     'current' => ($current == 'false') ? false : true
313                 );
314             }
315         }
316
317         return $expArray;
318     }
319
320     function saveExperiences($user) {
321         common_debug('save experiences');
322         $experiences = $this->findExperiences();
323
324         $this->removeAll($user, 'company');
325         $this->removeAll($user, 'start');
326         $this->removeAll($user, 'end'); // also stores 'current'
327
328         $i = 0;
329         foreach($experiences as $experience) {
330             if (!empty($experience['company'])) {
331                 ++$i;
332                 $this->saveField(
333                     $user,
334                     'company',
335                     $experience['company'],
336                     null,
337                     $i
338                 );
339
340                 $this->saveField(
341                     $user,
342                     'start',
343                     null,
344                     null,
345                     $i,
346                     $experience['start']
347                 );
348
349                 // Save "current" employer indicator in rel
350                 if ($experience['current']) {
351                     $this->saveField(
352                         $user,
353                         'end',
354                         null,
355                         'current', // rel
356                         $i
357                     );
358                 } else {
359                     $this->saveField(
360                         $user,
361                         'end',
362                         null,
363                         null,
364                         $i,
365                         $experience['end']
366                     );
367                 }
368
369             }
370         }
371     }
372
373     function findEducations() {
374
375         // Form vals look like this:
376         // 'extprofile-education-0-school' => 'Pigdog',
377         // 'extprofile-education-0-degree' => 'BA',
378         // 'extprofile-education-0-description' => 'Blar',
379         // 'extprofile-education-0-start' => '05/22/99',
380         // 'extprofile-education-0-end' => '05/22/05',
381
382         $edus = $this->sliceParams('education', 5);
383         $eduArray = array();
384
385         foreach ($edus as $edu) {
386             list($school, $degree, $description, $end, $start) = array_values($edu);
387             if (!empty($school)) {
388                 $eduArray[] = array(
389                     'school'      => $school,
390                     'degree'      => $degree,
391                     'description' => $description,
392                     'start'       => $this->parseDate('Start', $start, true),
393                     'end'         => $this->parseDate('End', $end, true)
394                 );
395             }
396         }
397
398         return $eduArray;
399     }
400
401
402     function saveEducations($user) {
403          common_debug('save education');
404          $edus = $this->findEducations();
405          common_debug(var_export($edus, true));
406
407          $this->removeAll($user, 'school');
408          $this->removeAll($user, 'degree');
409          $this->removeAll($user, 'degree_descr');
410          $this->removeAll($user, 'school_start');
411          $this->removeAll($user, 'school_end');
412
413          $i = 0;
414          foreach($edus as $edu) {
415              if (!empty($edu['school'])) {
416                  ++$i;
417                  $this->saveField(
418                      $user,
419                      'school',
420                      $edu['school'],
421                      null,
422                      $i
423                  );
424                  $this->saveField(
425                      $user,
426                      'degree',
427                      $edu['degree'],
428                      null,
429                      $i
430                  );
431                  $this->saveField(
432                      $user,
433                      'degree_descr',
434                      $edu['description'],
435                      null,
436                      $i
437                  );
438                  $this->saveField(
439                      $user,
440                      'school_start',
441                      null,
442                      null,
443                      $i,
444                      $edu['start']
445                  );
446
447                  $this->saveField(
448                      $user,
449                      'school_end',
450                      null,
451                      null,
452                      $i,
453                      $edu['end']
454                  );
455             }
456          }
457      }
458
459     function arraySplit($array, $pieces)
460     {
461         if ($pieces < 2) {
462             return array($array);
463         }
464
465         $newCount = ceil(count($array) / $pieces);
466         $a = array_slice($array, 0, $newCount);
467         $b = $this->arraySplit(array_slice($array, $newCount), $pieces - 1);
468
469         return array_merge(array($a), $b);
470     }
471
472     function findMultiParams($type) {
473         $formVals = array();
474         $target   = $type;
475         foreach ($_POST as $key => $val) {
476             if (strrpos('extprofile-' . $key, $target) !== false) {
477                 $formVals[$key] = $val;
478             }
479         }
480         return $formVals;
481     }
482
483     function sliceParams($key, $size) {
484         $slice = array();
485         $params = $this->findMultiParams($key);
486         ksort($params);
487         $slice = $this->arraySplit($params, sizeof($params) / $size);
488         return $slice;
489     }
490
491     /**
492      * Save an extended profile field as a Profile_detail
493      *
494      * @param User   $user    the current user
495      * @param string $name    field name
496      * @param string $value   field value
497      * @param string $rel     field rel (type)
498      * @param int    $index   index (fields can have multiple values)
499      * @param date   $date    related date
500      */
501     function saveField($user, $name, $value, $rel = null, $index = null, $date = null)
502     {
503         $profile = $user->getProfile();
504         $detail  = new Profile_detail();
505
506         $detail->profile_id  = $profile->id;
507         $detail->field_name  = $name;
508         $detail->value_index = $index;
509
510         $result = $detail->find(true);
511
512         if (empty($result)) {
513             $detial->value_index = $index;
514             $detail->rel         = $rel;
515             $detail->field_value = $value;
516             $detail->date        = $date;
517             $detail->created     = common_sql_now();
518             $result = $detail->insert();
519             if (empty($result)) {
520                 common_log_db_error($detail, 'INSERT', __FILE__);
521                 // TRANS: Server error displayed when a field could not be saved in the database.
522                 $this->serverError(_m('Could not save profile details.'));
523             }
524         } else {
525             $orig = clone($detail);
526
527             $detail->field_value = $value;
528             $detail->rel         = $rel;
529             $detail->date        = $date;
530
531             $result = $detail->update($orig);
532             if (empty($result)) {
533                 common_log_db_error($detail, 'UPDATE', __FILE__);
534                 // TRANS: Server error displayed when a field could not be saved in the database.
535                 $this->serverError(_m('Could not save profile details.'));
536             }
537         }
538
539         $detail->free();
540     }
541
542     function removeAll($user, $name)
543     {
544         $profile = $user->getProfile();
545         $detail  = new Profile_detail();
546         $detail->profile_id  = $profile->id;
547         $detail->field_name  = $name;
548         $detail->delete();
549         $detail->free();
550     }
551
552     /**
553      * Save fields that should be stored in the main profile object
554      *
555      * XXX: There's a lot of dupe code here from ProfileSettingsAction.
556      *      Do not want.
557      *
558      * @param User $user the current user
559      */
560     function saveStandardProfileDetails($user)
561     {
562         $fullname  = $this->trimmed('extprofile-fullname');
563         $location  = $this->trimmed('extprofile-location');
564         $tagstring = $this->trimmed('extprofile-tags');
565         $bio       = $this->trimmed('extprofile-bio');
566
567         if ($tagstring) {
568             $tags = array_map(
569                 'common_canonical_tag',
570                 preg_split('/[\s,]+/', $tagstring)
571             );
572         } else {
573             $tags = array();
574         }
575
576         foreach ($tags as $tag) {
577             if (!common_valid_profile_tag($tag)) {
578                 // TRANS: Validation error in form for profile settings.
579                 // TRANS: %s is an invalid tag.
580                 throw new Exception(sprintf(_m('Invalid tag: "%s".'), $tag));
581             }
582         }
583
584         $profile = $user->getProfile();
585
586         $oldTags = $user->getSelfTags();
587         $newTags = array_diff($tags, $oldTags);
588
589         if ($fullname    != $profile->fullname
590             || $location != $profile->location
591             || !empty($newTags)
592             || $bio      != $profile->bio) {
593
594             $orig = clone($profile);
595
596             $profile->nickname = $user->nickname;
597             $profile->fullname = $fullname;
598             $profile->bio      = $bio;
599             $profile->location = $location;
600
601             $loc = Location::fromName($location);
602
603             if (empty($loc)) {
604                 $profile->lat         = null;
605                 $profile->lon         = null;
606                 $profile->location_id = null;
607                 $profile->location_ns = null;
608             } else {
609                 $profile->lat         = $loc->lat;
610                 $profile->lon         = $loc->lon;
611                 $profile->location_id = $loc->location_id;
612                 $profile->location_ns = $loc->location_ns;
613             }
614
615             $profile->profileurl = common_profile_url($user->nickname);
616
617             $result = $profile->update($orig);
618
619             if ($result === false) {
620                 common_log_db_error($profile, 'UPDATE', __FILE__);
621                 // TRANS: Server error thrown when user profile settings could not be saved.
622                 $this->serverError(_m('Could not save profile.'));
623                 return;
624             }
625
626             // Set the user tags
627             $result = $user->setSelfTags($tags);
628
629             if (!$result) {
630                 // TRANS: Server error thrown when user profile settings tags could not be saved.
631                 $this->serverError(_m('Could not save tags.'));
632                 return;
633             }
634
635             Event::handle('EndProfileSaveForm', array($this));
636             common_broadcast_profile($profile);
637         }
638     }
639
640 }