diff --git a/www/images/user_photo.jpg b/www/images/user_photo.jpg
new file mode 100644
index 0000000..af73630
Binary files /dev/null and b/www/images/user_photo.jpg differ
diff --git a/www/protected/controllers/UsuarioController.php b/www/protected/controllers/UsuarioController.php
index 42f8dc1..7762917 100644
--- a/www/protected/controllers/UsuarioController.php
+++ b/www/protected/controllers/UsuarioController.php
@@ -39,21 +39,30 @@ class UsuarioController extends Controller {
if ($id != Yii::app()->user->id)
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
- $model = $this->loadModel($id);
-
+ $usuario = $this->loadModel($id);
+
// Uncomment the following line if AJAX validation is needed
- // $this->performAjaxValidation($model);
+ // $this->performAjaxValidation($usuario);
if (isset($_POST['Usuario'])) {
- $model->attributes = $_POST['Usuario'];
- if ($model->save()) {
+ $usuario->attributes = $_POST['Usuario'];
+ $ficheroFotografia = CUploadedFile::getInstance($usuario, 'ficheroFotografia');
+ $quitarFotografia = Yii::app()->request->getParam('quitar_fotografia', '0');
+
+ if ($usuario->save()) {
+ if (($quitarFotografia == '1') && ($usuario->fotografia->tieneFotografia()))
+ $usuario->fotografia->eliminarFotografia();
+
+ if ($ficheroFotografia)
+ $usuario->fotografia->guardarFotografia($ficheroFotografia);
+
Yii::app()->user->setFlash('success', Yii::t('profind', 'Se ha actualizado el perfil'));
- $this->redirect(array('modificar', 'id' => $model->id));
+ $this->redirect(array('modificar', 'id' => $usuario->id));
}
}
$this->render('modificar', array(
- 'model' => $model,
+ 'model' => $usuario,
));
}
@@ -66,6 +75,7 @@ class UsuarioController extends Controller {
$model = Usuario::model()->findByPk($id);
if ($model === null)
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
+
return $model;
}
diff --git a/www/protected/helpers/recursive_remove_directory.php b/www/protected/helpers/recursive_remove_directory.php
new file mode 100644
index 0000000..daa4410
--- /dev/null
+++ b/www/protected/helpers/recursive_remove_directory.php
@@ -0,0 +1,46 @@
+
\ No newline at end of file
diff --git a/www/protected/models/Usuario.php b/www/protected/models/Usuario.php
index 7a80d50..5820e0b 100644
--- a/www/protected/models/Usuario.php
+++ b/www/protected/models/Usuario.php
@@ -1,9 +1,9 @@
estado == self::ESTADO_ACTIVO);
}
-
+
/**
* Returns the static model of the specified AR class.
* @param string $className active record class name.
@@ -43,7 +45,7 @@ class Usuario extends CActiveRecord {
public static function model($className = __CLASS__) {
return parent::model($className);
}
-
+
/**
* @return string the associated database table name
*/
@@ -54,22 +56,27 @@ class Usuario extends CActiveRecord {
/**
* @return array validation rules for model attributes.
*/
- public function rules()
- {
+ public function rules() {
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('email, password', 'required'),
- array('estado', 'length', 'max'=>1),
+ array('estado', 'length', 'max' => 1),
array('email', 'email'),
array('email', 'unique'),
array('descripcion', 'safe'),
- array('email, nombre, apellidos, password, tipo, titulo, localidad, telefono', 'length', 'max'=>255),
-
- array('id, id_empresa, estado, email, nombre, apellidos, tipo, titulo, localidad, telefono, descripcion', 'safe', 'on'=>'search'),
+ array('email, nombre, apellidos, password, tipo, titulo, localidad, telefono', 'length', 'max' => 255),
+ array('ficheroFotografia', 'file',
+ 'types' => 'jpg',
+ 'maxSize' => 1024 * 1024 * 1, // 1MB como máximo
+ 'tooLarge' => Yii::t('profind', 'La imagen es demasiado pesada. Elija otra fotografía más pequeña.'),
+ 'wrongType' => Yii::t('profind', 'Sólo se permiten imágenes en formato JPG.'),
+ 'allowEmpty' => 'true',
+ ),
+ array('id, id_empresa, estado, email, nombre, apellidos, tipo, titulo, localidad, telefono, descripcion', 'safe', 'on' => 'search'),
);
- }
-
+ }
+
/**
* @return array relational rules.
*/
@@ -77,16 +84,17 @@ class Usuario extends CActiveRecord {
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
- 'empresa' => array(self::HAS_ONE, 'Empresa', 'id'),
+ 'empresa' => array(self::HAS_ONE, 'Empresa', 'id'),
);
}
-
+
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels() {
return array(
'id' => 'ID',
+ 'ficheroFotografia' => 'Fotografía',
'estado' => 'Estado',
'email' => 'Email',
'nombre' => 'Nombre',
@@ -97,37 +105,98 @@ class Usuario extends CActiveRecord {
'localidad' => 'Localidad',
'telefono' => 'Teléfono',
'descripcion' => 'Descripción',
- );
+ );
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
- public function search()
- {
- $criteria=new CDbCriteria;
+ public function search() {
+ $criteria = new CDbCriteria;
- $criteria->compare('id',$this->id);
- $criteria->compare('id_empresa',$this->id_empresa);
- $criteria->compare('estado',$this->estado,true);
- $criteria->compare('email',$this->email,true);
- $criteria->compare('nombre',$this->nombre,true);
- $criteria->compare('apellidos',$this->apellidos,true);
- $criteria->compare('tipo',$this->tipo,true);
- $criteria->compare('titulo',$this->titulo,true);
- $criteria->compare('localidad',$this->localidad,true);
- $criteria->compare('telefono',$this->telefono,true);
- $criteria->compare('last_login_time',$this->last_login_time,true);
- $criteria->compare('descripcion',$this->descripcion,true);
+ $criteria->compare('id', $this->id);
+ $criteria->compare('id_empresa', $this->id_empresa);
+ $criteria->compare('estado', $this->estado, true);
+ $criteria->compare('email', $this->email, true);
+ $criteria->compare('nombre', $this->nombre, true);
+ $criteria->compare('apellidos', $this->apellidos, true);
+ $criteria->compare('tipo', $this->tipo, true);
+ $criteria->compare('titulo', $this->titulo, true);
+ $criteria->compare('localidad', $this->localidad, true);
+ $criteria->compare('telefono', $this->telefono, true);
+ $criteria->compare('last_login_time', $this->last_login_time, true);
+ $criteria->compare('descripcion', $this->descripcion, true);
return new CActiveDataProvider($this, array(
- 'criteria'=>$criteria,
- ));
+ 'criteria' => $criteria,
+ ));
+ }
+
+ protected function afterFind() {
+ parent::afterFind();
+ $this->fotografia = new UsuarioFotografia();
+ $this->fotografia->usuario = $this;
}
+ protected function afterConstruct() {
+ parent::afterConstruct();
+ $this->fotografia = new UsuarioFotografia();
+ $this->fotografia->usuario = $this;
+ }
+
+ protected function afterSave() {
+ parent::afterSave();
+ if ($this->isNewRecord)
+ $this->createUploadDir();
+ }
+
+ protected function afterDelete() {
+ parent::afterDelete();
+ $this->deleteUploadDir();
+ }
+
+ /*
+ * Devuelve la ruta con los ficheros del usuario.
+ * Incluye el separador de directorios al final de la ruta.
+ * @return string ruta
+ */
+ public function getUploadPath() {
+ return Yii::getPathOfAlias('application.uploads') . DIRECTORY_SEPARATOR . $this->id . DIRECTORY_SEPARATOR;
+ }
+
+ /*
+ * Crea un directorio para almacenar ficheros del usuario
+ * @return boolean
+ */
+ private function createUploadDir() {
+ $upload = $this->getUploadPath();
+
+ if(!is_dir($upload)) {
+ return mkdir($upload);
+ }
+ else return false;
+ }
+
+ /*
+ * Elimina el directorio del usuario y todos sus ficheros
+ * @return boolean
+ */
+ private function deleteUploadDir() {
+ $upload = $this->getUploadPath();
+
+ if(is_dir($upload)) {
+ require_once( Yii::getPathOfAlias('application.helpers') . DIRECTORY_SEPARATOR . 'recursive_remove_directory.php');
+ return recursive_remove_directory($upload);
+ }
+ else return false;
+ }
+
+ /*
+ * Función para cifrar la contraseña del usuario (temporal)
+ * @return string contraseña cifrada
+ */
public function encrypt($value) {
return md5($value);
}
-
}
diff --git a/www/protected/models/UsuarioFotografia.php b/www/protected/models/UsuarioFotografia.php
new file mode 100644
index 0000000..fdee73e
--- /dev/null
+++ b/www/protected/models/UsuarioFotografia.php
@@ -0,0 +1,97 @@
+usuario)
+ throw new CException(Yii::t('profind', 'Usuario no asignado.'));
+
+ if ($this->tieneFotografia()) {
+ $fichero = $this->getRutaCompletaFicheroFotografia();
+ } else {
+ $fichero = Yii::getPathOfAlias('webroot') . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR;
+ $fichero .= 'user_photo.jpg';
+ }
+ $imgdata = base64_encode(file_get_contents($fichero));
+ return 'data:image/jpeg;base64,' . $imgdata;
+ }
+
+ /*
+ * Comprueba si el usuario ha subido su fotografía
+ * @return boolean
+ */
+ public function tieneFotografia() {
+ if (!$this->usuario)
+ throw new CException(Yii::t('profind', 'Usuario no asignado.'));
+
+ $fichero = $this->getRutaCompletaFicheroFotografia();
+ return file_exists($fichero);
+ }
+
+ /*
+ * Devuelve la ruta completa (ruta y nombre) del fichero con la fotografía del usuario.
+ * @return string ruta completa del fichero
+ */
+ private function getRutaCompletaFicheroFotografia() {
+ if (!$this->usuario)
+ throw new CException(Yii::t('profind', 'Usuario no asignado.'));
+
+ $upload = $this->usuario->getUploadPath();
+ $nombre = $this->getNombreFicheroFotografia();
+
+ return $upload . $nombre;
+ }
+
+ /*
+ * Devuelve el nombre del fichero con la fotografía del usuario.
+ * @return string nombre del fichero
+ */
+ private function getNombreFicheroFotografia() {
+ if (!$this->usuario)
+ throw new CException(Yii::t('profind', 'Usuario no asignado.'));
+
+ return $this->usuario->id . '.jpg';
+ }
+
+ /*
+ * Guarda una fotografía subida por el usuario
+ * return CUploadedFile fichero subido
+ */
+
+ public function guardarFotografia($fichero) {
+ if (!$this->usuario)
+ throw new CException(Yii::t('profind', 'Usuario no asignado.'));
+
+ if ($fichero) {
+ $nombre = $this->getRutaCompletaFicheroFotografia();
+ return $fichero->saveAs($nombre);
+ }
+ else
+ return false;
+ }
+
+ /*
+ * Elimina la fotografía del usuario
+ * return bool
+ */
+
+ public function eliminarFotografia() {
+ if (!$this->usuario)
+ throw new CException(Yii::t('profind', 'Usuario no asignado.'));
+
+ $fichero = $this->getRutaCompletaFicheroFotografia();
+ return unlink($fichero);
+ }
+}
+
+?>
diff --git a/www/themes/profind/js/bootstrap-fileupload.js b/www/themes/profind/js/bootstrap-fileupload.js
new file mode 100644
index 0000000..17cbc3c
--- /dev/null
+++ b/www/themes/profind/js/bootstrap-fileupload.js
@@ -0,0 +1,126 @@
+/* ===========================================================
+ * bootstrap-fileupload.js j1a
+ * http://jasny.github.com/bootstrap/javascript.html#fileupload
+ * ===========================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function ($) {
+
+ "use strict"; // jshint ;_
+
+ /* INPUTMASK PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Fileupload = function (element, options) {
+ this.$element = $(element)
+ this.type = this.$element.data('uploadtype') || (this.$element.find('.thumbnail').length > 0 ? "image" : "file")
+
+ this.$input = this.$element.find(':file')
+ if (this.$input.length === 0) return
+
+ this.name = this.$input.attr('name') || options.name
+
+ this.$hidden = this.$element.find(':hidden[name="'+this.name+'"]')
+ if (this.$hidden.length === 0) {
+ this.$hidden = $('')
+ this.$element.prepend(this.$hidden)
+ }
+
+ this.$preview = this.$element.find('.fileupload-preview')
+ var height = this.$preview.css('height')
+ if (this.$preview.css('display') != 'inline' && height != '0px' && height != 'none') this.$preview.css('line-height', height)
+
+ this.$remove = this.$element.find('[data-dismiss="fileupload"]')
+
+ this.listen()
+ }
+
+ Fileupload.prototype = {
+
+ listen: function() {
+ this.$input.on('change.fileupload', $.proxy(this.change, this))
+ if (this.$remove) this.$remove.on('click.fileupload', $.proxy(this.clear, this))
+ },
+
+ change: function(e, invoked) {
+ var file = e.target.files !== undefined ? e.target.files[0] : { name: e.target.value.replace(/^.+\\/, '') }
+ if (!file || invoked === 'clear') return
+
+ this.$hidden.val('')
+ this.$hidden.attr('name', '')
+ this.$input.attr('name', this.name)
+
+ if (this.type === "image" && this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match('image.*') : file.name.match('\\.(gif|png|jpe?g)$')) && typeof FileReader !== "undefined") {
+ var reader = new FileReader()
+ var preview = this.$preview
+ var element = this.$element
+
+ reader.onload = function(e) {
+ preview.html('')
+ element.addClass('fileupload-exists').removeClass('fileupload-new')
+ }
+
+ reader.readAsDataURL(file)
+ } else {
+ this.$preview.text(file.name)
+ this.$element.addClass('fileupload-exists').removeClass('fileupload-new')
+ }
+ },
+
+ clear: function(e) {
+ this.$hidden.val('')
+ this.$hidden.attr('name', this.name)
+ this.$input.attr('name', '')
+
+ this.$preview.html('')
+ this.$element.addClass('fileupload-new').removeClass('fileupload-exists')
+
+ this.$input.trigger('change', [ 'clear' ])
+
+ e.preventDefault()
+ return false
+ }
+ }
+
+
+ /* INPUTMASK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.fileupload = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('fileupload')
+ if (!data) $this.data('fileupload', (data = new Fileupload(this, options)))
+ })
+ }
+
+ $.fn.fileupload.Constructor = Fileupload
+
+
+ /* INPUTMASK DATA-API
+ * ================== */
+
+ $(function () {
+ $('body').on('click.fileupload.data-api', '[data-provides="fileupload"]', function (e) {
+ var $this = $(this)
+ if ($this.data('fileupload')) return
+ $this.fileupload($this.data())
+
+ if ($(e.target).data('dismiss') == 'fileupload') $(e.target).trigger('click.fileupload')
+ })
+ })
+
+}(window.jQuery)
diff --git a/www/themes/profind/views/layouts/main.php b/www/themes/profind/views/layouts/main.php
index 91c8689..3d4b419 100644
--- a/www/themes/profind/views/layouts/main.php
+++ b/www/themes/profind/views/layouts/main.php
@@ -35,7 +35,7 @@
name); ?>