diff --git a/src/IDF/Form/Admin/UserUpdate.php b/src/IDF/Form/Admin/UserUpdate.php index 6859859..d9111ae 100644 --- a/src/IDF/Form/Admin/UserUpdate.php +++ b/src/IDF/Form/Admin/UserUpdate.php @@ -24,13 +24,15 @@ /** * Update user's details. */ -class IDF_Form_Admin_UserUpdate extends Pluf_Form +class IDF_Form_Admin_UserUpdate extends Pluf_Form { public $user = null; public function initFields($extra=array()) { $this->user = $extra['user']; + $user_data = IDF_UserData::factory($this->user); + $this->fields['first_name'] = new Pluf_Form_Field_Varchar( array('required' => false, 'label' => __('First name'), @@ -66,7 +68,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form 'initial' => $this->user->language, 'widget' => 'Pluf_Form_Widget_SelectInput', 'widget_attrs' => array( - 'choices' => + 'choices' => 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) { $this->fields['staff'] = new Pluf_Form_Field_Boolean( array('required' => false, @@ -136,8 +198,37 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form $update_pass = true; } $this->user->setFromFormData($this->cleaned_data); + if ($commit) { $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) { /** * [signal] @@ -170,7 +261,7 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form { $last_name = trim($this->cleaned_data['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'); } 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.')); } 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'); } return $first_name; @@ -201,12 +292,23 @@ class IDF_Form_Admin_UserUpdate extends Pluf_Form 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() { - if (!isset($this->errors['password']) + if (!isset($this->errors['password']) && !isset($this->errors['password2'])) { $password1 = $this->cleaned_data['password']; $password2 = $this->cleaned_data['password2']; diff --git a/src/IDF/Form/UserAccount.php b/src/IDF/Form/UserAccount.php index 5af3185..7b6a5cb 100644 --- a/src/IDF/Form/UserAccount.php +++ b/src/IDF/Form/UserAccount.php @@ -33,6 +33,8 @@ class IDF_Form_UserAccount extends Pluf_Form public function initFields($extra=array()) { $this->user = $extra['user']; + $user_data = IDF_UserData::factory($this->user); + $this->fields['first_name'] = new Pluf_Form_Field_Varchar( array('required' => false, '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( array('required' => false, 'label' => __('Add a public key'), @@ -138,7 +200,7 @@ class IDF_Form_UserAccount extends Pluf_Form 'email' => $new_email, 'user'=> $this->user, ) - ); + ); $tmpl = new Pluf_Template('idf/user/changeemail-email.txt'); $text_email = $tmpl->render($context); $email = new Pluf_Mail(Pluf::f('from_email'), $new_email, @@ -157,8 +219,37 @@ class IDF_Form_UserAccount extends Pluf_Form $key->create(); } } + if ($commit) { $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) { /** * [signal] @@ -266,6 +357,19 @@ class IDF_Form_UserAccount extends Pluf_Form 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() { $last_name = trim($this->cleaned_data['last_name']); @@ -322,4 +426,6 @@ class IDF_Form_UserAccount extends Pluf_Form return $this->cleaned_data; } + + } diff --git a/src/IDF/Gconf.php b/src/IDF/Gconf.php index 4bbec62..ad09ef8 100644 --- a/src/IDF/Gconf.php +++ b/src/IDF/Gconf.php @@ -46,7 +46,7 @@ class IDF_Gconf extends Pluf_Model array( 'type' => 'Pluf_DB_Field_Sequence', //It is automatically added. - 'blank' => true, + 'blank' => true, ), 'model_class' => array( @@ -108,7 +108,7 @@ class IDF_Gconf extends Pluf_Model */ function setVal($key, $value) { - if (!is_null($this->getVal($key, null)) + if (!is_null($this->getVal($key, null)) and $value == $this->getVal($key)) { return; } @@ -121,7 +121,7 @@ class IDF_Gconf extends Pluf_Model $this->datacache[$key] = $value; return; } - } + } // we insert $conf = new IDF_Gconf(); $conf->model_class = $this->_mod->_model; diff --git a/src/IDF/IssueComment.php b/src/IDF/IssueComment.php index 110f3d8..084ecf3 100644 --- a/src/IDF/IssueComment.php +++ b/src/IDF/IssueComment.php @@ -41,9 +41,9 @@ class IDF_IssueComment extends Pluf_Model 'id' => array( 'type' => 'Pluf_DB_Field_Sequence', - 'blank' => true, + 'blank' => true, ), - 'issue' => + 'issue' => array( 'type' => 'Pluf_DB_Field_Foreignkey', 'model' => 'IDF_Issue', @@ -57,7 +57,7 @@ class IDF_IssueComment extends Pluf_Model 'blank' => false, 'verbose' => __('comment'), ), - 'submitter' => + 'submitter' => array( 'type' => 'Pluf_DB_Field_Foreignkey', 'model' => 'Pluf_User', @@ -79,7 +79,7 @@ class IDF_IssueComment extends Pluf_Model 'verbose' => __('creation date'), ), ); - $this->_a['idx'] = array( + $this->_a['idx'] = array( 'creation_dtime_idx' => array( 'col' => 'creation_dtime', @@ -119,7 +119,7 @@ class IDF_IssueComment extends Pluf_Model $sql = new Pluf_SQL('issue=%s', array($this->issue)); $co = Pluf::factory('IDF_IssueComment')->getList(array('filter'=>$sql->gen())); 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()); } } @@ -129,7 +129,7 @@ class IDF_IssueComment extends Pluf_Model public function timelineFragment($request) { $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, $issue->id)); $url .= '#ic'.$this->id; @@ -168,7 +168,7 @@ class IDF_IssueComment extends Pluf_Model } $out .= ''; $out .= "\n".'