Integrando sfGuardUser con mi Perfil de Usuarios

Hola a todos, este sera un rapido posteo, porque no tengo tiempo… pero lo prometido es deuda…

Se instala sfGuardUserPlugin, como mejor les guste.
Teniendo en mi schema:

    usuario:
_attributes:    { phpName: Usuario, idMethod: native }
id:             { type: integer, required: true, primaryKey: true, autoIncrement: true }
sf_guard_user_id:   { type: integer, foreignTable: sf_guard_user, foreignReference: id, onDelete: cascade }
categoria_id:       { type: integer, foreignTable: categoria, foreignReference: id, onDelete: null }
nombre:         { type: varchar(255) }
apellido:       { type: varchar(255) }
nacimiento:     { type: date }
habilitado:     { type: boolean }       # simil is_active de sfGuardUser
email:          { type: varchar(255) }
telefono:       { type: varchar(255) }
codigo:         { type: varchar(32) }
updated_at:     ~
created_at:     ~

Podran notar el  ” sf_guard_user_id: ” … Este era mi entidad Usuario que luego decidi complementar con sfGuard. por loque cuando hable de Usuario, en tu caso podras decirle Perfil

Generen como mejor les resulte el modelo, DB, y el init-admin… para todos los modelos-clases incluido el sfGuarUser.
Por mi parte, lo genere para una APP, llamada “administracion” .
Por alguna razon que no recuerdo en /lib tengo “myUserProject.class.php” , algo asi como para tenerlo en todas las APPS:

Codigo:
class myUserProject extends sfGuardSecurityUser
{
}

Lo que tenemos que decidir es:

METODO 1 : si vamos a adjuntar sfGuardUser a nuestro modelo Usuario (perfil)

METODO 2 : si vamos a adjuntar nuestro modelo Usuario (perfil) al de sfGuardUser

El metodo 2, permite ver el ABM o CRUD de sfGuardUser, con los datos adicionales que queremos.
Mientras que el metodo 1, no da un ABM de nuestro modelo con el Username y Password del sfGuard (y nada mas)

METODO 1

En /lib/model tengo el archivo “Usuario.php”  cuyo codigo es:
class Usuario extends BaseUsuario {

/**********************************/
public function getUsername() {
if (!$this->isNew()) {
return $this->getsfGuardUser()->getUsername();
}
return null;
}
public function setUsername($p) {
if ($this->isNew() && $p != “”) {
$this->getsfGuardUser()->setUsername($p);
}
}
//———————————-
public function getRenuevaPassword() {
return null;
}
public function setRenuevaPassword($p) {
if ($p != “”) {
$this->getsfGuardUser()->setPassword($p);
}
}
//———————————-
public function getRenuevaPasswordBis() {
return null;
}
public function setRenuevaPasswordBis() {
}
//———————————-
public function getIsActive() {
return $this->getsfGuardUser()->getIsActive();
}
public function setIsActive($p) {
$this->getsfGuardUser()->setIsActive((isset($p) ? $p : 0));
}
}

Bueno ahora pasemos a la APP.
Em mi caso: /apps/administracion
Un vistazo a /apps/administracion/config.
No dice esto de app.yml:
# default values
all:
sf_guard_plugin:
profile_class:      Usuario
profile_field_name: sf_guard_user_id

sfMediaLibrary:
use_thumbnails: true
thumbnails_dir: thumbnails

Solo para molestar i18n.yml:
all:
default_culture:     es_AR
source:              XLIFF
debug:               on
cache:               on
untranslated_prefix: "-"
untranslated_suffix: "-"

El routing.yml:
# default rules
homepage:
url:   /
param: { module: default, action: index }

##############################################################

sf_guard_signin:
url:   /login
param: { module: sfGuardAuth, action: signin }

sf_guard_signout:
url:   /logout
param: { module: sfGuardAuth, action: signout }

sf_guard_password:
url:   /request_password
param: { module: sfGuardAuth, action: password }

##############################################################

