3 * StatusNet - the distributed open-source microblogging tool
4 * Copyright (C) 2011, StatusNet, Inc.
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.
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.
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/>.
20 if (!defined('STATUSNET')) {
24 class ProfileDetailSettingsAction extends ProfileSettingsAction
28 // TRANS: Title for extended profile settings.
29 return _m('Extended profile settings');
33 * Instructions for use
35 * @return instructions for use
37 function getInstructions()
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.');
44 function showStylesheets() {
45 parent::showStylesheets();
46 $this->cssLink('plugins/ExtendedProfile/css/profiledetail.css');
50 function showScripts() {
51 parent::showScripts();
52 $this->script('plugins/ExtendedProfile/js/profiledetail.js');
59 $token = $this->trimmed('token');
60 if (!$token || $token != common_session_token()) {
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.'
70 if ($this->arg('save')) {
73 // TRANS: Message given submitting a form with an unknown action.
74 $this->showForm(_m('Unexpected form submission.'));
78 function showContent()
80 $cur = common_current_user();
81 $profile = $cur->getProfile();
83 $widget = new ExtendedProfileWidget(
86 ExtendedProfileWidget::EDITABLE
91 function saveDetails()
93 common_debug(var_export($_POST, true));
95 $user = common_current_user();
98 $this->saveStandardProfileDetails($user);
100 $profile = $user->getProfile();
102 $simpleFieldNames = array('title', 'spouse', 'kids', 'manager');
103 $dateFieldNames = array('birthday');
105 foreach ($simpleFieldNames as $name) {
106 $value = $this->trimmed('extprofile-' . $name);
107 if (!empty($value)) {
108 $this->saveField($user, $name, $value);
112 foreach ($dateFieldNames as $name) {
113 $value = $this->trimmed('extprofile-' . $name);
114 $dateVal = $this->parseDate($name, $value);
125 $this->savePhoneNumbers($user);
126 $this->saveIms($user);
127 $this->saveWebsites($user);
128 $this->saveExperiences($user);
129 $this->saveEducations($user);
131 } catch (Exception $e) {
132 $this->showForm($e->getMessage(), false);
136 // TRANS: Success message after saving extended profile details.
137 $this->showForm(_m('Details saved.'), true);
141 function parseDate($fieldname, $datestr, $required = false)
143 if (empty($datestr)) {
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".'),
151 throw new Exception($msg);
154 $ts = strtotime($datestr);
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.'),
166 return common_sql_date($ts);
171 function savePhoneNumbers($user) {
172 $phones = $this->findPhoneNumbers();
173 $this->removeAll($user, 'phone');
175 foreach($phones as $phone) {
176 if (!empty($phone['value'])) {
189 function findPhoneNumbers() {
191 // Form vals look like this:
192 // 'extprofile-phone-1' => '11332',
193 // 'extprofile-phone-1-rel' => 'mobile',
195 $phones = $this->sliceParams('phone', 2);
196 $phoneArray = array();
198 foreach ($phones as $phone) {
199 list($number, $rel) = array_values($phone);
200 $phoneArray[] = array(
211 // Form vals look like this:
212 // 'extprofile-im-0' => 'jed',
213 // 'extprofile-im-0-rel' => 'yahoo',
215 $ims = $this->sliceParams('im', 2);
218 foreach ($ims as $im) {
219 list($id, $rel) = array_values($im);
229 function saveIms($user) {
230 $ims = $this->findIms();
231 $this->removeAll($user, 'im');
233 foreach($ims as $im) {
234 if (!empty($im['value'])) {
247 function findWebsites() {
249 // Form vals look like this:
251 $sites = $this->sliceParams('website', 2);
254 foreach ($sites as $site) {
255 list($id, $rel) = array_values($site);
265 function saveWebsites($user) {
266 $sites = $this->findWebsites();
267 $this->removeAll($user, 'website');
269 foreach($sites as $site) {
270 if (!empty($site['value']) && !Validate::uri(
272 array('allowed_schemes' => array('http', 'https')))
274 // TRANS: Exception thrown when entering an invalid URL.
275 // TRANS: %s is the invalid URL.
276 throw new Exception(sprintf(_m('Invalid URL: %s.'), $site['value']));
279 if (!empty($site['value'])) {
292 function findExperiences() {
294 // Form vals look like this:
295 // 'extprofile-experience-0' => 'Bozotronix',
296 // 'extprofile-experience-0-current' => 'true'
297 // 'extprofile-experience-0-start' => '1/5/10',
298 // 'extprofile-experience-0-end' => '2/3/11',
300 $experiences = $this->sliceParams('experience', 4);
303 foreach ($experiences as $exp) {
304 if (sizeof($experiences) == 4) {
305 list($company, $current, $end, $start) = array_values($exp);
308 list($company, $current, $start) = array_values($exp);
310 if (!empty($company)) {
312 'company' => $company,
313 'start' => $this->parseDate('Start', $start, true),
314 'end' => ($current == 'false') ? $this->parseDate('End', $end, true) : null,
315 'current' => ($current == 'false') ? false : true
323 function saveExperiences($user) {
324 common_debug('save experiences');
325 $experiences = $this->findExperiences();
327 $this->removeAll($user, 'company');
328 $this->removeAll($user, 'start');
329 $this->removeAll($user, 'end'); // also stores 'current'
332 foreach($experiences as $experience) {
333 if (!empty($experience['company'])) {
338 $experience['company'],
352 // Save "current" employer indicator in rel
353 if ($experience['current']) {
376 function findEducations() {
378 // Form vals look like this:
379 // 'extprofile-education-0-school' => 'Pigdog',
380 // 'extprofile-education-0-degree' => 'BA',
381 // 'extprofile-education-0-description' => 'Blar',
382 // 'extprofile-education-0-start' => '05/22/99',
383 // 'extprofile-education-0-end' => '05/22/05',
385 $edus = $this->sliceParams('education', 5);
388 foreach ($edus as $edu) {
389 list($school, $degree, $description, $end, $start) = array_values($edu);
390 if (!empty($school)) {
394 'description' => $description,
395 'start' => $this->parseDate('Start', $start, true),
396 'end' => $this->parseDate('End', $end, true)
405 function saveEducations($user) {
406 common_debug('save education');
407 $edus = $this->findEducations();
408 common_debug(var_export($edus, true));
410 $this->removeAll($user, 'school');
411 $this->removeAll($user, 'degree');
412 $this->removeAll($user, 'degree_descr');
413 $this->removeAll($user, 'school_start');
414 $this->removeAll($user, 'school_end');
417 foreach($edus as $edu) {
418 if (!empty($edu['school'])) {
462 function arraySplit($array, $pieces)
465 return array($array);
468 $newCount = ceil(count($array) / $pieces);
469 $a = array_slice($array, 0, $newCount);
470 $b = $this->arraySplit(array_slice($array, $newCount), $pieces - 1);
472 return array_merge(array($a), $b);
475 function findMultiParams($type) {
478 foreach ($_POST as $key => $val) {
479 if (strrpos('extprofile-' . $key, $target) !== false) {
480 $formVals[$key] = $val;
486 function sliceParams($key, $size) {
488 $params = $this->findMultiParams($key);
490 $slice = $this->arraySplit($params, sizeof($params) / $size);
495 * Save an extended profile field as a Profile_detail
497 * @param User $user the current user
498 * @param string $name field name
499 * @param string $value field value
500 * @param string $rel field rel (type)
501 * @param int $index index (fields can have multiple values)
502 * @param date $date related date
504 function saveField($user, $name, $value, $rel = null, $index = null, $date = null)
506 $profile = $user->getProfile();
507 $detail = new Profile_detail();
509 $detail->profile_id = $profile->id;
510 $detail->field_name = $name;
511 $detail->value_index = $index;
513 $result = $detail->find(true);
515 if (empty($result)) {
516 $detial->value_index = $index;
518 $detail->field_value = $value;
519 $detail->date = $date;
520 $detail->created = common_sql_now();
521 $result = $detail->insert();
522 if (empty($result)) {
523 common_log_db_error($detail, 'INSERT', __FILE__);
524 // TRANS: Server error displayed when a field could not be saved in the database.
525 $this->serverError(_m('Could not save profile details.'));
528 $orig = clone($detail);
530 $detail->field_value = $value;
532 $detail->date = $date;
534 $result = $detail->update($orig);
535 if (empty($result)) {
536 common_log_db_error($detail, 'UPDATE', __FILE__);
537 // TRANS: Server error displayed when a field could not be saved in the database.
538 $this->serverError(_m('Could not save profile details.'));
545 function removeAll($user, $name)
547 $profile = $user->getProfile();
548 $detail = new Profile_detail();
549 $detail->profile_id = $profile->id;
550 $detail->field_name = $name;
556 * Save fields that should be stored in the main profile object
558 * XXX: There's a lot of dupe code here from ProfileSettingsAction.
561 * @param User $user the current user
563 function saveStandardProfileDetails($user)
565 $fullname = $this->trimmed('extprofile-fullname');
566 $location = $this->trimmed('extprofile-location');
567 $tagstring = $this->trimmed('extprofile-tags');
568 $bio = $this->trimmed('extprofile-bio');
572 'common_canonical_tag',
573 preg_split('/[\s,]+/', $tagstring)
579 foreach ($tags as $tag) {
580 if (!common_valid_profile_tag($tag)) {
581 // TRANS: Validation error in form for profile settings.
582 // TRANS: %s is an invalid tag.
583 throw new Exception(sprintf(_m('Invalid tag: "%s".'), $tag));
587 $profile = $user->getProfile();
589 $oldTags = $user->getSelfTags();
590 $newTags = array_diff($tags, $oldTags);
592 if ($fullname != $profile->fullname
593 || $location != $profile->location
595 || $bio != $profile->bio) {
597 $orig = clone($profile);
599 $profile->nickname = $user->nickname;
600 $profile->fullname = $fullname;
601 $profile->bio = $bio;
602 $profile->location = $location;
604 $loc = Location::fromName($location);
607 $profile->lat = null;
608 $profile->lon = null;
609 $profile->location_id = null;
610 $profile->location_ns = null;
612 $profile->lat = $loc->lat;
613 $profile->lon = $loc->lon;
614 $profile->location_id = $loc->location_id;
615 $profile->location_ns = $loc->location_ns;
618 $profile->profileurl = common_profile_url($user->nickname);
620 $result = $profile->update($orig);
622 if ($result === false) {
623 common_log_db_error($profile, 'UPDATE', __FILE__);
624 // TRANS: Server error thrown when user profile settings could not be saved.
625 $this->serverError(_m('Could not save profile.'));
630 $result = $user->setSelfTags($tags);
633 // TRANS: Server error thrown when user profile settings tags could not be saved.
634 $this->serverError(_m('Could not save tags.'));
638 Event::handle('EndProfileSaveForm', array($this));
639 common_broadcast_profile($profile);