. */ if (!defined('STATUSNET')) { exit(1); } class ProfileDetailSettingsAction extends ProfileSettingsAction { function title() { return _m('Extended profile settings'); } /** * Instructions for use * * @return instructions for use */ function getInstructions() { // TRANS: Usage instructions for profile settings. return _('You can update your personal profile info here '. 'so people know more about you.'); } function showStylesheets() { parent::showStylesheets(); $this->cssLink('plugins/ExtendedProfile/css/profiledetail.css'); $this->cssLink('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css'); return true; } function showScripts() { parent::showScripts(); $this->script('plugins/ExtendedProfile/js/profiledetail.js'); $this->script('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js'); return true; } function handlePost() { // CSRF protection $token = $this->trimmed('token'); if (!$token || $token != common_session_token()) { $this->showForm( _m( 'There was a problem with your session token. ' . 'Try again, please.' ) ); return; } if ($this->arg('save')) { $this->saveDetails(); } else { // TRANS: Message given submitting a form with an unknown action $this->showForm(_m('Unexpected form submission.')); } } function showContent() { $cur = common_current_user(); $profile = $cur->getProfile(); $widget = new ExtendedProfileWidget( $this, $profile, ExtendedProfileWidget::EDITABLE ); $widget->show(); } function saveDetails() { common_debug(var_export($_POST, true)); $user = common_current_user(); try { $this->saveStandardProfileDetails($user); $profile = $user->getProfile(); $simpleFieldNames = array('title', 'spouse', 'kids', 'manager'); $dateFieldNames = array('birthday'); foreach ($simpleFieldNames as $name) { $value = $this->trimmed('extprofile-' . $name); if (!empty($value)) { $this->saveField($user, $name, $value); } } foreach ($dateFieldNames as $name) { $value = $this->trimmed('extprofile-' . $name); $dateVal = $this->parseDate($name, $value); $this->saveField( $user, $name, null, null, null, $dateVal ); } $this->savePhoneNumbers($user); $this->saveIms($user); $this->saveWebsites($user); $this->saveExperiences($user); $this->saveEducations($user); } catch (Exception $e) { $this->showForm($e->getMessage(), false); return; } $this->showForm(_('Details saved.'), true); } function parseDate($fieldname, $datestr, $required = false) { if (empty($datestr) && $required) { $msg = sprintf( _m('You must supply a date for "%s".'), $fieldname ); throw new Exception($msg); } else { $ts = strtotime($datestr); if ($ts === false) { throw new Exception( sprintf( _m('Invalid date entered for "%s": %s'), $fieldname, $ts ) ); } return common_sql_date($ts); } return null; } function savePhoneNumbers($user) { $phones = $this->findPhoneNumbers(); $this->removeAll($user, 'phone'); $i = 0; foreach($phones as $phone) { if (!empty($phone['value'])) { ++$i; $this->saveField( $user, 'phone', $phone['value'], $phone['rel'], $i ); } } } function findPhoneNumbers() { // Form vals look like this: // 'extprofile-phone-1' => '11332', // 'extprofile-phone-1-rel' => 'mobile', $phones = $this->sliceParams('phone', 2); $phoneArray = array(); foreach ($phones as $phone) { list($number, $rel) = array_values($phone); $phoneArray[] = array( 'value' => $number, 'rel' => $rel ); } return $phoneArray; } function findIms() { // Form vals look like this: // 'extprofile-im-0' => 'jed', // 'extprofile-im-0-rel' => 'yahoo', $ims = $this->sliceParams('im', 2); $imArray = array(); foreach ($ims as $im) { list($id, $rel) = array_values($im); $imArray[] = array( 'value' => $id, 'rel' => $rel ); } return $imArray; } function saveIms($user) { $ims = $this->findIms(); $this->removeAll($user, 'im'); $i = 0; foreach($ims as $im) { if (!empty($im['value'])) { ++$i; $this->saveField( $user, 'im', $im['value'], $im['rel'], $i ); } } } function findWebsites() { // Form vals look like this: $sites = $this->sliceParams('website', 2); $wsArray = array(); foreach ($sites as $site) { list($id, $rel) = array_values($site); $wsArray[] = array( 'value' => $id, 'rel' => $rel ); } return $wsArray; } function saveWebsites($user) { $sites = $this->findWebsites(); $this->removeAll($user, 'website'); $i = 0; foreach($sites as $site) { if (!Validate::uri( $site['value'], array('allowed_schemes' => array('http', 'https'))) ) { throw new Exception(sprintf(_m('Invalid URL: %s'), $site['value'])); } if (!empty($site['value'])) { ++$i; $this->saveField( $user, 'website', $site['value'], $site['rel'], $i ); } } } function findExperiences() { // Form vals look like this: // 'extprofile-experience-0' => 'Bozotronix', // 'extprofile-experience-0-current' => 'true' // 'extprofile-experience-0-start' => '1/5/10', // 'extprofile-experience-0-end' => '2/3/11', $experiences = $this->sliceParams('experience', 4); $expArray = array(); foreach ($experiences as $exp) { if (sizeof($experiences) == 4) { list($company, $current, $end, $start) = array_values($exp); } else { $end = null; list($company, $current, $start) = array_values($exp); } if (!empty($company)) { $expArray[] = array( 'company' => $company, 'start' => $this->parseDate('Start', $start, true), 'end' => ($current == 'false') ? $this->parseDate('End', $end, true) : null, 'current' => ($current == 'false') ? false : true ); } } return $expArray; } function saveExperiences($user) { common_debug('save experiences'); $experiences = $this->findExperiences(); $this->removeAll($user, 'company'); $this->removeAll($user, 'start'); $this->removeAll($user, 'end'); // also stores 'current' $i = 0; foreach($experiences as $experience) { if (!empty($experience['company'])) { ++$i; $this->saveField( $user, 'company', $experience['company'], null, $i ); $this->saveField( $user, 'start', null, null, $i, $experience['start'] ); // Save "current" employer indicator in rel if ($experience['current']) { $this->saveField( $user, 'end', null, 'current', // rel $i ); } else { $this->saveField( $user, 'end', null, null, $i, $experience['end'] ); } } } } function findEducations() { // Form vals look like this: // 'extprofile-education-0-school' => 'Pigdog', // 'extprofile-education-0-degree' => 'BA', // 'extprofile-education-0-description' => 'Blar', // 'extprofile-education-0-start' => '05/22/99', // 'extprofile-education-0-end' => '05/22/05', $edus = $this->sliceParams('education', 5); $eduArray = array(); foreach ($edus as $edu) { list($school, $degree, $description, $end, $start) = array_values($edu); if (!empty($school)) { $eduArray[] = array( 'school' => $school, 'degree' => $degree, 'description' => $description, 'start' => $this->parseDate('Start', $start, true), 'end' => $this->parseDate('End', $end, true) ); } } return $eduArray; } function saveEducations($user) { common_debug('save education'); $edus = $this->findEducations(); common_debug(var_export($edus, true)); $this->removeAll($user, 'school'); $this->removeAll($user, 'degree'); $this->removeAll($user, 'degree_descr'); $this->removeAll($user, 'school_start'); $this->removeAll($user, 'school_end'); $i = 0; foreach($edus as $edu) { if (!empty($edu['school'])) { ++$i; $this->saveField( $user, 'school', $edu['school'], null, $i ); $this->saveField( $user, 'degree', $edu['degree'], null, $i ); $this->saveField( $user, 'degree_descr', $edu['description'], null, $i ); $this->saveField( $user, 'school_start', null, null, $i, $edu['start'] ); $this->saveField( $user, 'school_end', null, null, $i, $edu['end'] ); } } } function arraySplit($array, $pieces) { if ($pieces < 2) { return array($array); } $newCount = ceil(count($array) / $pieces); $a = array_slice($array, 0, $newCount); $b = $this->arraySplit(array_slice($array, $newCount), $pieces - 1); return array_merge(array($a), $b); } function findMultiParams($type) { $formVals = array(); $target = $type; foreach ($_POST as $key => $val) { if (strrpos('extprofile-' . $key, $target) !== false) { $formVals[$key] = $val; } } return $formVals; } function sliceParams($key, $size) { $slice = array(); $params = $this->findMultiParams($key); ksort($params); $slice = $this->arraySplit($params, sizeof($params) / $size); return $slice; } /** * Save an extended profile field as a Profile_detail * * @param User $user the current user * @param string $name field name * @param string $value field value * @param string $rel field rel (type) * @param int $index index (fields can have multiple values) * @param date $date related date */ function saveField($user, $name, $value, $rel = null, $index = null, $date = null) { $profile = $user->getProfile(); $detail = new Profile_detail(); $detail->profile_id = $profile->id; $detail->field_name = $name; $detail->value_index = $index; $result = $detail->find(true); if (empty($result)) { $detial->value_index = $index; $detail->rel = $rel; $detail->field_value = $value; $detail->date = $date; $detail->created = common_sql_now(); $result = $detail->insert(); if (empty($result)) { common_log_db_error($detail, 'INSERT', __FILE__); $this->serverError(_m('Could not save profile details.')); } } else { $orig = clone($detail); $detail->field_value = $value; $detail->rel = $rel; $detail->date = $date; $result = $detail->update($orig); if (empty($result)) { common_log_db_error($detail, 'UPDATE', __FILE__); $this->serverError(_m('Could not save profile details.')); } } $detail->free(); } function removeAll($user, $name) { $profile = $user->getProfile(); $detail = new Profile_detail(); $detail->profile_id = $profile->id; $detail->field_name = $name; $detail->delete(); $detail->free(); } /** * Save fields that should be stored in the main profile object * * XXX: There's a lot of dupe code here from ProfileSettingsAction. * Do not want. * * @param User $user the current user */ function saveStandardProfileDetails($user) { $fullname = $this->trimmed('extprofile-fullname'); $location = $this->trimmed('extprofile-location'); $tagstring = $this->trimmed('extprofile-tags'); $bio = $this->trimmed('extprofile-bio'); if ($tagstring) { $tags = array_map( 'common_canonical_tag', preg_split('/[\s,]+/', $tagstring) ); } else { $tags = array(); } foreach ($tags as $tag) { if (!common_valid_profile_tag($tag)) { // TRANS: Validation error in form for profile settings. // TRANS: %s is an invalid tag. throw new Exception(sprintf(_m('Invalid tag: "%s".'), $tag)); } } $profile = $user->getProfile(); $oldTags = $user->getSelfTags(); $newTags = array_diff($tags, $oldTags); if ($fullname != $profile->fullname || $location != $profile->location || !empty($newTags) || $bio != $profile->bio) { $orig = clone($profile); $profile->nickname = $user->nickname; $profile->fullname = $fullname; $profile->bio = $bio; $profile->location = $location; $loc = Location::fromName($location); if (empty($loc)) { $profile->lat = null; $profile->lon = null; $profile->location_id = null; $profile->location_ns = null; } else { $profile->lat = $loc->lat; $profile->lon = $loc->lon; $profile->location_id = $loc->location_id; $profile->location_ns = $loc->location_ns; } $profile->profileurl = common_profile_url($user->nickname); $result = $profile->update($orig); if ($result === false) { common_log_db_error($profile, 'UPDATE', __FILE__); // TRANS: Server error thrown when user profile settings could not be saved. $this->serverError(_('Could not save profile.')); return; } // Set the user tags $result = $user->setSelfTags($tags); if (!$result) { // TRANS: Server error thrown when user profile settings tags could not be saved. $this->serverError(_('Could not save tags.')); return; } Event::handle('EndProfileSaveForm', array($this)); common_broadcast_profile($profile); } } }