default_symfony:
url:   /symfony/:action/*
param: { module: default }

default_index:
url:   /:module
param: { action: index }

default:
url:   /:module/:action/*

Y para terminar el CONFIG, el famoso settings.yml:
prod:
.settings:
no_script_name:           off

dev:
.settings:
error_reporting:
web_debug:              on
cache:                  off
no_script_name:         off
etag:                   off

test:
.settings:
error_reporting:
cache:                  off
web_debug:              off
no_script_name:         off
etag:                   off

all:
.actions:
login_module:           sfGuardAuth
login_action:           signin

secure_module:          sfGuardAuth
secure_action:          secure

.settings:
enabled_modules:        [default, sfGuardAuth, sfGuardGroup, sfGuardUser, sfGuardPermission]
i18n:                   on       # Enable interface translation. Set to off if your application should not be translated.

En apps/administracion/lib tenemos un amigo (hijo) cercano a uno anterior, el myUser.class.php:

class myUser extends myUserProject
{
}

Y ahora SI !!!
Vamos al /apps/administracion/modules/usuario , donde los hombres se hacen hombres … 🙂

En /apps/administracion/modules/usuario/actions/actions.class.php

class usuarioActions extends autousuarioActions {

/**
* @see autoUsuarioActions::getUsuarioOrCreate()
*
* @param unknown_type $id
* @return unknown
*/
protected function getUsuarioOrCreate($id = ‘id’) {
if (! $this->getRequestParameter($id)) {
$usuario = new Usuario();
$usuario->setsfGuardUser(new sfGuardUser());/**/
} else {
$usuario = UsuarioPeer::retrieveByPk($this->getRequestParameter($id));
$this->forward404Unless($usuario);
}
return $usuario;
}

public function updateUsuarioFromRequest() {
$this->usuario->setIsActive(0);
parent::updateUsuarioFromRequest();
}

}

Y la MAGIMA en /apps/administracion/modules/usuario/config/generator.yml:
generator:
class:              sfPropelAdminGenerator
param:
model_class:      Usuario
theme:            default

fields:
username:             { name: Mi Usuario, type: input_tag }
renueva_password:     { name: Nueva Password, type: input_tag }
renueva_password_bis: { name: Nueva Password, type: input_tag }
is_active:            { name: Activo, type: checkbox_tag }
list:
title:          Lista de Perfiles
display:    [nombre, apellido, nacimiento, email, created_at]
object_actions:
_edit:         ~
_delete:       ~
actions:
_create:       ~
filters: [ nombre ]

edit:
title:          Datos del Usuario %%username%%
display:    [categoria_id, username, renueva_password, is_active, nombre, apellido, nacimiento, habilitado, email, telefono, codigo]
actions:
_list:          ~
_save_and_list: ~
_save:          ~
_save_and_add:  ~
#_delete:        ~

TODO ESTO ES EL METODO 1,PASEMOS AL…

METODO 2

Ajusten los cinturones, Esto esta bueno, pero hay mas archivos.
Voy a suponer que leyeron el Metodo 1, y que tiene un /apps/administracion/config/*  igualito.

Ahora vamos a trabajar en /plugins/sfGuardPlugin.
Tenemos un /plugins/sfGuardPlugin/lib/model/sfGuardUser.php:

class sfGuardUser extends PluginsfGuardUser
{

/**********************************/
public function getNombre() {
return $this->getProfile()->getNombre();
}
public function setNombre($p) {
$this->getProfile()->setNombre($p);
$this->getProfile()->save(); // el perfil lo debo guardar ya que no se hidrata de sfGuardUser a Profile, sino de Profile a sfGuardUser
}
//———————————-
public function getApellido() {
return $this->getProfile()->getApellido();
}
public function setApellido($p) {
$this->getProfile()->setApellido($p);
$this->getProfile()->save();
}
//———————————-
public function getEmail() {
return $this->getProfile()->getEmail();
}
public function setEmail($p) {
$this->getProfile()->setEmail($p);
$this->getProfile()->save();
}
//———————————-
public function getNacimiento() {
return $this->getProfile()->getNacimiento();
}
public function setNacimiento($p) {
$this->getProfile()->setNacimiento($p);
$this->getProfile()->save();
}
//———————————-
public function getTelefono() {
return $this->getProfile()->getTelefono();
}
public function setTelefono($p) {
$this->getProfile()->setTelefono($p);
$this->getProfile()->save();
}
}

