Implemented an extended user profile based on a patch from Jethro Carr (issue 510).
Changes with respect to the original patch: - use Gconf instead of separate table / data scheme - better form validation for URLs and emails - no htmlentity-encoded contents in the database (pluf automatically safe-encodes stuff before it writes out contents into templates) - add visual separators in the form views to have a distinct view of basic (important) data and other data which are only displayed in the public profile - give a hint about the maximum display size of 60x60 px^2 and use max-width and max-height in the templates to avoid nasty distortions by the browser - use target=_blank and rel=nofollow on the twitter and website links in the profile - some whitespace / formatting / code style fixes
This commit is contained in:
parent
874b5aa7e9
commit
784c9718eb
@ -24,13 +24,15 @@
|
|||||||
/**
|
/**
|
||||||
* Update user's details.
|
* Update user's details.
|
||||||
*/
|
*/
|
||||||
class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
||||||
{
|
{
|
||||||
public $user = null;
|
public $user = null;
|
||||||
|
|
||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
$this->user = $extra['user'];
|
$this->user = $extra['user'];
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('First name'),
|
'label' => __('First name'),
|
||||||
@ -66,7 +68,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
'initial' => $this->user->language,
|
'initial' => $this->user->language,
|
||||||
'widget' => 'Pluf_Form_Widget_SelectInput',
|
'widget' => 'Pluf_Form_Widget_SelectInput',
|
||||||
'widget_attrs' => array(
|
'widget_attrs' => array(
|
||||||
'choices' =>
|
'choices' =>
|
||||||
Pluf_L10n::getInstalledLanguages()
|
Pluf_L10n::getInstalledLanguages()
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -93,6 +95,66 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields['description'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Description'),
|
||||||
|
'initial' => $user_data->description,
|
||||||
|
'widget_attrs' => array('rows' => 3,
|
||||||
|
'cols' => 40),
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['twitter'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Twitter username'),
|
||||||
|
'initial' => $user_data->twitter,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['public_email'] = new Pluf_Form_Field_Email(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Public email address'),
|
||||||
|
'initial' => $user_data->public_email,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['website'] = new Pluf_Form_Field_Url(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Website URL'),
|
||||||
|
'initial' => $user_data->website,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['custom_avatar'] = new Pluf_Form_Field_File(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Upload custom avatar'),
|
||||||
|
'initial' => '',
|
||||||
|
'max_size' => Pluf::f('max_upload_size', 2097152),
|
||||||
|
'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/avatars',
|
||||||
|
'upload_path_create' => true,
|
||||||
|
'upload_overwrite' => true,
|
||||||
|
'file_name' => 'user_'.$this->user->id.'_%s'),
|
||||||
|
'help_text' => __('An image file with a width and height not larger than 60 pixels (bigger images are scaled down).'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['remove_custom_avatar'] = new Pluf_Form_Field_Boolean(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Remove custom avatar'),
|
||||||
|
'initial' => false,
|
||||||
|
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
||||||
|
'widget_attrs' => array(),
|
||||||
|
'help_text' => __('Tick this to delete the custom avatar.'),
|
||||||
|
));
|
||||||
|
|
||||||
if ($extra['request']->user->administrator) {
|
if ($extra['request']->user->administrator) {
|
||||||
$this->fields['staff'] = new Pluf_Form_Field_Boolean(
|
$this->fields['staff'] = new Pluf_Form_Field_Boolean(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
@ -136,8 +198,37 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
$update_pass = true;
|
$update_pass = true;
|
||||||
}
|
}
|
||||||
$this->user->setFromFormData($this->cleaned_data);
|
$this->user->setFromFormData($this->cleaned_data);
|
||||||
|
|
||||||
if ($commit) {
|
if ($commit) {
|
||||||
$this->user->update();
|
$this->user->update();
|
||||||
|
|
||||||
|
// FIXME: go the extra mile and check the input lengths for
|
||||||
|
// all fields here!
|
||||||
|
// FIXME: this is all doubled in UserAccount!
|
||||||
|
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
|
// Add or remove avatar - we need to do this here because every
|
||||||
|
// single setter directly leads to a save in the database
|
||||||
|
if ($user_data->avatar != '' &&
|
||||||
|
($this->cleaned_data['remove_custom_avatar'] == 1 ||
|
||||||
|
$this->cleaned_data['custom_avatar'] != '')) {
|
||||||
|
$avatar_path = Pluf::f('upload_path').'/avatars/'.basename($user_data->avatar);
|
||||||
|
if (basename($avatar_path) != '' && is_file($avatar_path)) {
|
||||||
|
unlink($avatar_path);
|
||||||
|
}
|
||||||
|
$user_data->avatar = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
$user_data->avatar = $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_data->description = $this->cleaned_data['description'];
|
||||||
|
$user_data->twitter = $this->cleaned_data['twitter'];
|
||||||
|
$user_data->public_email = $this->cleaned_data['public_email'];
|
||||||
|
$user_data->website = $this->cleaned_data['website'];
|
||||||
|
|
||||||
if ($update_pass) {
|
if ($update_pass) {
|
||||||
/**
|
/**
|
||||||
* [signal]
|
* [signal]
|
||||||
@ -170,7 +261,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
{
|
{
|
||||||
$last_name = trim($this->cleaned_data['last_name']);
|
$last_name = trim($this->cleaned_data['last_name']);
|
||||||
if ($last_name == mb_strtoupper($last_name)) {
|
if ($last_name == mb_strtoupper($last_name)) {
|
||||||
return mb_convert_case(mb_strtolower($last_name),
|
return mb_convert_case(mb_strtolower($last_name),
|
||||||
MB_CASE_TITLE, 'UTF-8');
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
return $last_name;
|
return $last_name;
|
||||||
@ -183,7 +274,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
throw new Pluf_Form_Invalid(__('--- is not a valid first name.'));
|
throw new Pluf_Form_Invalid(__('--- is not a valid first name.'));
|
||||||
}
|
}
|
||||||
if ($first_name == mb_strtoupper($first_name)) {
|
if ($first_name == mb_strtoupper($first_name)) {
|
||||||
$first_name = mb_convert_case(mb_strtolower($first_name),
|
$first_name = mb_convert_case(mb_strtolower($first_name),
|
||||||
MB_CASE_TITLE, 'UTF-8');
|
MB_CASE_TITLE, 'UTF-8');
|
||||||
}
|
}
|
||||||
return $first_name;
|
return $first_name;
|
||||||
@ -201,12 +292,23 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form
|
|||||||
return $email;
|
return $email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clean_custom_avatar()
|
||||||
|
{
|
||||||
|
// Just png, jpeg/jpg or gif
|
||||||
|
if (!preg_match('/\.(png|jpg|jpeg|gif)$/i', $this->cleaned_data['custom_avatar']) &&
|
||||||
|
$this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
@unlink(Pluf::f('upload_path').'/avatars/'.$this->cleaned_data['custom_avatar']);
|
||||||
|
throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the 2 passwords are the same.
|
* Check to see if the two passwords are the same.
|
||||||
*/
|
*/
|
||||||
public function clean()
|
public function clean()
|
||||||
{
|
{
|
||||||
if (!isset($this->errors['password'])
|
if (!isset($this->errors['password'])
|
||||||
&& !isset($this->errors['password2'])) {
|
&& !isset($this->errors['password2'])) {
|
||||||
$password1 = $this->cleaned_data['password'];
|
$password1 = $this->cleaned_data['password'];
|
||||||
$password2 = $this->cleaned_data['password2'];
|
$password2 = $this->cleaned_data['password2'];
|
||||||
|
@ -33,6 +33,8 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
public function initFields($extra=array())
|
public function initFields($extra=array())
|
||||||
{
|
{
|
||||||
$this->user = $extra['user'];
|
$this->user = $extra['user'];
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('First name'),
|
'label' => __('First name'),
|
||||||
@ -92,6 +94,66 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$this->fields['description'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Description'),
|
||||||
|
'initial' => $user_data->description,
|
||||||
|
'widget_attrs' => array('rows' => 3,
|
||||||
|
'cols' => 40),
|
||||||
|
'widget' => 'Pluf_Form_Widget_TextareaInput',
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['twitter'] = new Pluf_Form_Field_Varchar(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Twitter username'),
|
||||||
|
'initial' => $user_data->twitter,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['public_email'] = new Pluf_Form_Field_Email(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Public email address'),
|
||||||
|
'initial' => $user_data->public_email,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['website'] = new Pluf_Form_Field_Url(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Website URL'),
|
||||||
|
'initial' => $user_data->website,
|
||||||
|
'widget_attrs' => array(
|
||||||
|
'maxlength' => 50,
|
||||||
|
'size' => 15,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['custom_avatar'] = new Pluf_Form_Field_File(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Upload custom avatar'),
|
||||||
|
'initial' => '',
|
||||||
|
'max_size' => Pluf::f('max_upload_size', 2097152),
|
||||||
|
'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/avatars',
|
||||||
|
'upload_path_create' => true,
|
||||||
|
'upload_overwrite' => true,
|
||||||
|
'file_name' => 'user_'.$this->user->id.'_%s'),
|
||||||
|
'help_text' => __('An image file with a width and height not larger than 60 pixels (bigger images are scaled down).'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->fields['remove_custom_avatar'] = new Pluf_Form_Field_Boolean(
|
||||||
|
array('required' => false,
|
||||||
|
'label' => __('Remove custom avatar'),
|
||||||
|
'initial' => false,
|
||||||
|
'widget' => 'Pluf_Form_Widget_CheckboxInput',
|
||||||
|
'widget_attrs' => array(),
|
||||||
|
'help_text' => __('Tick this to delete the custom avatar.'),
|
||||||
|
));
|
||||||
|
|
||||||
$this->fields['public_key'] = new Pluf_Form_Field_Varchar(
|
$this->fields['public_key'] = new Pluf_Form_Field_Varchar(
|
||||||
array('required' => false,
|
array('required' => false,
|
||||||
'label' => __('Add a public key'),
|
'label' => __('Add a public key'),
|
||||||
@ -138,7 +200,7 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
'email' => $new_email,
|
'email' => $new_email,
|
||||||
'user'=> $this->user,
|
'user'=> $this->user,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$tmpl = new Pluf_Template('idf/user/changeemail-email.txt');
|
$tmpl = new Pluf_Template('idf/user/changeemail-email.txt');
|
||||||
$text_email = $tmpl->render($context);
|
$text_email = $tmpl->render($context);
|
||||||
$email = new Pluf_Mail(Pluf::f('from_email'), $new_email,
|
$email = new Pluf_Mail(Pluf::f('from_email'), $new_email,
|
||||||
@ -157,8 +219,37 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
$key->create();
|
$key->create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($commit) {
|
if ($commit) {
|
||||||
$this->user->update();
|
$this->user->update();
|
||||||
|
|
||||||
|
// FIXME: go the extra mile and check the input lengths for
|
||||||
|
// all fields here!
|
||||||
|
// FIXME: this is all doubled in admin/UserUpdate!
|
||||||
|
|
||||||
|
$user_data = IDF_UserData::factory($this->user);
|
||||||
|
|
||||||
|
// Add or remove avatar - we need to do this here because every
|
||||||
|
// single setter directly leads to a save in the database
|
||||||
|
if ($user_data->avatar != '' &&
|
||||||
|
($this->cleaned_data['remove_custom_avatar'] == 1 ||
|
||||||
|
$this->cleaned_data['custom_avatar'] != '')) {
|
||||||
|
$avatar_path = Pluf::f('upload_path').'/avatars/'.basename($user_data->avatar);
|
||||||
|
if (basename($avatar_path) != '' && is_file($avatar_path)) {
|
||||||
|
unlink($avatar_path);
|
||||||
|
}
|
||||||
|
$user_data->avatar = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
$user_data->avatar = $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_data->description = $this->cleaned_data['description'];
|
||||||
|
$user_data->twitter = $this->cleaned_data['twitter'];
|
||||||
|
$user_data->public_email = $this->cleaned_data['public_email'];
|
||||||
|
$user_data->website = $this->cleaned_data['website'];
|
||||||
|
|
||||||
if ($update_pass) {
|
if ($update_pass) {
|
||||||
/**
|
/**
|
||||||
* [signal]
|
* [signal]
|
||||||
@ -266,6 +357,19 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clean_custom_avatar()
|
||||||
|
{
|
||||||
|
// Just png, jpeg/jpg or gif
|
||||||
|
if (!preg_match('/\.(png|jpg|jpeg|gif)$/i', $this->cleaned_data['custom_avatar']) &&
|
||||||
|
$this->cleaned_data['custom_avatar'] != '') {
|
||||||
|
@unlink(Pluf::f('upload_path').'/avatars/'.$this->cleaned_data['custom_avatar']);
|
||||||
|
throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.'));
|
||||||
|
}
|
||||||
|
return $this->cleaned_data['custom_avatar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function clean_last_name()
|
function clean_last_name()
|
||||||
{
|
{
|
||||||
$last_name = trim($this->cleaned_data['last_name']);
|
$last_name = trim($this->cleaned_data['last_name']);
|
||||||
@ -322,4 +426,6 @@ class IDF_Form_UserAccount extends Pluf_Form
|
|||||||
|
|
||||||
return $this->cleaned_data;
|
return $this->cleaned_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class IDF_Gconf extends Pluf_Model
|
|||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
//It is automatically added.
|
//It is automatically added.
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'model_class' =>
|
'model_class' =>
|
||||||
array(
|
array(
|
||||||
@ -108,7 +108,7 @@ class IDF_Gconf extends Pluf_Model
|
|||||||
*/
|
*/
|
||||||
function setVal($key, $value)
|
function setVal($key, $value)
|
||||||
{
|
{
|
||||||
if (!is_null($this->getVal($key, null))
|
if (!is_null($this->getVal($key, null))
|
||||||
and $value == $this->getVal($key)) {
|
and $value == $this->getVal($key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ class IDF_Gconf extends Pluf_Model
|
|||||||
$this->datacache[$key] = $value;
|
$this->datacache[$key] = $value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we insert
|
// we insert
|
||||||
$conf = new IDF_Gconf();
|
$conf = new IDF_Gconf();
|
||||||
$conf->model_class = $this->_mod->_model;
|
$conf->model_class = $this->_mod->_model;
|
||||||
|
@ -41,9 +41,9 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
'id' =>
|
'id' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'issue' =>
|
'issue' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'IDF_Issue',
|
'model' => 'IDF_Issue',
|
||||||
@ -57,7 +57,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
'blank' => false,
|
'blank' => false,
|
||||||
'verbose' => __('comment'),
|
'verbose' => __('comment'),
|
||||||
),
|
),
|
||||||
'submitter' =>
|
'submitter' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@ -79,7 +79,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
'verbose' => __('creation date'),
|
'verbose' => __('creation date'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$this->_a['idx'] = array(
|
$this->_a['idx'] = array(
|
||||||
'creation_dtime_idx' =>
|
'creation_dtime_idx' =>
|
||||||
array(
|
array(
|
||||||
'col' => 'creation_dtime',
|
'col' => 'creation_dtime',
|
||||||
@ -119,7 +119,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
$sql = new Pluf_SQL('issue=%s', array($this->issue));
|
$sql = new Pluf_SQL('issue=%s', array($this->issue));
|
||||||
$co = Pluf::factory('IDF_IssueComment')->getList(array('filter'=>$sql->gen()));
|
$co = Pluf::factory('IDF_IssueComment')->getList(array('filter'=>$sql->gen()));
|
||||||
if ($co->count() > 1) {
|
if ($co->count() > 1) {
|
||||||
IDF_Timeline::insert($this, $this->get_issue()->get_project(),
|
IDF_Timeline::insert($this, $this->get_issue()->get_project(),
|
||||||
$this->get_submitter());
|
$this->get_submitter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
public function timelineFragment($request)
|
public function timelineFragment($request)
|
||||||
{
|
{
|
||||||
$issue = $this->get_issue();
|
$issue = $this->get_issue();
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$issue->id));
|
$issue->id));
|
||||||
$url .= '#ic'.$this->id;
|
$url .= '#ic'.$this->id;
|
||||||
@ -168,7 +168,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
}
|
}
|
||||||
$out .= '</td></tr>';
|
$out .= '</td></tr>';
|
||||||
$out .= "\n".'<tr class="extra"><td colspan="2">
|
$out .= "\n".'<tr class="extra"><td colspan="2">
|
||||||
<div class="helptext right">'.sprintf(__('Comment on <a href="%s" class="%s">issue %d</a>, by %s'), $url, $ic, $issue->id, $user).'</div></td></tr>';
|
<div class="helptext right">'.sprintf(__('Comment on <a href="%s" class="%s">issue %d</a>, by %s'), $url, $ic, $issue->id, $user).'</div></td></tr>';
|
||||||
return Pluf_Template::markSafe($out);
|
return Pluf_Template::markSafe($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
{
|
{
|
||||||
$issue = $this->get_issue();
|
$issue = $this->get_issue();
|
||||||
$url = Pluf::f('url_base')
|
$url = Pluf::f('url_base')
|
||||||
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
.Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$issue->id));
|
$issue->id));
|
||||||
$title = sprintf(__('%s: Comment on issue %d - %s'),
|
$title = sprintf(__('%s: Comment on issue %d - %s'),
|
||||||
@ -196,4 +196,9 @@ class IDF_IssueComment extends Pluf_Model
|
|||||||
$tmpl = new Pluf_Template('idf/issues/feedfragment.xml');
|
$tmpl = new Pluf_Template('idf/issues/feedfragment.xml');
|
||||||
return $tmpl->render($context);
|
return $tmpl->render($context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get_submitter_data()
|
||||||
|
{
|
||||||
|
return IDF_UserData::factory($this->get_submitter());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,12 @@
|
|||||||
* A comment set on a review.
|
* A comment set on a review.
|
||||||
*
|
*
|
||||||
* A comment is associated to a patch as a review can have many
|
* A comment is associated to a patch as a review can have many
|
||||||
* patches associated to it.
|
* patches associated to it.
|
||||||
*
|
*
|
||||||
* A comment is also tracking the changes in the review in the same
|
* A comment is also tracking the changes in the review in the same
|
||||||
* way the issue comment is tracking the changes in the issue.
|
* way the issue comment is tracking the changes in the issue.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class IDF_Review_Comment extends Pluf_Model
|
class IDF_Review_Comment extends Pluf_Model
|
||||||
{
|
{
|
||||||
@ -45,9 +45,9 @@ class IDF_Review_Comment extends Pluf_Model
|
|||||||
'id' =>
|
'id' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Sequence',
|
'type' => 'Pluf_DB_Field_Sequence',
|
||||||
'blank' => true,
|
'blank' => true,
|
||||||
),
|
),
|
||||||
'patch' =>
|
'patch' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'IDF_Review_Patch',
|
'model' => 'IDF_Review_Patch',
|
||||||
@ -61,7 +61,7 @@ class IDF_Review_Comment extends Pluf_Model
|
|||||||
'blank' => true, // if only commented on lines
|
'blank' => true, // if only commented on lines
|
||||||
'verbose' => __('comment'),
|
'verbose' => __('comment'),
|
||||||
),
|
),
|
||||||
'submitter' =>
|
'submitter' =>
|
||||||
array(
|
array(
|
||||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||||
'model' => 'Pluf_User',
|
'model' => 'Pluf_User',
|
||||||
@ -118,8 +118,8 @@ class IDF_Review_Comment extends Pluf_Model
|
|||||||
function postSave($create=false)
|
function postSave($create=false)
|
||||||
{
|
{
|
||||||
if ($create) {
|
if ($create) {
|
||||||
IDF_Timeline::insert($this,
|
IDF_Timeline::insert($this,
|
||||||
$this->get_patch()->get_review()->get_project(),
|
$this->get_patch()->get_review()->get_project(),
|
||||||
$this->get_submitter());
|
$this->get_submitter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ class IDF_Review_Comment extends Pluf_Model
|
|||||||
public function timelineFragment($request)
|
public function timelineFragment($request)
|
||||||
{
|
{
|
||||||
$review = $this->get_patch()->get_review();
|
$review = $this->get_patch()->get_review();
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$review->id));
|
$review->id));
|
||||||
$out = '<tr class="log"><td><a href="'.$url.'">'.
|
$out = '<tr class="log"><td><a href="'.$url.'">'.
|
||||||
@ -138,14 +138,14 @@ class IDF_Review_Comment extends Pluf_Model
|
|||||||
$ic = (in_array($review->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o';
|
$ic = (in_array($review->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o';
|
||||||
$out .= sprintf(__('<a href="%1$s" class="%2$s" title="View review">Review %3$d</a>, %4$s'), $url, $ic, $review->id, Pluf_esc($review->summary)).'</td>';
|
$out .= sprintf(__('<a href="%1$s" class="%2$s" title="View review">Review %3$d</a>, %4$s'), $url, $ic, $review->id, Pluf_esc($review->summary)).'</td>';
|
||||||
$out .= "\n".'<tr class="extra"><td colspan="2">
|
$out .= "\n".'<tr class="extra"><td colspan="2">
|
||||||
<div class="helptext right">'.sprintf(__('Update of <a href="%s" class="%s">review %d</a>, by %s'), $url, $ic, $review->id, $user).'</div></td></tr>';
|
<div class="helptext right">'.sprintf(__('Update of <a href="%s" class="%s">review %d</a>, by %s'), $url, $ic, $review->id, $user).'</div></td></tr>';
|
||||||
return Pluf_Template::markSafe($out);
|
return Pluf_Template::markSafe($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function feedFragment($request)
|
public function feedFragment($request)
|
||||||
{
|
{
|
||||||
$review = $this->get_patch()->get_review();
|
$review = $this->get_patch()->get_review();
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
||||||
array($request->project->shortname,
|
array($request->project->shortname,
|
||||||
$review->id));
|
$review->id));
|
||||||
$title = sprintf(__('%s: Updated review %d - %s'),
|
$title = sprintf(__('%s: Updated review %d - %s'),
|
||||||
@ -221,4 +221,9 @@ class IDF_Review_Comment extends Pluf_Model
|
|||||||
}
|
}
|
||||||
Pluf_Translation::loadSetLocale($current_locale);
|
Pluf_Translation::loadSetLocale($current_locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get_submitter_data()
|
||||||
|
{
|
||||||
|
return IDF_UserData::factory($this->get_submitter());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
59
src/IDF/UserData.php
Normal file
59
src/IDF/UserData.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# This file is part of InDefero, an open source project management application.
|
||||||
|
# Copyright (C) 2008 Céondo Ltd and contributors.
|
||||||
|
#
|
||||||
|
# InDefero is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# InDefero 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
# ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thin wrapper around the general purpose Gconf data driver
|
||||||
|
* to model a userdata object as key value store
|
||||||
|
*/
|
||||||
|
class IDF_UserData extends IDF_Gconf
|
||||||
|
{
|
||||||
|
/** columns for the underlying model for which we do not want to
|
||||||
|
override __get and __set */
|
||||||
|
private static $protectedVars =
|
||||||
|
array('id', 'model_class', 'model_id', 'vkey', 'vdesc');
|
||||||
|
|
||||||
|
function __set($key, $value)
|
||||||
|
{
|
||||||
|
if (in_array($key, self::$protectedVars))
|
||||||
|
{
|
||||||
|
parent::__set($key, $value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->setVal($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function __get($key)
|
||||||
|
{
|
||||||
|
if (in_array($key, self::$protectedVars))
|
||||||
|
return parent::__get($key);
|
||||||
|
return $this->getVal($key, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function factory($user)
|
||||||
|
{
|
||||||
|
$conf = new IDF_UserData();
|
||||||
|
$conf->setModel((object) array('_model'=>'IDF_UserData', 'id' => $user->id));
|
||||||
|
$conf->initCache();
|
||||||
|
return $conf;
|
||||||
|
}
|
||||||
|
}
|
@ -86,7 +86,10 @@ class IDF_Views
|
|||||||
$title = __('Create Your Account');
|
$title = __('Create Your Account');
|
||||||
$params = array('request'=>$request);
|
$params = array('request'=>$request);
|
||||||
if ($request->method == 'POST') {
|
if ($request->method == 'POST') {
|
||||||
$form = new IDF_Form_Register($request->POST, $params);
|
$form = new IDF_Form_Register(array_merge(
|
||||||
|
(array)$request->POST,
|
||||||
|
(array)$request->FILES
|
||||||
|
), $params);
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$user = $form->save(); // It is sending the confirmation email
|
$user = $form->save(); // It is sending the confirmation email
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey');
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey');
|
||||||
|
@ -268,7 +268,9 @@ class IDF_Views_Admin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($request->method == 'POST') {
|
if ($request->method == 'POST') {
|
||||||
$form = new IDF_Form_Admin_UserUpdate($request->POST, $params);
|
$form = new IDF_Form_Admin_UserUpdate(array_merge($request->POST,
|
||||||
|
$request->FILES),
|
||||||
|
$params);
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$form->save();
|
$form->save();
|
||||||
$request->user->setMessage(__('The user has been updated.'));
|
$request->user->setMessage(__('The user has been updated.'));
|
||||||
@ -299,7 +301,9 @@ class IDF_Views_Admin
|
|||||||
'request' => $request,
|
'request' => $request,
|
||||||
);
|
);
|
||||||
if ($request->method == 'POST') {
|
if ($request->method == 'POST') {
|
||||||
$form = new IDF_Form_Admin_UserCreate($request->POST, $params);
|
$form = new IDF_Form_Admin_UserCreate(array_merge($request->POST,
|
||||||
|
$request->FILES),
|
||||||
|
$params);
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$cuser = $form->save();
|
$cuser = $form->save();
|
||||||
$request->user->setMessage(sprintf(__('The user %s has been created.'), (string) $cuser));
|
$request->user->setMessage(sprintf(__('The user %s has been created.'), (string) $cuser));
|
||||||
|
@ -279,6 +279,7 @@ class IDF_Views_Issue
|
|||||||
$form = new IDF_Form_IssueUpdate(null, $params);
|
$form = new IDF_Form_IssueUpdate(null, $params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$arrays = self::autoCompleteArrays($prj);
|
$arrays = self::autoCompleteArrays($prj);
|
||||||
return Pluf_Shortcuts_RenderToResponse('idf/issues/view.html',
|
return Pluf_Shortcuts_RenderToResponse('idf/issues/view.html',
|
||||||
array_merge(
|
array_merge(
|
||||||
@ -290,7 +291,7 @@ class IDF_Views_Issue
|
|||||||
'page_title' => $title,
|
'page_title' => $title,
|
||||||
'closed' => $closed,
|
'closed' => $closed,
|
||||||
'preview' => $preview,
|
'preview' => $preview,
|
||||||
'interested' =>$interested->count(),
|
'interested' => $interested->count(),
|
||||||
),
|
),
|
||||||
$arrays),
|
$arrays),
|
||||||
$request);
|
$request);
|
||||||
|
@ -89,10 +89,10 @@ class IDF_Views_Review
|
|||||||
));
|
));
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$review = $form->save();
|
$review = $form->save();
|
||||||
$urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
$urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
||||||
array($prj->shortname, $review->id));
|
array($prj->shortname, $review->id));
|
||||||
$request->user->setMessage(sprintf(__('The <a href="%s">code review %d</a> has been created.'), $urlr, $review->id));
|
$request->user->setMessage(sprintf(__('The <a href="%s">code review %d</a> has been created.'), $urlr, $review->id));
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index',
|
||||||
array($prj->shortname));
|
array($prj->shortname));
|
||||||
return new Pluf_HTTP_Response_Redirect($url);
|
return new Pluf_HTTP_Response_Redirect($url);
|
||||||
}
|
}
|
||||||
@ -155,10 +155,10 @@ class IDF_Views_Review
|
|||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$review_comment = $form->save();
|
$review_comment = $form->save();
|
||||||
$review = $patch->get_review();
|
$review = $patch->get_review();
|
||||||
$urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
$urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
||||||
array($prj->shortname, $review->id));
|
array($prj->shortname, $review->id));
|
||||||
$request->user->setMessage(sprintf(__('Your <a href="%s">code review %d</a> has been published.'), $urlr, $review->id));
|
$request->user->setMessage(sprintf(__('Your <a href="%s">code review %d</a> has been published.'), $urlr, $review->id));
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index',
|
||||||
array($prj->shortname));
|
array($prj->shortname));
|
||||||
$review_comment->notify($request->conf);
|
$review_comment->notify($request->conf);
|
||||||
return new Pluf_HTTP_Response_Redirect($url);
|
return new Pluf_HTTP_Response_Redirect($url);
|
||||||
@ -181,7 +181,7 @@ class IDF_Views_Review
|
|||||||
foreach ($cts as $ct) {
|
foreach ($cts as $ct) {
|
||||||
$reviewers[] = $ct->get_comment()->get_submitter();
|
$reviewers[] = $ct->get_comment()->get_submitter();
|
||||||
}
|
}
|
||||||
if (count($def['chunks'])) {
|
if (count($def['chunks'])) {
|
||||||
$orig_file = ($fileinfo) ? $scm->getFile($fileinfo) : '';
|
$orig_file = ($fileinfo) ? $scm->getFile($fileinfo) : '';
|
||||||
$files[$filename] = array(
|
$files[$filename] = array(
|
||||||
$diff->fileCompare($orig_file, $def, $filename),
|
$diff->fileCompare($orig_file, $def, $filename),
|
||||||
@ -192,6 +192,7 @@ class IDF_Views_Review
|
|||||||
$files[$filename] = array('', $form->f->{md5($filename)}, $cts);
|
$files[$filename] = array('', $form->f->{md5($filename)}, $cts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$reviewers = Pluf_Model_RemoveDuplicates($reviewers);
|
$reviewers = Pluf_Model_RemoveDuplicates($reviewers);
|
||||||
return Pluf_Shortcuts_RenderToResponse('idf/review/view.html',
|
return Pluf_Shortcuts_RenderToResponse('idf/review/view.html',
|
||||||
array_merge(
|
array_merge(
|
||||||
@ -219,7 +220,7 @@ class IDF_Views_Review
|
|||||||
*/
|
*/
|
||||||
function IDF_Views_Review_SummaryAndLabels($field, $review, $extra='')
|
function IDF_Views_Review_SummaryAndLabels($field, $review, $extra='')
|
||||||
{
|
{
|
||||||
$edit = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
$edit = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
|
||||||
array($review->shortname, $review->id));
|
array($review->shortname, $review->id));
|
||||||
$tags = array();
|
$tags = array();
|
||||||
foreach ($review->get_tags_list() as $tag) {
|
foreach ($review->get_tags_list() as $tag) {
|
||||||
|
@ -33,13 +33,13 @@ Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
|
|||||||
class IDF_Views_User
|
class IDF_Views_User
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Dashboard of a user.
|
* Dashboard of a user.
|
||||||
*
|
*
|
||||||
* Shows all the open issues assigned to the user.
|
* Shows all the open issues assigned to the user.
|
||||||
*
|
*
|
||||||
* TODO: This views is a SQL horror. What needs to be done to cut
|
* TODO: This views is a SQL horror. What needs to be done to cut
|
||||||
* by many the number of SQL queries:
|
* by many the number of SQL queries:
|
||||||
* - Add a table to cache the open/closed status ids for all the
|
* - Add a table to cache the open/closed status ids for all the
|
||||||
* projects.
|
* projects.
|
||||||
* - Left join the issues with the project to get the shortname.
|
* - Left join the issues with the project to get the shortname.
|
||||||
*
|
*
|
||||||
@ -110,7 +110,10 @@ class IDF_Views_User
|
|||||||
$ext_pass = substr(sha1($request->user->password.Pluf::f('secret_key')), 0, 8);
|
$ext_pass = substr(sha1($request->user->password.Pluf::f('secret_key')), 0, 8);
|
||||||
$params = array('user' => $request->user);
|
$params = array('user' => $request->user);
|
||||||
if ($request->method == 'POST') {
|
if ($request->method == 'POST') {
|
||||||
$form = new IDF_Form_UserAccount($request->POST, $params);
|
$form = new IDF_Form_UserAccount(array_merge(
|
||||||
|
(array)$request->POST,
|
||||||
|
(array)$request->FILES
|
||||||
|
), $params);
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$user = $form->save();
|
$user = $form->save();
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount');
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount');
|
||||||
@ -121,10 +124,11 @@ class IDF_Views_User
|
|||||||
} else {
|
} else {
|
||||||
$data = $request->user->getData();
|
$data = $request->user->getData();
|
||||||
unset($data['password']);
|
unset($data['password']);
|
||||||
$form = new IDF_Form_UserAccount($data, $params);
|
$form = new IDF_Form_UserAccount(null, $params);
|
||||||
}
|
}
|
||||||
$keys = $request->user->get_idf_key_list();
|
$keys = $request->user->get_idf_key_list();
|
||||||
return Pluf_Shortcuts_RenderToResponse('idf/user/myaccount.html',
|
|
||||||
|
return Pluf_Shortcuts_RenderToResponse('idf/user/myaccount.html',
|
||||||
array('page_title' => __('Your Account'),
|
array('page_title' => __('Your Account'),
|
||||||
'api_key' => $api_key,
|
'api_key' => $api_key,
|
||||||
'ext_pass' => $ext_pass,
|
'ext_pass' => $ext_pass,
|
||||||
@ -170,11 +174,11 @@ class IDF_Views_User
|
|||||||
} else {
|
} else {
|
||||||
$form = new IDF_Form_UserChangeEmail();
|
$form = new IDF_Form_UserChangeEmail();
|
||||||
}
|
}
|
||||||
return Pluf_Shortcuts_RenderToResponse('idf/user/changeemail.html',
|
return Pluf_Shortcuts_RenderToResponse('idf/user/changeemail.html',
|
||||||
array('page_title' => __('Confirm The Email Change'),
|
array('page_title' => __('Confirm The Email Change'),
|
||||||
'form' => $form),
|
'form' => $form),
|
||||||
$request);
|
$request);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -208,13 +212,17 @@ class IDF_Views_User
|
|||||||
public function view($request, $match)
|
public function view($request, $match)
|
||||||
{
|
{
|
||||||
$sql = new Pluf_SQL('login=%s', array($match[1]));
|
$sql = new Pluf_SQL('login=%s', array($match[1]));
|
||||||
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
|
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
|
||||||
if (count($users) != 1 or !$users[0]->active) {
|
if (count($users) != 1 or !$users[0]->active) {
|
||||||
throw new Pluf_HTTP_Error404();
|
throw new Pluf_HTTP_Error404();
|
||||||
}
|
}
|
||||||
return Pluf_Shortcuts_RenderToResponse('idf/user/public.html',
|
|
||||||
array('page_title' => (string) $users[0],
|
$user = $users[0];
|
||||||
'member' => $users[0],
|
$user_data = IDF_UserData::factory($user);
|
||||||
|
return Pluf_Shortcuts_RenderToResponse('idf/user/public.html',
|
||||||
|
array('page_title' => (string) $user,
|
||||||
|
'member' => $user,
|
||||||
|
'user_data' => $user_data,
|
||||||
),
|
),
|
||||||
$request);
|
$request);
|
||||||
}
|
}
|
||||||
@ -230,11 +238,11 @@ class IDF_Views_User
|
|||||||
function IDF_Views_IssueSummaryAndLabels($field, $issue, $extra='')
|
function IDF_Views_IssueSummaryAndLabels($field, $issue, $extra='')
|
||||||
{
|
{
|
||||||
$project = $issue->get_project();
|
$project = $issue->get_project();
|
||||||
$edit = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
$edit = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||||
array($project->shortname, $issue->id));
|
array($project->shortname, $issue->id));
|
||||||
$tags = array();
|
$tags = array();
|
||||||
foreach ($issue->get_tags_list() as $tag) {
|
foreach ($issue->get_tags_list() as $tag) {
|
||||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::listLabel',
|
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::listLabel',
|
||||||
array($project->shortname, $tag->id, 'open'));
|
array($project->shortname, $tag->id, 'open'));
|
||||||
$tags[] = sprintf('<a class="label" href="%s">%s</a>', $url, Pluf_esc((string) $tag));
|
$tags[] = sprintf('<a class="label" href="%s">%s</a>', $url, Pluf_esc((string) $tag));
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ $m['IDF_Conf'] = array('relate_to' => array('IDF_Project'));
|
|||||||
$m['IDF_Commit'] = array('relate_to' => array('IDF_Project', 'Pluf_User'));
|
$m['IDF_Commit'] = array('relate_to' => array('IDF_Project', 'Pluf_User'));
|
||||||
$m['IDF_Scm_Cache_Git'] = array('relate_to' => array('IDF_Project'));
|
$m['IDF_Scm_Cache_Git'] = array('relate_to' => array('IDF_Project'));
|
||||||
|
|
||||||
|
$m['IDF_UserData'] = array('relate_to' => array('Pluf_User'));
|
||||||
|
|
||||||
Pluf_Signal::connect('Pluf_Template_Compiler::construct_template_tags_modifiers',
|
Pluf_Signal::connect('Pluf_Template_Compiler::construct_template_tags_modifiers',
|
||||||
array('IDF_Middleware', 'updateTemplateTagsModifiers'));
|
array('IDF_Middleware', 'updateTemplateTagsModifiers'));
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<form method="post" action=".">
|
<form method="post" enctype="multipart/form-data" action=".">
|
||||||
<table class="form" summary="">
|
<table class="form" summary="">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{trans 'Login:'}</th>{aurl 'url', 'IDF_Views_User::view', array($cuser.login)}
|
<th>{trans 'Login:'}</th>{aurl 'url', 'IDF_Views_User::view', array($cuser.login)}
|
||||||
@ -51,7 +51,48 @@
|
|||||||
<td>{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if}
|
<td>{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if}
|
||||||
{$form.f.password2|unsafe}
|
{$form.f.password2|unsafe}
|
||||||
</td>
|
</td>
|
||||||
</tr>{if $user.administrator}
|
</tr>
|
||||||
|
<tr><td colspan="2" class="separator">{trans "Public Profile"}</td></tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.description.labelTag}:</th>
|
||||||
|
<td>{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if}
|
||||||
|
{$form.f.description|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.twitter.labelTag}:</th>
|
||||||
|
<td>{if $form.f.twitter.errors}{$form.f.twitter.fieldErrors}{/if}
|
||||||
|
{$form.f.twitter|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.public_email.labelTag}:</th>
|
||||||
|
<td>{if $form.f.public_email.errors}{$form.f.public_email.fieldErrors}{/if}
|
||||||
|
{$form.f.public_email|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.website.labelTag}:</th>
|
||||||
|
<td>{if $form.f.website.errors}{$form.f.website.fieldErrors}{/if}
|
||||||
|
{$form.f.website|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.custom_avatar.labelTag}:</th>
|
||||||
|
<td>{if $form.f.custom_avatar.errors}{$form.f.custom_avatar.fieldErrors}{/if}
|
||||||
|
{$form.f.custom_avatar|unsafe}<br />
|
||||||
|
<span class="helptext">{$form.f.custom_avatar.help_text}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{if $form.f.remove_custom_avatar.errors}{$form.f.remove_custom_avatar.fieldErrors}{/if}
|
||||||
|
{$form.f.remove_custom_avatar|unsafe}
|
||||||
|
</th>
|
||||||
|
<td>{$form.f.remove_custom_avatar.labelTag}<br />
|
||||||
|
<span class="helptext">{$form.f.remove_custom_avatar.help_text}</span></td>
|
||||||
|
</tr>
|
||||||
|
{if $user.administrator}
|
||||||
|
<tr><td colspan="2" class="separator">{trans "Administrative"}</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{if $form.f.staff.errors}{$form.f.staff.fieldErrors}{/if}
|
<th>{if $form.f.staff.errors}{$form.f.staff.fieldErrors}{/if}
|
||||||
{$form.f.staff|unsafe}
|
{$form.f.staff|unsafe}
|
||||||
@ -69,7 +110,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
<td>
|
<td>
|
||||||
<input type="submit" value="{trans 'Update User'}" name="submit" />
|
<input type="submit" value="{trans 'Update User'}" name="submit" />
|
||||||
| <a href="{url 'IDF_Views_Admin::users'}">{trans 'Cancel'}</a>
|
| <a href="{url 'IDF_Views_Admin::users'}">{trans 'Cancel'}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -3,8 +3,15 @@
|
|||||||
{block body}
|
{block body}
|
||||||
{assign $i = 0}
|
{assign $i = 0}
|
||||||
{assign $nc = $comments.count()}
|
{assign $nc = $comments.count()}
|
||||||
{foreach $comments as $c}{ashowuser 'submitter', $c.get_submitter(), $request}{assign $who = $c.get_submitter()}
|
{foreach $comments as $c}{ashowuser 'submitter', $c.get_submitter(), $request}
|
||||||
<div class="issue-comment{if $i == 0} issue-comment-first{/if}{if $i == ($nc-1)} issue-comment-last{/if}" id="ic{$c.id}"><img style="float:right; position: relative;" src="http://www.gravatar.com/avatar/{$who.email|md5}.jpg?s=60&d={media}/idf/img/spacer.gif" alt=" " />
|
{assign $submitter = $c.get_submitter()}
|
||||||
|
{assign $submitter_data = $c.get_submitter_data()}
|
||||||
|
<div class="issue-comment{if $i == 0} issue-comment-first{/if}{if $i == ($nc-1)} issue-comment-last{/if}" id="ic{$c.id}">
|
||||||
|
{if $submitter_data.avatar != ''}
|
||||||
|
<img style="float:right; position: relative; max-height: 60px; max-width: 60px;" src="{media}/upload/avatars/{$submitter_data.avatar}" alt=" " />
|
||||||
|
{else}
|
||||||
|
<img style="float:right; position: relative; max-height: 60px; max-width: 60px;" src="http://www.gravatar.com/avatar/{$submitter.email|md5}.jpg?s=60&d={media}/idf/img/spacer.gif" alt=" " />
|
||||||
|
{/if}
|
||||||
{if $i == 0}
|
{if $i == 0}
|
||||||
<p>{blocktrans}Reported by {$submitter}, {$c.creation_dtime|date}{/blocktrans}</p>
|
<p>{blocktrans}Reported by {$submitter}, {$c.creation_dtime|date}{/blocktrans}</p>
|
||||||
{else}
|
{else}
|
||||||
|
@ -79,9 +79,9 @@ to propose more contributions</strong>.
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{assign $fcomments = $def[2]}
|
{assign $fcomments = $def[2]}
|
||||||
{assign $nc = $fcomments.count()}
|
{assign $nc = $fcomments.count()}
|
||||||
{assign $i = 1}
|
{assign $i = 1}
|
||||||
{foreach $fcomments as $c}
|
{foreach $fcomments as $c}
|
||||||
<div class="issue-comment{if $i == 1} issue-comment-first{/if}{if $i == $nc} issue-comment-last{/if}" id="ic{$c.id}">{assign $who = $c.get_comment().get_submitter()}{aurl 'whourl', 'IDF_Views_User::view', array($who.login)}
|
<div class="issue-comment{if $i == 1} issue-comment-first{/if}{if $i == $nc} issue-comment-last{/if}" id="ic{$c.id}">{assign $who = $c.get_comment().get_submitter()}{aurl 'whourl', 'IDF_Views_User::view', array($who.login)}
|
||||||
{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)}
|
{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)}
|
||||||
{assign $id = $c.id}
|
{assign $id = $c.id}
|
||||||
@ -101,13 +101,18 @@ to propose more contributions</strong>.
|
|||||||
</tr></table>{/if}
|
</tr></table>{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
|
|
||||||
{assign $i = 1}
|
{assign $i = 1}
|
||||||
{assign $nc = $comments.count()}
|
{assign $nc = $comments.count()}
|
||||||
{if $nc}<hr align="left" class="attach" />
|
{if $nc}<hr align="left" class="attach" />
|
||||||
<h2>{trans 'General Comments'}</h2>
|
<h2>{trans 'General Comments'}</h2>
|
||||||
{/if}
|
{/if}
|
||||||
{foreach $comments as $c}{ashowuser 'submitter', $c.get_submitter(), $request}{assign $who = $c.get_submitter()}
|
{foreach $comments as $c}{ashowuser 'submitter', $c.get_submitter(), $request}{assign $submitter = $c.get_submitter()}{assign $submitter_data = $c.get_submitter_data()}
|
||||||
<div class="issue-comment{if $i == 1} issue-comment-first{/if}{if $i == ($nc)} issue-comment-last{/if}" id="ic{$c.id}"><img style="float:right; position: relative;" src="http://www.gravatar.com/avatar/{$who.email|md5}.jpg?s=60&d={media}/idf/img/spacer.gif" alt=" " />
|
<div class="issue-comment{if $i == 1} issue-comment-first{/if}{if $i == ($nc)} issue-comment-last{/if}" id="ic{$c.id}">
|
||||||
|
{if $submitter_data.avatar != ''}
|
||||||
|
<img style="float:right; position: relative; max-height: 60px; max-width: 60px;" src="{media}/upload/avatars/{$submitter_data.avatar}" alt=" " />
|
||||||
|
{else}
|
||||||
|
<img style="float:right; position: relative;" src="http://www.gravatar.com/avatar/{$submitter.email|md5}.jpg?s=60&d={media}/idf/img/spacer.gif" alt=" " />
|
||||||
|
{/if}
|
||||||
{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)}
|
{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)}
|
||||||
{assign $id = $c.id}
|
{assign $id = $c.id}
|
||||||
{assign $url = $url~'#ic'~$c.id}
|
{assign $url = $url~'#ic'~$c.id}
|
||||||
@ -118,11 +123,11 @@ to propose more contributions</strong>.
|
|||||||
{if strlen($c.content) > 0}<pre class="issue-comment-text">{issuetext $c.content, $request}</pre>{/if}
|
{if strlen($c.content) > 0}<pre class="issue-comment-text">{issuetext $c.content, $request}</pre>{/if}
|
||||||
|
|
||||||
{if $c.changedReview()}
|
{if $c.changedReview()}
|
||||||
<div class="issue-changes">
|
<div class="issue-changes">
|
||||||
{foreach $c.changes as $w => $v}
|
{foreach $c.changes as $w => $v}
|
||||||
<strong>{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}</strong> {$v}<br />
|
<strong>{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}</strong> {$v}<br />
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>{assign $i = $i + 1}{if $i == $nc+1 and $user.isAnonymous()}
|
</div>{assign $i = $i + 1}{if $i == $nc+1 and $user.isAnonymous()}
|
||||||
<div class="issue-comment-signin">
|
<div class="issue-comment-signin">
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<form method="post" action=".">
|
<form method="post" enctype="multipart/form-data" action=".">
|
||||||
<table class="form" summary="">
|
<table class="form" summary="">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{trans 'Login:'}</th>{aurl 'url', 'IDF_Views_User::view', array($user.login)}
|
<th>{trans 'Login:'}</th>{aurl 'url', 'IDF_Views_User::view', array($user.login)}
|
||||||
@ -53,6 +53,46 @@
|
|||||||
{$form.f.password2|unsafe}
|
{$form.f.password2|unsafe}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr><td colspan="2" class="separator">{trans "Public Profile"}</td></tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.description.labelTag}:</th>
|
||||||
|
<td>{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if}
|
||||||
|
{$form.f.description|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.twitter.labelTag}:</th>
|
||||||
|
<td>{if $form.f.twitter.errors}{$form.f.twitter.fieldErrors}{/if}
|
||||||
|
{$form.f.twitter|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.public_email.labelTag}:</th>
|
||||||
|
<td>{if $form.f.public_email.errors}{$form.f.public_email.fieldErrors}{/if}
|
||||||
|
{$form.f.public_email|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.website.labelTag}:</th>
|
||||||
|
<td>{if $form.f.website.errors}{$form.f.website.fieldErrors}{/if}
|
||||||
|
{$form.f.website|unsafe}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{$form.f.custom_avatar.labelTag}:</th>
|
||||||
|
<td>{if $form.f.custom_avatar.errors}{$form.f.custom_avatar.fieldErrors}{/if}
|
||||||
|
{$form.f.custom_avatar|unsafe}<br />
|
||||||
|
<span class="helptext">{$form.f.custom_avatar.help_text}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{if $form.f.remove_custom_avatar.errors}{$form.f.remove_custom_avatar.fieldErrors}{/if}
|
||||||
|
{$form.f.remove_custom_avatar|unsafe}
|
||||||
|
</th>
|
||||||
|
<td>{$form.f.remove_custom_avatar.labelTag}<br />
|
||||||
|
<span class="helptext">{$form.f.remove_custom_avatar.help_text}</span></td>
|
||||||
|
</tr>
|
||||||
|
<tr><td colspan="2" class="separator">{trans "Key Management"}</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{$form.f.public_key.labelTag}:</th>
|
<th>{$form.f.public_key.labelTag}:</th>
|
||||||
<td>{if $form.f.public_key.errors}{$form.f.public_key.fieldErrors}{/if}
|
<td>{if $form.f.public_key.errors}{$form.f.public_key.fieldErrors}{/if}
|
||||||
|
@ -2,9 +2,39 @@
|
|||||||
{block body}
|
{block body}
|
||||||
<table class="form" summary="">
|
<table class="form" summary="">
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th style="text-align: right">{if $user_data.avatar != ''}
|
||||||
|
<img style="max-height: 60px; max-width: 60px;" src="{media}/upload/avatars/{$user_data.avatar}" alt=" " />
|
||||||
|
{else}
|
||||||
|
<img src="http://www.gravatar.com/avatar/{$member.email|md5}.jpg?s=60&d={media}/idf/img/spacer.gif" alt=" " />
|
||||||
|
{/if}
|
||||||
|
</th>
|
||||||
<td>{$member}</td>
|
<td>{$member}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{if $user_data.description != ''}
|
||||||
|
<tr>
|
||||||
|
<th>{trans 'Description:'}</th>
|
||||||
|
<td>{$user_data.description}</td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if $user_data.twitter != ''}
|
||||||
|
<tr>
|
||||||
|
<th>{trans 'Twitter:'}</th>
|
||||||
|
<td><a rel="nofollow" target="_blank" href='http://twitter.com/{$user_data.twitter}'>{$user_data.twitter}</a></td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if $user_data.public_email != ''}
|
||||||
|
<tr>
|
||||||
|
<th>{trans 'Public Email:'}</th>
|
||||||
|
<td><a href='mailto:{$user_data.public_email}'>{$user_data.public_email}</a></td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{if $user_data.website != ''}
|
||||||
|
<tr>
|
||||||
|
<th>{trans 'Website:'}</th>
|
||||||
|
<td><a rel="nofollow" target="_blank" href='{$user_data.website}'>{$user_data.website}</a></td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>{trans 'Last time seen:'}</th>
|
<th>{trans 'Last time seen:'}</th>
|
||||||
<td>{$member.last_login|dateago}</td>
|
<td>{$member.last_login|dateago}</td>
|
||||||
|
@ -104,6 +104,11 @@ table.form th {
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.form td.separator {
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.px-message-error {
|
.px-message-error {
|
||||||
padding-left: 37px;
|
padding-left: 37px;
|
||||||
background: url("../img/dialog-error.png");
|
background: url("../img/dialog-error.png");
|
||||||
|
Loading…
Reference in New Issue
Block a user