Merge branch 'profile-fixups' into 1.0.x
* profile-fixups: (46 commits) * Extended profile - make cloned datefields work correctly with calendar popup * Validate URLs More style for profile edit. Extended profile - don't show empty company entry in view Extended profile - linkify related URLs added by the user Extended profile - fix some issues saving and displaying dates Extended profile - don't check end date if experience entry has current checked Extended profile - allow adding more than one website Small smattering of pixie dust Extended profile - fix regression whereby if there was only one item, you could still delete it! Remove supersizeme class as appropriate. Extended profile - hide add button when not needed (regression) Extended profile - add fancy JQuery UI confirm dialog when deleting items Extended profile - add fancy datepicker widgets Extended profile - prettier date formatting Extended profile - fix issue with JavaScript not executing in Firefox Extended profile - namespace JavaScript functions Extended profile - autocomplete for manager Hide all unnecessarylabels from profile edit view. Extended profile - make birthday save Extended profile - make websites save ...
This commit is contained in:
commit
daf73f8231
@ -54,6 +54,7 @@ class ExtendedProfilePlugin extends Plugin
|
||||
function onAutoload($cls)
|
||||
{
|
||||
$lower = strtolower($cls);
|
||||
|
||||
switch ($lower)
|
||||
{
|
||||
case 'extendedprofile':
|
||||
@ -62,6 +63,9 @@ class ExtendedProfilePlugin extends Plugin
|
||||
case 'profiledetailsettingsaction':
|
||||
require_once dirname(__FILE__) . '/' . $lower . '.php';
|
||||
return false;
|
||||
case 'userautocompleteaction':
|
||||
require_once dirname(__FILE__) . '/action/' . mb_substr($lower, 0, -6) . '.php';
|
||||
return false;
|
||||
case 'profile_detail':
|
||||
require_once dirname(__FILE__) . '/' . ucfirst($lower) . '.php';
|
||||
return false;
|
||||
@ -81,11 +85,19 @@ class ExtendedProfilePlugin extends Plugin
|
||||
*/
|
||||
function onStartInitializeRouter($m)
|
||||
{
|
||||
$m->connect(':nickname/detail',
|
||||
$m->connect(
|
||||
':nickname/detail',
|
||||
array('action' => 'profiledetail'),
|
||||
array('nickname' => Nickname::DISPLAY_FMT));
|
||||
$m->connect('settings/profile/detail',
|
||||
array('action' => 'profiledetailsettings'));
|
||||
array('nickname' => Nickname::DISPLAY_FMT)
|
||||
);
|
||||
$m->connect(
|
||||
'/settings/profile/finduser',
|
||||
array('action' => 'Userautocomplete')
|
||||
);
|
||||
$m->connect(
|
||||
'settings/profile/detail',
|
||||
array('action' => 'profiledetailsettings')
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -95,8 +107,6 @@ class ExtendedProfilePlugin extends Plugin
|
||||
$schema = Schema::get();
|
||||
$schema->ensureTable('profile_detail', Profile_detail::schemaDef());
|
||||
|
||||
// @hack until key definition support is merged
|
||||
Profile_detail::fixIndexes($schema);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -21,130 +21,122 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class Profile_detail extends Memcached_DataObject
|
||||
/**
|
||||
* DataObject class to store extended profile fields. Allows for storing
|
||||
* multiple values per a "field_name" (field_name property is not unique).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Jed's Phone Numbers
|
||||
* home : 510-384-1992
|
||||
* mobile: 510-719-1139
|
||||
* work : 415-231-1121
|
||||
*
|
||||
* We can store these phone numbers in a "field" represented by three
|
||||
* Profile_detail objects, each named 'phone_number' like this:
|
||||
*
|
||||
* $phone1 = new Profile_detail();
|
||||
* $phone1->field_name = 'phone_number';
|
||||
* $phone1->rel = 'home';
|
||||
* $phone1->field_value = '510-384-1992';
|
||||
* $phone1->value_index = 1;
|
||||
*
|
||||
* $phone1 = new Profile_detail();
|
||||
* $phone1->field_name = 'phone_number';
|
||||
* $phone1->rel = 'mobile';
|
||||
* $phone1->field_value = '510-719-1139';
|
||||
* $phone1->value_index = 2;
|
||||
*
|
||||
* $phone1 = new Profile_detail();
|
||||
* $phone1->field_name = 'phone_number';
|
||||
* $phone1->rel = 'work';
|
||||
* $phone1->field_value = '415-231-1121';
|
||||
* $phone1->value_index = 3;
|
||||
*
|
||||
*/
|
||||
class Profile_detail extends Managed_DataObject
|
||||
{
|
||||
public $__table = 'submirror';
|
||||
public $__table = 'profile_detail';
|
||||
|
||||
public $id;
|
||||
|
||||
public $profile_id;
|
||||
public $field;
|
||||
public $field_index; // relative ordering of multiple values in the same field
|
||||
|
||||
public $value; // primary text value
|
||||
public $profile_id; // profile this is for
|
||||
public $rel; // detail for some field types; eg "home", "mobile", "work" for phones or "aim", "irc", "xmpp" for IM
|
||||
public $field_name; // name
|
||||
public $field_value; // primary text value
|
||||
public $value_index; // relative ordering of multiple values in the same field
|
||||
public $date; // related date
|
||||
public $ref_profile; // for people types, allows pointing to a known profile in the system
|
||||
|
||||
public $created;
|
||||
public $modified;
|
||||
|
||||
public /*static*/ function staticGet($k, $v=null)
|
||||
/**
|
||||
* Get an instance by key
|
||||
*
|
||||
* This is a utility method to get a single instance with a given key value.
|
||||
*
|
||||
* @param string $k Key to use to lookup
|
||||
* @param mixed $v Value to lookup
|
||||
*
|
||||
* @return User_greeting_count object found, or null for no hits
|
||||
*
|
||||
*/
|
||||
|
||||
function staticGet($k, $v=null)
|
||||
{
|
||||
return parent::staticGet(__CLASS__, $k, $v);
|
||||
return Memcached_DataObject::staticGet('Profile_detail', $k, $v);
|
||||
}
|
||||
|
||||
/**
|
||||
* return table definition for DB_DataObject
|
||||
* Get an instance by compound key
|
||||
*
|
||||
* DB_DataObject needs to know something about the table to manipulate
|
||||
* instances. This method provides all the DB_DataObject needs to know.
|
||||
* This is a utility method to get a single instance with a given set of
|
||||
* key-value pairs. Usually used for the primary key for a compound key; thus
|
||||
* the name.
|
||||
*
|
||||
* @param array $kv array of key-value mappings
|
||||
*
|
||||
* @return Bookmark object found, or null for no hits
|
||||
*
|
||||
* @return array array of column definitions
|
||||
*/
|
||||
|
||||
function table()
|
||||
function pkeyGet($kv)
|
||||
{
|
||||
return array('id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
|
||||
|
||||
'profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
|
||||
'field' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
|
||||
'field_index' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
|
||||
|
||||
'value' => DB_DATAOBJECT_STR,
|
||||
'rel' => DB_DATAOBJECT_STR,
|
||||
'ref_profile' => DB_DATAOBJECT_ID,
|
||||
|
||||
'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
|
||||
'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
|
||||
return Memcached_DataObject::pkeyGet('Profile_detail', $kv);
|
||||
}
|
||||
|
||||
static function schemaDef()
|
||||
{
|
||||
// @fixme need a reverse key on (subscribed, subscriber) as well
|
||||
return array(new ColumnDef('id', 'integer',
|
||||
null, false, 'PRI'),
|
||||
|
||||
// @fixme need a unique index on these three
|
||||
new ColumnDef('profile_id', 'integer',
|
||||
null, false),
|
||||
new ColumnDef('field', 'varchar',
|
||||
16, false),
|
||||
new ColumnDef('field_index', 'integer',
|
||||
null, false),
|
||||
|
||||
new ColumnDef('value', 'text',
|
||||
null, true),
|
||||
new ColumnDef('rel', 'varchar',
|
||||
16, true),
|
||||
new ColumnDef('ref_profile', 'integer',
|
||||
null, true),
|
||||
|
||||
new ColumnDef('created', 'datetime',
|
||||
null, false),
|
||||
new ColumnDef('modified', 'datetime',
|
||||
null, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary hack to set up the compound index, since we can't do
|
||||
* it yet through regular Schema interface. (Coming for 1.0...)
|
||||
*
|
||||
* @param Schema $schema
|
||||
* @return void
|
||||
*/
|
||||
static function fixIndexes($schema)
|
||||
{
|
||||
try {
|
||||
// @fixme this won't be a unique index... SIGH
|
||||
$schema->createIndex('profile_detail', array('profile_id', 'field', 'field_index'));
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_ERR, __METHOD__ . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return key definitions for DB_DataObject
|
||||
*
|
||||
* DB_DataObject needs to know about keys that the table has; this function
|
||||
* defines them.
|
||||
*
|
||||
* @return array key definitions
|
||||
*/
|
||||
|
||||
function keys()
|
||||
{
|
||||
return array_keys($this->keyTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* return key definitions for Memcached_DataObject
|
||||
*
|
||||
* Our caching system uses the same key definitions, but uses a different
|
||||
* method to get them.
|
||||
*
|
||||
* @return array key definitions
|
||||
*/
|
||||
|
||||
function keyTypes()
|
||||
{
|
||||
// @fixme keys
|
||||
// need a sane key for reverse lookup too
|
||||
return array('id' => 'K');
|
||||
}
|
||||
|
||||
function sequenceKey()
|
||||
{
|
||||
return array('id', true);
|
||||
return array(
|
||||
'description'
|
||||
=> 'Additional profile details for the ExtendedProfile plugin',
|
||||
'fields' => array(
|
||||
'id' => array('type' => 'serial', 'not null' => true),
|
||||
'profile_id' => array('type' => 'int', 'not null' => true),
|
||||
'field_name' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 16,
|
||||
'not null' => true
|
||||
),
|
||||
'value_index' => array('type' => 'int'),
|
||||
'field_value' => array('type' => 'text'),
|
||||
'date' => array('type' => 'datetime'),
|
||||
'rel' => array('type' => 'varchar', 'length' => 16),
|
||||
'rel_profile' => array('type' => 'int'),
|
||||
'created' => array(
|
||||
'type' => 'datetime',
|
||||
'not null' => true
|
||||
),
|
||||
'modified' => array(
|
||||
'type' => 'timestamp',
|
||||
'not null' => true
|
||||
),
|
||||
),
|
||||
'primary key' => array('id'),
|
||||
'unique keys' => array(
|
||||
'profile_detail_profile_id_field_name_value_index'
|
||||
=> array('profile_id', 'field_name', 'value_index'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
113
plugins/ExtendedProfile/action/userautocomplete.php
Normal file
113
plugins/ExtendedProfile/action/userautocomplete.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action for showing Twitter-like JSON search results
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Search
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2011 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
class UserautocompleteAction extends Action
|
||||
{
|
||||
var $query;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean true if nothing goes wrong
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->query = $this->trimmed('term');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for users matching the query and spit the results out
|
||||
* as a quick-n-dirty JSON document
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showResults()
|
||||
{
|
||||
$people = array();
|
||||
|
||||
$profile = new Profile();
|
||||
|
||||
$search_engine = $profile->getSearchEngine('profile');
|
||||
$search_engine->set_sort_mode('nickname_desc');
|
||||
$search_engine->limit(0, 10);
|
||||
$search_engine->query(strtolower($this->query . '*'));
|
||||
|
||||
$cnt = $profile->find();
|
||||
|
||||
if ($cnt > 0) {
|
||||
|
||||
$sql = 'SELECT profile.* FROM profile, user WHERE profile.id = user.id '
|
||||
. ' AND LEFT(LOWER(profile.nickname), '
|
||||
. strlen($this->query)
|
||||
. ') = \'%s\' '
|
||||
. ' LIMIT 0, 10';
|
||||
|
||||
$profile->query(sprintf($sql, $this->query));
|
||||
}
|
||||
|
||||
while ($profile->fetch()) {
|
||||
$people[] = $profile->nickname;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
print json_encode($people);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need to write to the database?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
164
plugins/ExtendedProfile/css/profiledetail.css
Normal file
164
plugins/ExtendedProfile/css/profiledetail.css
Normal file
@ -0,0 +1,164 @@
|
||||
/* Note the #content is only needed to override weird crap in default styles */
|
||||
|
||||
#profiledetail .entity_actions {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#profiledetail #content h3 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#content table.extended-profile {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0px 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#content table.extended-profile th {
|
||||
color: #777;
|
||||
background-color: #ECECF2;
|
||||
width: 150px;
|
||||
text-align: right;
|
||||
padding: 2px 8px 2px 0px;
|
||||
}
|
||||
|
||||
#content table.extended-profile th.employer, #content table.extended-profile th.institution {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#content table.extended-profile td {
|
||||
padding: 2px 0px 2px 8px;
|
||||
}
|
||||
|
||||
.experience-item, .education-item {
|
||||
float: left;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.experience-item .label, .education-item .label {
|
||||
float: left;
|
||||
clear: left;
|
||||
position: relative;
|
||||
left: -8px;
|
||||
margin-right: 2px;
|
||||
margin-bottom: 8px;
|
||||
color: #777;
|
||||
background-color: #ECECF2;
|
||||
width: 150px;
|
||||
text-align: right;
|
||||
padding: 2px 8px 2px 0px;
|
||||
}
|
||||
|
||||
.experience-item .field, .education-item .field {
|
||||
float: left;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
#profiledetailsettings #content table.extended-profile td {
|
||||
padding: 0px 0px 0px 8px;
|
||||
}
|
||||
|
||||
#profiledetailsettings input {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.form_settings .extended-profile label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.extended-profile textarea {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.extended-profile input[type=text] {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.extended-profile .phone-item input[type=text], .extended-profile .im-item input[type=text], .extended-profile .website-item input[type=text] {
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
.extended-profile input.hasDatepicker {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.experience-item input[type=text], .education-item input[type=text] {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.extended-profile .current-checkbox {
|
||||
float: left;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.form_settings .extended-profile input.checkbox {
|
||||
margin-left: 0px;
|
||||
left: 0px;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.form_settings .extended-profile label.checkbox {
|
||||
max-width: 100%;
|
||||
float: none;
|
||||
display: inline;
|
||||
left: -20px;
|
||||
}
|
||||
|
||||
.extended-profile select {
|
||||
padding-right: 2px;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
.extended-profile a.add_row, .extended-profile a.remove_row {
|
||||
display: block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
overflow: hidden;
|
||||
background-image: url('../../../theme/rebase/images/icons/icons-01.gif');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.extended-profile a.remove_row {
|
||||
background-position: 0px -1252px;
|
||||
float: right;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
line-height: 4em;
|
||||
}
|
||||
|
||||
.extended-profile a.add_row {
|
||||
clear: both;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
left: 2px;
|
||||
background-position: 0px -1186px;
|
||||
width: 120px;
|
||||
padding-left: 20px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
#content table.extended-profile .supersizeme th {
|
||||
border-bottom: 28px solid #fff;
|
||||
}
|
||||
|
||||
#profiledetailsettings .experience-item, #profiledetailsettings .education-item {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#profiledetailsettings .education-item textarea {
|
||||
float: left;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#profiledetailsettings tr:last-child .experience-item, #profiledetailsettings tr:last-child .education-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#profiledetailsettings .experience-item a.add_row, #profiledetailsettings .education-item a.add_row {
|
||||
left: 160px;
|
||||
}
|
@ -21,27 +21,256 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to represent extended profile data
|
||||
*/
|
||||
class ExtendedProfile
|
||||
{
|
||||
protected $fields;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Profile $profile
|
||||
*/
|
||||
function __construct(Profile $profile)
|
||||
{
|
||||
$this->profile = $profile;
|
||||
$this->sections = $this->getSections();
|
||||
$this->user = $profile->getUser();
|
||||
$this->fields = $this->loadFields();
|
||||
$this->sections = $this->getSections();
|
||||
//common_debug(var_export($this->sections, true));
|
||||
|
||||
//common_debug(var_export($this->fields, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load extended profile fields
|
||||
*
|
||||
* @return array $fields the list of fields
|
||||
*/
|
||||
function loadFields()
|
||||
{
|
||||
$detail = new Profile_detail();
|
||||
$detail->profile_id = $this->profile->id;
|
||||
$detail->find();
|
||||
|
||||
while ($detail->get()) {
|
||||
$fields[$detail->field][] = clone($detail);
|
||||
$fields = array();
|
||||
|
||||
while ($detail->fetch()) {
|
||||
$fields[$detail->field_name][] = clone($detail);
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a the self-tags associated with this profile
|
||||
*
|
||||
* @return string the concatenated string of tags
|
||||
*/
|
||||
function getTags()
|
||||
{
|
||||
return implode(' ', $this->user->getSelfTags());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a simple string value. Checks for fields that should
|
||||
* be stored in the regular profile and returns values from it
|
||||
* if appropriate.
|
||||
*
|
||||
* @param string $name name of the detail field to get the
|
||||
* value from
|
||||
*
|
||||
* @return string the value
|
||||
*/
|
||||
function getTextValue($name)
|
||||
{
|
||||
$key = strtolower($name);
|
||||
$profileFields = array('fullname', 'location', 'bio');
|
||||
|
||||
if (in_array($key, $profileFields)) {
|
||||
return $this->profile->$name;
|
||||
} else if (array_key_exists($key, $this->fields)) {
|
||||
return $this->fields[$key][0]->field_value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getDateValue($name) {
|
||||
$key = strtolower($name);
|
||||
if (array_key_exists($key, $this->fields)) {
|
||||
return $this->fields[$key][0]->date;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: getPhones, getIms, and getWebsites pretty much do the same thing,
|
||||
// so refactor.
|
||||
function getPhones()
|
||||
{
|
||||
$phones = (isset($this->fields['phone'])) ? $this->fields['phone'] : null;
|
||||
$pArrays = array();
|
||||
|
||||
if (empty($phones)) {
|
||||
$pArrays[] = array(
|
||||
'label' => _m('Phone'),
|
||||
'index' => 0,
|
||||
'type' => 'phone',
|
||||
'vcard' => 'tel',
|
||||
'rel' => 'office',
|
||||
'value' => null
|
||||
);
|
||||
} else {
|
||||
for ($i = 0; $i < sizeof($phones); $i++) {
|
||||
$pa = array(
|
||||
'label' => _m('Phone'),
|
||||
'type' => 'phone',
|
||||
'index' => intval($phones[$i]->value_index),
|
||||
'rel' => $phones[$i]->rel,
|
||||
'value' => $phones[$i]->field_value,
|
||||
'vcard' => 'tel'
|
||||
);
|
||||
|
||||
$pArrays[] = $pa;
|
||||
}
|
||||
}
|
||||
return $pArrays;
|
||||
}
|
||||
|
||||
function getIms()
|
||||
{
|
||||
$ims = (isset($this->fields['im'])) ? $this->fields['im'] : null;
|
||||
$iArrays = array();
|
||||
|
||||
if (empty($ims)) {
|
||||
$iArrays[] = array(
|
||||
'label' => _m('IM'),
|
||||
'type' => 'im'
|
||||
);
|
||||
} else {
|
||||
for ($i = 0; $i < sizeof($ims); $i++) {
|
||||
$ia = array(
|
||||
'label' => _m('IM'),
|
||||
'type' => 'im',
|
||||
'index' => intval($ims[$i]->value_index),
|
||||
'rel' => $ims[$i]->rel,
|
||||
'value' => $ims[$i]->field_value,
|
||||
);
|
||||
|
||||
$iArrays[] = $ia;
|
||||
}
|
||||
}
|
||||
return $iArrays;
|
||||
}
|
||||
|
||||
function getWebsites()
|
||||
{
|
||||
$sites = (isset($this->fields['website'])) ? $this->fields['website'] : null;
|
||||
$wArrays = array();
|
||||
|
||||
if (empty($sites)) {
|
||||
$wArrays[] = array(
|
||||
'label' => _m('Website'),
|
||||
'type' => 'website'
|
||||
);
|
||||
} else {
|
||||
for ($i = 0; $i < sizeof($sites); $i++) {
|
||||
$wa = array(
|
||||
'label' => _m('Website'),
|
||||
'type' => 'website',
|
||||
'index' => intval($sites[$i]->value_index),
|
||||
'rel' => $sites[$i]->rel,
|
||||
'value' => $sites[$i]->field_value,
|
||||
);
|
||||
|
||||
$wArrays[] = $wa;
|
||||
}
|
||||
}
|
||||
return $wArrays;
|
||||
}
|
||||
|
||||
function getExperiences()
|
||||
{
|
||||
$companies = (isset($this->fields['company'])) ? $this->fields['company'] : null;
|
||||
$start = (isset($this->fields['start'])) ? $this->fields['start'] : null;
|
||||
$end = (isset($this->fields['end'])) ? $this->fields['end'] : null;
|
||||
|
||||
$eArrays = array();
|
||||
|
||||
if (empty($companies)) {
|
||||
$eArrays[] = array(
|
||||
'label' => _m('Employer'),
|
||||
'type' => 'experience',
|
||||
'company' => null,
|
||||
'start' => null,
|
||||
'end' => null,
|
||||
'current' => false,
|
||||
'index' => 0
|
||||
);
|
||||
} else {
|
||||
for ($i = 0; $i < sizeof($companies); $i++) {
|
||||
$ea = array(
|
||||
'label' => _m('Employer'),
|
||||
'type' => 'experience',
|
||||
'company' => $companies[$i]->field_value,
|
||||
'index' => intval($companies[$i]->value_index),
|
||||
'current' => $end[$i]->rel,
|
||||
'start' => $start[$i]->date,
|
||||
'end' => $end[$i]->date
|
||||
);
|
||||
$eArrays[] = $ea;
|
||||
}
|
||||
}
|
||||
return $eArrays;
|
||||
}
|
||||
|
||||
function getEducation()
|
||||
{
|
||||
$schools = (isset($this->fields['school'])) ? $this->fields['school'] : null;
|
||||
$degrees = (isset($this->fields['degree'])) ? $this->fields['degree'] : null;
|
||||
$descs = (isset($this->fields['degree_descr'])) ? $this->fields['degree_descr'] : null;
|
||||
$start = (isset($this->fields['school_start'])) ? $this->fields['school_start'] : null;
|
||||
$end = (isset($this->fields['school_end'])) ? $this->fields['school_end'] : null;
|
||||
$iArrays = array();
|
||||
|
||||
if (empty($schools)) {
|
||||
$iArrays[] = array(
|
||||
'type' => 'education',
|
||||
'label' => _m('Institution'),
|
||||
'school' => null,
|
||||
'degree' => null,
|
||||
'description' => null,
|
||||
'start' => null,
|
||||
'end' => null,
|
||||
'index' => 0
|
||||
);
|
||||
} else {
|
||||
for ($i = 0; $i < sizeof($schools); $i++) {
|
||||
$ia = array(
|
||||
'type' => 'education',
|
||||
'label' => _m('Institution'),
|
||||
'school' => $schools[$i]->field_value,
|
||||
'degree' => isset($degrees[$i]->field_value) ? $degrees[$i]->field_value : null,
|
||||
'description' => isset($descs[$i]->field_value) ? $descs[$i]->field_value : null,
|
||||
'index' => intval($schools[$i]->value_index),
|
||||
'start' => $start[$i]->date,
|
||||
'end' => $end[$i]->date
|
||||
);
|
||||
$iArrays[] = $ia;
|
||||
}
|
||||
}
|
||||
|
||||
return $iArrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the sections of the extended profile
|
||||
*
|
||||
* @return array the big list of sections and fields
|
||||
*/
|
||||
function getSections()
|
||||
{
|
||||
return array(
|
||||
@ -81,22 +310,9 @@ class ExtendedProfile
|
||||
'contact' => array(
|
||||
'label' => _m('Contact'),
|
||||
'fields' => array(
|
||||
'phone' => array(
|
||||
'label' => _m('Phone'),
|
||||
'type' => 'phone',
|
||||
'multi' => true,
|
||||
'vcard' => 'tel',
|
||||
),
|
||||
'im' => array(
|
||||
'label' => _m('IM'),
|
||||
'type' => 'im',
|
||||
'multi' => true,
|
||||
),
|
||||
'website' => array(
|
||||
'label' => _m('Websites'),
|
||||
'type' => 'website',
|
||||
'multi' => true,
|
||||
),
|
||||
'phone' => $this->getPhones(),
|
||||
'im' => $this->getIms(),
|
||||
'website' => $this->getWebsites()
|
||||
),
|
||||
),
|
||||
'personal' => array(
|
||||
@ -119,19 +335,13 @@ class ExtendedProfile
|
||||
'experience' => array(
|
||||
'label' => _m('Work experience'),
|
||||
'fields' => array(
|
||||
'experience' => array(
|
||||
'type' => 'experience',
|
||||
'label' => _m('Employer'),
|
||||
),
|
||||
'experience' => $this->getExperiences()
|
||||
),
|
||||
),
|
||||
'education' => array(
|
||||
'label' => _m('Education'),
|
||||
'fields' => array(
|
||||
'education' => array(
|
||||
'type' => 'education',
|
||||
'label' => _m('Institution'),
|
||||
),
|
||||
'education' => $this->getEducation()
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -21,13 +21,35 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class ExtendedProfileWidget extends Widget
|
||||
/**
|
||||
* Class for outputting a widget to display or edit
|
||||
* extended profiles
|
||||
*/
|
||||
class ExtendedProfileWidget extends Form
|
||||
{
|
||||
const EDITABLE=true;
|
||||
const EDITABLE = true;
|
||||
|
||||
/**
|
||||
* The parent profile
|
||||
*
|
||||
* @var Profile
|
||||
*/
|
||||
protected $profile;
|
||||
|
||||
/**
|
||||
* The extended profile
|
||||
*
|
||||
* @var Extended_profile
|
||||
*/
|
||||
protected $ext;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param XMLOutputter $out
|
||||
* @param Profile $profile
|
||||
* @param boolean $editable
|
||||
*/
|
||||
public function __construct(XMLOutputter $out=null, Profile $profile=null, $editable=false)
|
||||
{
|
||||
parent::__construct($out);
|
||||
@ -38,7 +60,37 @@ class ExtendedProfileWidget extends Widget
|
||||
$this->editable = $editable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the extended profile, or the edit form
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
if ($this->editable) {
|
||||
parent::show();
|
||||
} else {
|
||||
$this->showSections();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show form data
|
||||
*/
|
||||
public function formData()
|
||||
{
|
||||
// For JQuery UI modal dialog
|
||||
$this->out->elementStart(
|
||||
'div',
|
||||
array('id' => 'confirm-dialog', 'title' => 'Confirmation Required')
|
||||
);
|
||||
$this->out->text('Really delete this entry?');
|
||||
$this->out->elementEnd('div');
|
||||
$this->showSections();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show each section of the extended profile
|
||||
*/
|
||||
public function showSections()
|
||||
{
|
||||
$sections = $this->ext->getSections();
|
||||
foreach ($sections as $name => $section) {
|
||||
@ -46,21 +98,45 @@ class ExtendedProfileWidget extends Widget
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an extended profile section
|
||||
*
|
||||
* @param string $name name of the section
|
||||
* @param array $section array of fields for the section
|
||||
*/
|
||||
protected function showExtendedProfileSection($name, $section)
|
||||
{
|
||||
$this->out->element('h3', null, $section['label']);
|
||||
$this->out->elementStart('table', array('class' => 'extended-profile'));
|
||||
|
||||
foreach ($section['fields'] as $fieldName => $field) {
|
||||
|
||||
switch($fieldName) {
|
||||
case 'phone':
|
||||
case 'im':
|
||||
case 'website':
|
||||
case 'experience':
|
||||
case 'education':
|
||||
$this->showMultiple($fieldName, $field);
|
||||
break;
|
||||
default:
|
||||
$this->showExtendedProfileField($fieldName, $field);
|
||||
}
|
||||
}
|
||||
$this->out->elementEnd('table');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an extended profile field
|
||||
*
|
||||
* @param string $name name of the field
|
||||
* @param array $field set of key/value pairs for the field
|
||||
*/
|
||||
protected function showExtendedProfileField($name, $field)
|
||||
{
|
||||
$this->out->elementStart('tr');
|
||||
|
||||
$this->out->element('th', null, $field['label']);
|
||||
$this->out->element('th', str_replace(' ','_',strtolower($field['label'])), $field['label']);
|
||||
|
||||
$this->out->elementStart('td');
|
||||
if ($this->editable) {
|
||||
@ -73,30 +149,504 @@ class ExtendedProfileWidget extends Widget
|
||||
$this->out->elementEnd('tr');
|
||||
}
|
||||
|
||||
protected function showFieldValue($name, $field)
|
||||
{
|
||||
$this->out->text($name);
|
||||
protected function showMultiple($name, $fields) {
|
||||
foreach ($fields as $field) {
|
||||
$this->showExtendedProfileField($name, $field);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: showPhone, showIm and showWebsite all work the same, so
|
||||
// combine
|
||||
protected function showPhone($name, $field)
|
||||
{
|
||||
$this->out->elementStart('div', array('class' => 'phone-display'));
|
||||
$this->out->text($field['value']);
|
||||
if (!empty($field['rel'])) {
|
||||
$this->out->text(' (' . $field['rel'] . ')');
|
||||
}
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showIm($name, $field)
|
||||
{
|
||||
$this->out->elementStart('div', array('class' => 'im-display'));
|
||||
$this->out->text($field['value']);
|
||||
if (!empty($field['rel'])) {
|
||||
$this->out->text(' (' . $field['rel'] . ')');
|
||||
}
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showWebsite($name, $field)
|
||||
{
|
||||
$this->out->elementStart('div', array('class' => 'website-display'));
|
||||
|
||||
$url = $field['value'];
|
||||
|
||||
$this->out->element(
|
||||
"a",
|
||||
array(
|
||||
'href' => $url,
|
||||
'class' => 'extended-profile-link',
|
||||
'target' => "_blank"
|
||||
),
|
||||
$url
|
||||
);
|
||||
|
||||
if (!empty($field['rel'])) {
|
||||
$this->out->text(' (' . $field['rel'] . ')');
|
||||
}
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showEditableIm($name, $field)
|
||||
{
|
||||
$index = isset($field['index']) ? $field['index'] : 0;
|
||||
$id = "extprofile-$name-$index";
|
||||
$rel = $id . '-rel';
|
||||
$this->out->elementStart(
|
||||
'div', array(
|
||||
'id' => $id . '-edit',
|
||||
'class' => 'im-item'
|
||||
)
|
||||
);
|
||||
$this->out->input(
|
||||
$id,
|
||||
null,
|
||||
isset($field['value']) ? $field['value'] : null
|
||||
);
|
||||
$this->out->dropdown(
|
||||
$id . '-rel',
|
||||
'Type',
|
||||
array(
|
||||
'jabber' => 'Jabber',
|
||||
'gtalk' => 'GTalk',
|
||||
'aim' => 'AIM',
|
||||
'yahoo' => 'Yahoo! Messenger',
|
||||
'msn' => 'MSN',
|
||||
'skype' => 'Skype',
|
||||
'other' => 'Other'
|
||||
),
|
||||
null,
|
||||
false,
|
||||
isset($field['rel']) ? $field['rel'] : null
|
||||
);
|
||||
|
||||
$this->showMultiControls();
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showEditablePhone($name, $field)
|
||||
{
|
||||
$index = isset($field['index']) ? $field['index'] : 0;
|
||||
$id = "extprofile-$name-$index";
|
||||
$rel = $id . '-rel';
|
||||
$this->out->elementStart(
|
||||
'div', array(
|
||||
'id' => $id . '-edit',
|
||||
'class' => 'phone-item'
|
||||
)
|
||||
);
|
||||
$this->out->input(
|
||||
$id,
|
||||
null,
|
||||
isset($field['value']) ? $field['value'] : null
|
||||
);
|
||||
$this->out->dropdown(
|
||||
$id . '-rel',
|
||||
'Type',
|
||||
array(
|
||||
'office' => 'Office',
|
||||
'mobile' => 'Mobile',
|
||||
'home' => 'Home',
|
||||
'pager' => 'Pager',
|
||||
'other' => 'Other'
|
||||
),
|
||||
null,
|
||||
false,
|
||||
isset($field['rel']) ? $field['rel'] : null
|
||||
);
|
||||
|
||||
$this->showMultiControls();
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showEditableWebsite($name, $field)
|
||||
{
|
||||
$index = isset($field['index']) ? $field['index'] : 0;
|
||||
$id = "extprofile-$name-$index";
|
||||
$rel = $id . '-rel';
|
||||
$this->out->elementStart(
|
||||
'div', array(
|
||||
'id' => $id . '-edit',
|
||||
'class' => 'website-item'
|
||||
)
|
||||
);
|
||||
$this->out->input(
|
||||
$id,
|
||||
null,
|
||||
isset($field['value']) ? $field['value'] : null
|
||||
);
|
||||
$this->out->dropdown(
|
||||
$id . '-rel',
|
||||
'Type',
|
||||
array(
|
||||
'blog' => 'Blog',
|
||||
'homepage' => 'Homepage',
|
||||
'facebook' => 'Facebook',
|
||||
'linkedin' => 'LinkedIn',
|
||||
'flickr' => 'Flickr',
|
||||
'google' => 'Google Profile',
|
||||
'other' => 'Other',
|
||||
'twitter' => 'Twitter'
|
||||
),
|
||||
null,
|
||||
false,
|
||||
isset($field['rel']) ? $field['rel'] : null
|
||||
);
|
||||
|
||||
$this->showMultiControls();
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showExperience($name, $field)
|
||||
{
|
||||
$this->out->elementStart('div', 'experience-item');
|
||||
$this->out->element('div', 'label', _m('Company'));
|
||||
|
||||
if (!empty($field['company'])) {
|
||||
$this->out->element('div', 'field', $field['company']);
|
||||
|
||||
$this->out->element('div', 'label', _m('Start'));
|
||||
$this->out->element(
|
||||
'div',
|
||||
array('class' => 'field date'),
|
||||
date('j M Y', strtotime($field['start'])
|
||||
)
|
||||
);
|
||||
$this->out->element('div', 'label', _m('End'));
|
||||
$this->out->element(
|
||||
'div',
|
||||
array('class' => 'field date'),
|
||||
date('j M Y', strtotime($field['end'])
|
||||
)
|
||||
);
|
||||
|
||||
if ($field['current']) {
|
||||
$this->out->element(
|
||||
'div',
|
||||
array('class' => 'field current'),
|
||||
'(' . _m('Current') . ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showEditableExperience($name, $field)
|
||||
{
|
||||
$index = isset($field['index']) ? $field['index'] : 0;
|
||||
$id = "extprofile-$name-$index";
|
||||
$this->out->elementStart(
|
||||
'div', array(
|
||||
'id' => $id . '-edit',
|
||||
'class' => 'experience-item'
|
||||
)
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('Company'));
|
||||
$this->out->input(
|
||||
$id,
|
||||
null,
|
||||
isset($field['company']) ? $field['company'] : null
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('Start'));
|
||||
$this->out->input(
|
||||
$id . '-start',
|
||||
null,
|
||||
isset($field['start']) ? date('j M Y', strtotime($field['start'])) : null
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('End'));
|
||||
|
||||
$this->out->input(
|
||||
$id . '-end',
|
||||
null,
|
||||
isset($field['end']) ? date('j M Y', strtotime($field['end'])) : null
|
||||
);
|
||||
$this->out->hidden(
|
||||
$id . '-current',
|
||||
'false'
|
||||
);
|
||||
$this->out->elementStart('div', 'current-checkbox');
|
||||
$this->out->checkbox(
|
||||
$id . '-current',
|
||||
_m('Current'),
|
||||
$field['current']
|
||||
);
|
||||
$this->out->elementEnd('div');
|
||||
|
||||
$this->showMultiControls();
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showEducation($name, $field)
|
||||
{
|
||||
$this->out->elementStart('div', 'education-item');
|
||||
$this->out->element('div', 'label', _m('Institution'));
|
||||
$this->out->element('div', 'field', $field['school']);
|
||||
$this->out->element('div', 'label', _m('Degree'));
|
||||
$this->out->element('div', 'field', $field['degree']);
|
||||
$this->out->element('div', 'label', _m('Description'));
|
||||
$this->out->element('div', 'field', $field['description']);
|
||||
$this->out->element('div', 'label', _m('Start'));
|
||||
$this->out->element(
|
||||
'div',
|
||||
array('class' => 'field date'),
|
||||
date('j M Y', strtotime($field['start'])
|
||||
)
|
||||
);
|
||||
$this->out->element('div', 'label', _m('End'));
|
||||
$this->out->element(
|
||||
'div',
|
||||
array('class' => 'field date'),
|
||||
date('j M Y', strtotime($field['end'])
|
||||
)
|
||||
);
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
protected function showEditableEducation($name, $field)
|
||||
{
|
||||
$index = isset($field['index']) ? $field['index'] : 0;
|
||||
$id = "extprofile-$name-$index";
|
||||
$this->out->elementStart(
|
||||
'div', array(
|
||||
'id' => $id . '-edit',
|
||||
'class' => 'education-item'
|
||||
)
|
||||
);
|
||||
$this->out->element('div', 'label', _m('Institution'));
|
||||
$this->out->input(
|
||||
$id,
|
||||
null,
|
||||
isset($field['school']) ? $field['school'] : null
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('Degree'));
|
||||
$this->out->input(
|
||||
$id . '-degree',
|
||||
null,
|
||||
isset($field['degree']) ? $field['degree'] : null
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('Description'));
|
||||
$this->out->element('div', 'field', $field['description']);
|
||||
|
||||
$this->out->textarea(
|
||||
$id . '-description',
|
||||
null,
|
||||
isset($field['description']) ? $field['description'] : null
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('Start'));
|
||||
$this->out->input(
|
||||
$id . '-start',
|
||||
null,
|
||||
isset($field['start']) ? date('j M Y', strtotime($field['start'])) : null
|
||||
);
|
||||
|
||||
$this->out->element('div', 'label', _m('End'));
|
||||
$this->out->input(
|
||||
$id . '-end',
|
||||
null,
|
||||
isset($field['end']) ? date('j M Y', strtotime($field['end'])) : null
|
||||
);
|
||||
|
||||
$this->showMultiControls();
|
||||
$this->out->elementEnd('div');
|
||||
}
|
||||
|
||||
function showMultiControls()
|
||||
{
|
||||
$this->out->element(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'remove_row',
|
||||
'href' => 'javascript://',
|
||||
'style' => 'display: none;'
|
||||
),
|
||||
'-'
|
||||
);
|
||||
|
||||
$this->out->element(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'add_row',
|
||||
'href' => 'javascript://',
|
||||
'style' => 'display: none;'
|
||||
),
|
||||
'Add another item'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the value of a field
|
||||
*
|
||||
* @param string $name name of the field
|
||||
* @param array $field set of key/value pairs for the field
|
||||
*/
|
||||
protected function showFieldValue($name, $field)
|
||||
{
|
||||
$type = strval(@$field['type']);
|
||||
|
||||
switch($type)
|
||||
{
|
||||
case '':
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
$this->out->text($this->ext->getTextValue($name));
|
||||
break;
|
||||
case 'date':
|
||||
$value = $this->ext->getDateValue($name);
|
||||
if (!empty($value)) {
|
||||
$this->out->element(
|
||||
'div',
|
||||
array('class' => 'field date'),
|
||||
date('j M Y', strtotime($value))
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'person':
|
||||
$this->out->text($this->ext->getTextValue($name));
|
||||
break;
|
||||
case 'tags':
|
||||
$this->out->text($this->ext->getTags());
|
||||
break;
|
||||
case 'phone':
|
||||
$this->showPhone($name, $field);
|
||||
break;
|
||||
case 'website':
|
||||
$this->showWebsite($name, $field);
|
||||
break;
|
||||
case 'im':
|
||||
$this->showIm($name, $field);
|
||||
break;
|
||||
case 'experience':
|
||||
$this->showExperience($name, $field);
|
||||
break;
|
||||
case 'education':
|
||||
$this->showEducation($name, $field);
|
||||
break;
|
||||
default:
|
||||
$this->out->text("TYPE: $type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an editable version of the field
|
||||
*
|
||||
* @param string $name name fo the field
|
||||
* @param array $field array of key/value pairs for the field
|
||||
*/
|
||||
protected function showEditableField($name, $field)
|
||||
{
|
||||
$out = $this->out;
|
||||
//$out = new HTMLOutputter();
|
||||
// @fixme
|
||||
|
||||
$type = strval(@$field['type']);
|
||||
$id = "extprofile-" . $name;
|
||||
|
||||
$value = 'placeholder';
|
||||
|
||||
switch ($type) {
|
||||
case '':
|
||||
case 'text':
|
||||
$out->input($id, null, $value);
|
||||
$out->input($id, null, $this->ext->getTextValue($name));
|
||||
break;
|
||||
case 'date':
|
||||
$out->input(
|
||||
$id,
|
||||
null,
|
||||
date('j M Y', strtotime($this->ext->getDateValue($name)))
|
||||
);
|
||||
break;
|
||||
case 'person':
|
||||
$out->input($id, null, $this->ext->getTextValue($name));
|
||||
break;
|
||||
case 'textarea':
|
||||
$out->textarea($id, null, $value);
|
||||
$out->textarea($id, null, $this->ext->getTextValue($name));
|
||||
break;
|
||||
case 'tags':
|
||||
$out->input($id, null, $this->ext->getTags());
|
||||
break;
|
||||
case 'phone':
|
||||
$this->showEditablePhone($name, $field);
|
||||
break;
|
||||
case 'im':
|
||||
$this->showEditableIm($name, $field);
|
||||
break;
|
||||
case 'website':
|
||||
$this->showEditableWebsite($name, $field);
|
||||
break;
|
||||
case 'experience':
|
||||
$this->showEditableExperience($name, $field);
|
||||
break;
|
||||
case 'education':
|
||||
$this->showEditableEducation($name, $field);
|
||||
break;
|
||||
default:
|
||||
$out->input($id, null, "TYPE: $type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formActions()
|
||||
{
|
||||
$this->out->submit(
|
||||
'save',
|
||||
_m('BUTTON','Save'),
|
||||
'submit form_action-secondary',
|
||||
'save',
|
||||
_('Save details')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* ID of the form
|
||||
*
|
||||
* @return string ID of the form
|
||||
*/
|
||||
|
||||
function id()
|
||||
{
|
||||
return 'profile-details-' . $this->profile->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* class of the form
|
||||
*
|
||||
* @return string of the form class
|
||||
*/
|
||||
|
||||
function formClass()
|
||||
{
|
||||
return 'form_profile_details form_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action of the form
|
||||
*
|
||||
* @return string URL of the action
|
||||
*/
|
||||
|
||||
function action()
|
||||
{
|
||||
return common_local_url('profiledetailsettings');
|
||||
}
|
||||
}
|
||||
|
144
plugins/ExtendedProfile/js/profiledetail.js
Normal file
144
plugins/ExtendedProfile/js/profiledetail.js
Normal file
@ -0,0 +1,144 @@
|
||||
var SN_EXTENDED = SN_EXTENDED || {};
|
||||
|
||||
SN_EXTENDED.reorder = function(cls) {
|
||||
|
||||
var divs = $('div[class=' + cls + ']');
|
||||
|
||||
$(divs).each(function(i, div) {
|
||||
$(div).find('a.add_row').hide();
|
||||
$(div).find('a.remove_row').show();
|
||||
SN_EXTENDED.replaceIndex(SN_EXTENDED.rowIndex(div), i);
|
||||
});
|
||||
|
||||
var lastDiv = $(divs).last().closest('tr');
|
||||
lastDiv.addClass('supersizeme');
|
||||
|
||||
$(divs).last().find('a.add_row').show();
|
||||
|
||||
if (divs.length == 1) {
|
||||
$(divs).find('a.remove_row').fadeOut("slow");
|
||||
}
|
||||
};
|
||||
|
||||
SN_EXTENDED.rowIndex = function(div) {
|
||||
var idstr = $(div).attr('id');
|
||||
var id = idstr.match(/\d+/);
|
||||
return id;
|
||||
};
|
||||
|
||||
SN_EXTENDED.rowCount = function(cls) {
|
||||
var divs = $.find('div[class=' + cls + ']');
|
||||
return divs.length;
|
||||
};
|
||||
|
||||
SN_EXTENDED.replaceIndex = function(elem, oldIndex, newIndex) {
|
||||
$(elem).find('*').each(function() {
|
||||
$.each(this.attributes, function(i, attrib) {
|
||||
var regexp = /extprofile-.*-\d.*/;
|
||||
var value = attrib.value;
|
||||
var match = value.match(regexp);
|
||||
if (match !== null) {
|
||||
attrib.value = value.replace("-" + oldIndex, "-" + newIndex);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
SN_EXTENDED.resetRow = function(elem) {
|
||||
$(elem).find('input, textarea').attr('value', '');
|
||||
$(elem).find('input').removeAttr('disabled');
|
||||
$(elem).find("select option[value='office']").attr("selected", true);
|
||||
$(elem).find("input:checkbox").attr('checked', false);
|
||||
$(elem).find("input[name$=-start], input[name$=-end]").each(function() {
|
||||
$(this).removeClass('hasDatepicker');
|
||||
$(this).datepicker({ dateFormat: 'd M yy' });
|
||||
});
|
||||
};
|
||||
|
||||
SN_EXTENDED.addRow = function() {
|
||||
var div = $(this).closest('div');
|
||||
var id = div.attr('id');
|
||||
var cls = div.attr('class');
|
||||
var index = id.match(/\d+/);
|
||||
var newIndex = parseInt(index) + 1;
|
||||
var newtr = $(div).closest('tr').removeClass('supersizeme').clone();
|
||||
SN_EXTENDED.replaceIndex(newtr, index, newIndex);
|
||||
SN_EXTENDED.resetRow(newtr);
|
||||
$(div).closest('tr').after(newtr);
|
||||
SN_EXTENDED.reorder(cls);
|
||||
};
|
||||
|
||||
SN_EXTENDED.removeRow = function() {
|
||||
|
||||
var div = $(this).closest('div');
|
||||
var id = $(div).attr('id');
|
||||
var cls = $(div).attr('class');
|
||||
var that = this;
|
||||
|
||||
$("#confirm-dialog").dialog({
|
||||
buttons : {
|
||||
"Confirm" : function() {
|
||||
$(this).dialog("close");
|
||||
var target = $(that).closest('tr');
|
||||
target.fadeOut("slow", function() {
|
||||
$(target).remove();
|
||||
SN_EXTENDED.reorder(cls);
|
||||
});
|
||||
},
|
||||
"Cancel" : function() {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var cnt = SN_EXTENDED.rowCount(cls);
|
||||
|
||||
if (cnt > 1) {
|
||||
$("#confirm-dialog").dialog("open");
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$("#confirm-dialog").dialog({
|
||||
autoOpen: false,
|
||||
modal: true
|
||||
});
|
||||
|
||||
$("input#extprofile-manager").autocomplete({
|
||||
source: 'finduser',
|
||||
minLength: 2 });
|
||||
|
||||
$("input[name$=-start], input[name$=-end], #extprofile-birthday").datepicker({ dateFormat: 'd M yy' });
|
||||
|
||||
var multifields = ["phone-item", "experience-item", "education-item", "im-item", 'website-item'];
|
||||
|
||||
for (f in multifields) {
|
||||
SN_EXTENDED.reorder(multifields[f]);
|
||||
}
|
||||
|
||||
$("input#extprofile-manager").autocomplete({
|
||||
source: 'finduser',
|
||||
minLength: 2 });
|
||||
|
||||
$('.add_row').live('click', SN_EXTENDED.addRow);
|
||||
$('.remove_row').live('click', SN_EXTENDED.removeRow);
|
||||
|
||||
$('input:checkbox[name$=current]').each(function() {
|
||||
var input = $(this).parent().siblings('input[id$=-end]');
|
||||
if ($(this).is(':checked')) {
|
||||
$(input).attr('disabled', 'true');
|
||||
}
|
||||
});
|
||||
|
||||
$('input:checkbox[name$=current]').live('click', function() {
|
||||
var input = $(this).parent().siblings('input[id$=-end]');
|
||||
if ($(this).is(':checked')) {
|
||||
$(input).val('');
|
||||
$(input).attr('disabled', 'true');
|
||||
} else {
|
||||
$(input).removeAttr('disabled');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
@ -1,22 +0,0 @@
|
||||
/* Note the #content is only needed to override weird crap in default styles */
|
||||
|
||||
#content table.extended-profile {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 8px;
|
||||
}
|
||||
#content table.extended-profile th {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
width: 150px;
|
||||
|
||||
padding-top: 0; /* override bizarre theme defaults */
|
||||
|
||||
text-align: right;
|
||||
padding-right: 8px;
|
||||
}
|
||||
#content table.extended-profile td {
|
||||
padding: 0; /* override bizarre theme defaults */
|
||||
|
||||
padding-left: 8px;
|
||||
}
|
@ -21,8 +21,9 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class ProfileDetailAction extends ProfileAction
|
||||
class ProfileDetailAction extends ShowstreamAction
|
||||
{
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
@ -33,28 +34,18 @@ class ProfileDetailAction extends ProfileAction
|
||||
return $this->profile->getFancyName();
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
{
|
||||
$nav = new PersonalGroupNav($this);
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showStylesheets() {
|
||||
parent::showStylesheets();
|
||||
$this->cssLink('plugins/ExtendedProfile/profiledetail.css');
|
||||
$this->cssLink('plugins/ExtendedProfile/css/profiledetail.css');
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$cur = common_current_user();
|
||||
if ($cur && $cur->id == $this->profile->id) { // your own page
|
||||
$this->elementStart('div', 'entity_actions');
|
||||
$this->elementStart('ul');
|
||||
$this->elementStart('li', 'entity_edit');
|
||||
$this->element('a', array('href' => common_local_url('profiledetailsettings'),
|
||||
// TRANS: Link title for link on user profile.
|
||||
@ -62,6 +53,7 @@ class ProfileDetailAction extends ProfileAction
|
||||
// TRANS: Link text for link on user profile.
|
||||
_m('Edit'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class ProfileDetailSettingsAction extends AccountSettingsAction
|
||||
class ProfileDetailSettingsAction extends ProfileSettingsAction
|
||||
{
|
||||
|
||||
function title()
|
||||
@ -43,13 +43,38 @@ class ProfileDetailSettingsAction extends AccountSettingsAction
|
||||
|
||||
function showStylesheets() {
|
||||
parent::showStylesheets();
|
||||
$this->cssLink('plugins/ExtendedProfile/profiledetail.css');
|
||||
$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 handle($args)
|
||||
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()
|
||||
{
|
||||
$this->showPage();
|
||||
// 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()
|
||||
@ -57,7 +82,554 @@ class ProfileDetailSettingsAction extends AccountSettingsAction
|
||||
$cur = common_current_user();
|
||||
$profile = $cur->getProfile();
|
||||
|
||||
$widget = new ExtendedProfileWidget($this, $profile, ExtendedProfileWidget::EDITABLE);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user