Y aqui viene otra vez la MAGIA, en el metodo 2.

En /plugins/sfGuardPlugin/modules/sfGuardUser/actions/actions.class.php , tenemos redifinicio para buscar en el list (se imaginan?)
Ademas, como buen alumno, anote algunas reflexiones en el mismo codigo, asi siempre solo debemos copiar y pegar , para otros proyectos y tener una asi una ayuda de que demonios se esta haciendo

class sfGuardUserActions extends BasesfGuardUserActions {
/*
# usar como filtro a "nombre" implica que addFiltersCriteria($c)
# filtre por sfGuardUserPeer::NOMBRE , y como NOMBRE no es un
# atributo/CONSTANTE de esta clase => Fatal error: Undefined class constant 'NOMBRE' in /home/icox/Escritorio/PROYECTOS/callcenter/cache/administracion/dev/modules/autoSfGuardUser/actions/actions.class.php on line 256
# como debo usar UsuarioPeer::NOMBRE o PorfileClassPeer::NOMBRE
# se crea un filtro adicionar recargando el metodo addFiltersCriteria($c)
#
# if (isset($this->filters['nombre']) && $this->filters['nombre'] != '') {
#     $c->add(UsuarioPeer::NOMBRE, strtr($this->filters['nombre'], '*', '%'), Criteria::LIKE);
#     $c->addJoin(UsuarioPeer::SF_GUARD_USER_ID, sfGuardUserPeer::ID);
# }
#
# y un elemento parcial en el template para que dibuje el HTML
#
#
# Podemos usar filters[nombre] o filters[CUALQUIERA] (usar _ dentro de CUALQUIERA me dio error), no nos preocupanos
# si coincide con el field que acabamos de traer a la entidad, que es este no se usara
# para los filtros y por ende addFiltersCriteria() no recibira tal parametro para el sfGuardUserPeer
#
# Solo debemos considerar que el nombre del template del elemento parcial sea
# el que usamos en la definicion del filters del generator _perfil_nombre => _perfil_nombre.php
*/

protected function addFiltersCriteria($c) {
parent::addFiltersCriteria($c);

if (isset($this->filters[‘perfilnombre’]) && $this->filters[‘perfilnombre’] != ”) {
$c->add(UsuarioPeer::NOMBRE, strtr($this->filters[‘perfilnombre’], ‘*’, ‘%’), Criteria::LIKE);
$c->addJoin(UsuarioPeer::SF_GUARD_USER_ID, sfGuardUserPeer::ID);
}

if (isset($this->filters[‘perfilapellido’]) && $this->filters[‘perfilapellido’] != ”) {
$c->add(UsuarioPeer::APELLIDO, strtr($this->filters[‘perfilapellido’], ‘*’, ‘%’), Criteria::LIKE);
$c->addJoin(UsuarioPeer::SF_GUARD_USER_ID, sfGuardUserPeer::ID);
}
if (isset($this->filters[‘perfiltelefono’]) && $this->filters[‘perfiltelefono’] != ”) {
$c->add(UsuarioPeer::TELEFONO, strtr($this->filters[‘perfiltelefono’], ‘*’, ‘%’), Criteria::LIKE);
$c->addJoin(UsuarioPeer::SF_GUARD_USER_ID, sfGuardUserPeer::ID);
}
if (isset($this->filters[‘perfilemail’]) && $this->filters[‘perfilemail’] != ”) {
$c->add(UsuarioPeer::EMAIL, strtr($this->filters[‘perfilemail’], ‘*’, ‘%’), Criteria::LIKE);
$c->addJoin(UsuarioPeer::SF_GUARD_USER_ID, sfGuardUserPeer::ID);
}

if (isset($this->filters[‘perfilgrupos’]) && $this->filters[‘perfilgrupos’] != ”) {
$c->add(sfGuardGroupPeer::NAME, strtr($this->filters[‘perfilgrupos’], ‘*’, ‘%’), Criteria::LIKE);
$c->addJoin(sfGuardGroupPeer::ID, sfGuardUserGroupPeer::GROUP_ID);
$c->addJoin(sfGuardUserGroupPeer::USER_ID, sfGuardUserPeer::ID);
}

}
}

