]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/ExtendedProfile/actions/profiledetailsettings.php
Merge branch '1.0.x' of git://gitorious.org/statusnet/mainline
[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
27     function title()
28     {
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                 _m(
63                     '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         $this->showForm(_m('Details saved.'), true);
137
138     }
139
140     function parseDate($fieldname, $datestr, $required = false)
141     {
142         if (empty($datestr)) {
143             if ($required) {
144                 $msg = sprintf(
145                     // TRANS: Exception thrown when no date was entered in a required date field.
146                     // TRANS: %s is the field name.
147                     _m('You must supply a date for "%s".'),
148                     $fieldname
149                 );
150                 throw new Exception($msg);
151             }
152         } else {
153             $ts = strtotime($datestr);
154             if ($ts === false) {
155                 throw new Exception(
156                     sprintf(
157                         // TRANS: Exception thrown on incorrect data input.
158                         // TRANS: %1$s is a field name, %2$s is the incorrect input.
159                         _m('Invalid date entered for "%1$s": %2$s.'),
160                         $fieldname,
161                         $ts
162                     )
163                 );
164             }
165             return common_sql_date($ts);
166         }
167         return null;
168     }
169
170     function savePhoneNumbers($user) {
171         $phones = $this->findPhoneNumbers();
172         $this->removeAll($user, 'phone');
173         $i = 0;
174         foreach($phones as $phone) {
175             if (!empty($phone['value'])) {
176                 ++$i;
177                 $this->saveField(
178                     $user,
179                     'phone',
180                     $phone['value'],
181                     $phone['rel'],
182                     $i
183                 );
184             }
185         }
186     }
187
188     function findPhoneNumbers() {
189
190         // Form vals look like this:
191         // 'extprofile-phone-1' => '11332',
192         // 'extprofile-phone-1-rel' => 'mobile',
193
194         $phones     = $this->sliceParams('phone', 2);
195         $phoneArray = array();
196
197         foreach ($phones as $phone) {
198             list($number, $rel) = array_values($phone);
199             $phoneArray[] = array(
200                 'value' => $number,
201                 'rel'   => $rel
202             );
203         }
204
205         return $phoneArray;
206     }
207
208     function findIms() {
209
210         //  Form vals look like this:
211         // 'extprofile-im-0' => 'jed',
212         // 'extprofile-im-0-rel' => 'yahoo',
213
214         $ims     = $this->sliceParams('im', 2);
215         $imArray = array();
216
217         foreach ($ims as $im) {
218             list($id, $rel) = array_values($im);
219             $imArray[] = array(
220                 'value' => $id,
221                 'rel'   => $rel
222             );
223         }
224
225         return $imArray;
226     }
227
228     function saveIms($user) {
229         $ims = $this->findIms();
230         $this->removeAll($user, 'im');
231         $i = 0;
232         foreach($ims as $im) {
233             if (!empty($im['value'])) {
234                 ++$i;
235                 $this->saveField(
236                     $user,
237                     'im',
238                     $im['value'],
239                     $im['rel'],
240                     $i
241                 );
242             }
243         }
244     }
245
246     function findWebsites() {
247
248         //  Form vals look like this:
249
250         $sites = $this->sliceParams('website', 2);
251         $wsArray = array();
252
253         foreach ($sites as $site) {
254             list($id, $rel) = array_values($site);
255             $wsArray[] = array(
256                 'value' => $id,
257                 'rel'   => $rel
258             );
259         }
260
261         return $wsArray;
262     }
263
264     function saveWebsites($user) {
265         $sites = $this->findWebsites();
266         $this->removeAll($user, 'website');
267         $i = 0;
268         foreach($sites as $site) {
269             if (!empty($site['value']) && !Validate::uri(
270                 $site['value'],
271                 array('allowed_schemes' => array('http', 'https')))
272             ) {
273                 // TRANS: Exception thrown when entering an invalid URL.
274                 // TRANS: %s is the invalid URL.
275                 throw new Exception(sprintf(_m('Invalid URL: %s.'), $site['value']));
276             }
277
278             if (!empty($site['value'])) {
279                 ++$i;
280                 $this->saveField(
281                     $user,
282                     'website',
283                     $site['value'],
284                     $site['rel'],
285                     $i
286                 );
287             }
288         }
289     }
290
291     function findExperiences() {
292
293         // Form vals look like this:
294         // 'extprofile-experience-0'         => 'Bozotronix',
295         // 'extprofile-experience-0-current' => 'true'
296         // 'extprofile-experience-0-start'   => '1/5/10',
297         // 'extprofile-experience-0-end'     => '2/3/11',
298
299         $experiences = $this->sliceParams('experience', 4);
300         $expArray = array();
301
302         foreach ($experiences as $exp) {
303             if (sizeof($experiences) == 4) {
304                 list($company, $current, $end, $start) = array_values($exp);
305             } else {
306                 $end = null;
307                 list($company, $current, $start) = array_values($exp);
308             }
309             if (!empty($company)) {
310                 $expArray[] = array(
311                     'company' => $company,
312                     'start'   => $this->parseDate('Start', $start, true),
313                     'end'     => ($current == 'false') ? $this->parseDate('End', $end, true) : null,
314                     'current' => ($current == 'false') ? false : true
315                 );
316             }
317         }
318
319         return $expArray;
320     }
321
322     function saveExperiences($user) {
323         common_debug('save experiences');
324         $experiences = $this->findExperiences();
325
326         $this->removeAll($user, 'company');
327         $this->removeAll($user, 'start');
328         $this->removeAll($user, 'end'); // also stores 'current'
329
330         $i = 0;
331         foreach($experiences as $experience) {
332             if (!empty($experience['company'])) {
333                 ++$i;
334                 $this->saveField(
335                     $user,
336                     'company',
337                     $experience['company'],
338                     null,
339                     $i
340                 );
341
342                 $this->saveField(
343                     $user,
344                     'start',
345                     null,
346                     null,
347                     $i,
348                     $experience['start']
349                 );
350
351                 // Save "current" employer indicator in rel
352                 if ($experience['current']) {
353                     $this->saveField(
354                         $user,
355                         'end',
356                         null,
357                         'current', // rel
358                         $i
359                     );
360                 } else {
361                     $this->saveField(
362                         $user,
363                         'end',
364                         null,
365                         null,
366                         $i,
367                         $experience['end']
368                     );
369                 }
370
371             }
372         }
373     }
374
375     function findEducations() {
376
377         // Form vals look like this:
378         // 'extprofile-education-0-school' => 'Pigdog',
379         // 'extprofile-education-0-degree' => 'BA',
380         // 'extprofile-education-0-description' => 'Blar',
381         // 'extprofile-education-0-start' => '05/22/99',
382         // 'extprofile-education-0-end' => '05/22/05',
383
384         $edus = $this->sliceParams('education', 5);
385         $eduArray = array();
386
387         foreach ($edus as $edu) {
388             list($school, $degree, $description, $end, $start) = array_values($edu);
389             if (!empty($school)) {
390                 $eduArray[] = array(
391                     'school'      => $school,
392                     'degree'      => $degree,
393                     'description' => $description,
394                     'start'       => $this->parseDate('Start', $start, true),
395                     'end'         => $this->parseDate('End', $end, true)
396                 );
397             }
398         }
399
400         return $eduArray;
401     }
402
403
404     function saveEducations($user) {
405          common_debug('save education');
406          $edus = $this->findEducations();
407          common_debug(var_export($edus, true));
408
409          $this->removeAll($user, 'school');
410          $this->removeAll($user, 'degree');
411          $this->removeAll($user, 'degree_descr');
412          $this->removeAll($user, 'school_start');
413          $this->removeAll($user, 'school_end');
414
415          $i = 0;
416          foreach($edus as $edu) {
417              if (!empty($edu['school'])) {
418                  ++$i;
419                  $this->saveField(
420                      $user,
421                      'school',
422                      $edu['school'],
423                      null,
424                      $i
425                  );
426                  $this->saveField(
427                      $user,
428                      'degree',
429                      $edu['degree'],
430                      null,
431                      $i
432                  );
433                  $this->saveField(
434                      $user,
435                      'degree_descr',
436                      $edu['description'],
437                      null,
438                      $i
439                  );
440                  $this->saveField(
441                      $user,
442                      'school_start',
443                      null,
444                      null,
445                      $i,
446                      $edu['start']
447                  );
448
449                  $this->saveField(
450                      $user,
451                      'school_end',
452                      null,
453                      null,
454                      $i,
455                      $edu['end']
456                  );
457             }
458          }
459      }
460
461     function arraySplit($array, $pieces)
462     {
463         if ($pieces < 2) {
464             return array($array);
465         }
466
467         $newCount = ceil(count($array) / $pieces);
468         $a = array_slice($array, 0, $newCount);
469         $b = $this->arraySplit(array_slice($array, $newCount), $pieces - 1);
470
471         return array_merge(array($a), $b);
472     }
473
474     function findMultiParams($type) {
475         $formVals = array();
476         $target   = $type;
477         foreach ($_POST as $key => $val) {
478             if (strrpos('extprofile-' . $key, $target) !== false) {
479                 $formVals[$key] = $val;
480             }
481         }
482         return $formVals;
483     }
484
485     function sliceParams($key, $size) {
486         $slice = array();
487         $params = $this->findMultiParams($key);
488         ksort($params);
489         $slice = $this->arraySplit($params, sizeof($params) / $size);
490         return $slice;
491     }
492
493     /**
494      * Save an extended profile field as a Profile_detail
495      *
496      * @param User   $user    the current user
497      * @param string $name    field name
498      * @param string $value   field value
499      * @param string $rel     field rel (type)
500      * @param int    $index   index (fields can have multiple values)
501      * @param date   $date    related date
502      */
503     function saveField($user, $name, $value, $rel = null, $index = null, $date = null)
504     {
505         $profile = $user->getProfile();
506         $detail  = new Profile_detail();
507
508         $detail->profile_id  = $profile->id;
509         $detail->field_name  = $name;
510         $detail->value_index = $index;
511
512         $result = $detail->find(true);
513
514         if (empty($result)) {
515             $detial->value_index = $index;
516             $detail->rel         = $rel;
517             $detail->field_value = $value;
518             $detail->date        = $date;
519             $detail->created     = common_sql_now();
520             $result = $detail->insert();
521             if (empty($result)) {
522                 common_log_db_error($detail, 'INSERT', __FILE__);
523                 $this->serverError(_m('Could not save profile details.'));
524             }
525         } else {
526             $orig = clone($detail);
527
528             $detail->field_value = $value;
529             $detail->rel         = $rel;
530             $detail->date        = $date;
531
532             $result = $detail->update($orig);
533             if (empty($result)) {
534                 common_log_db_error($detail, 'UPDATE', __FILE__);
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 }