Como se menciono, hay unos templeates… solo voy a poner el del apellido, los demas son similares …….
En /plugins/sfGuardPlugin/modules/sfGuardUser/templates/_perfil_apellido.php:

Ojo como nombramos las cosas, en el generador
/plugins/sfGuardPlugin/modules/sfGuardUser/config/genereator.yml:

generator:
class:              sfPropelAdminGenerator
param:
model_class:      sfGuardUser
theme:            default

fields:
#username:     { name: NICK, type: input_tag }
password_bis: { name: “Password (again)” }
nombre:       { name: Nombres, type: input_tag }
perfil_nombre:    { name: Nombres, type: input_tag }
perfil_apellido:  { name: Apellidos, type: input_tag }
perfil_telefono:  { name: Telefono, type: input_tag }
perfil_email:  { name: Email, type: input_tag }
grupos:  { name: Grupos, type: input_tag }
apellido:     { name: Apellido, type: input_tag }
email:        { name: Email, type: input_tag }
nacimiento:   { name: Nacimiento, type: input_date_tag }
telefono:     { name: Telefono, type: input_tag, help: Numero de Telefono fijo o Celular }

list:
fields:
nombre: { name: Nombre, type: input_tag, params: disabled=false }
peer_method:
object_actions:
_edit:         ~
_delete:       ~
title:   Lista de Usuarios
display: [ =username, nombre, apellido, created_at, last_login ]
filters: [ _grupos, _perfil_nombre, _perfil_apellido, _perfil_telefono, _perfil_email, created_at, username ]

edit:
title: Edit “%%username%%” user
fields:
password:
password_bis:
groups:       { name: Groups/Roles, type: admin_double_list, params: through_class=sfGuardUserGroup }
permissions:  { name: permissions, type: admin_check_list, params: through_class=sfGuardUserPermission }
last_login:   { type: plain }
display:
“NONE”:                     [ username, _password, _password_bis ]
“Informacion”:              [ nombre, apellido, email, telefono, last_login ]
“Permisos y Grupos”:        [ is_active, groups, permissions ]

LISTO!!!
(Falta lo de siempre, limpiar cache, o borrarlo, regenerar si quieren, etc etc)
Creo es todo, es un post en tiempo record. Creo que deberia luego probarlo yo mismo, para ver si me olvide algo.

Pero queria dejar documentado, esto para nuestro symfony 1.0.x

En breve tratare de hacer lo mismo para 1.1, al que ya estoy abocado, y donde creo que podre hacerlo mas facil

Salutte a Tutti Cuanti!!

Roberto

Esta entrada fue publicada en Symfony. Guarda el enlace permanente.

Una respuesta a Integrando sfGuardUser con mi Perfil de Usuarios

  1. plmarcelo dijo:

    Hola Roberto,

    Muy buena esta publicación. He utilizado el metodo 2 y me funciono de lo mas bien todo excepto la validacion, cuando hay campos foreign keys. Entonces para solucionar esto lo que hice fue agregar el siguiente metodo en la case sfGuardUser:

    public function save($con = null)
    {
    parent::save($con);

    $this->getProfile()->save();

    }

    Y entonces quite todos los save de los settters. Y ahora todo va bien, ya que el save() ocurre despues de la validación.

    Salu2 y muchas gracias,
    Pedro

Deja un comentario