Algunos enlaces sobre la metodología SCRUM:
http://albertoromeu.com/scrum/
Sitio donde organizar tarjetas:
Método Kanban:
http://www.elornitorrincoenmascarado.com/2014/05/a-todo-kanban-una-introduccion-kanb
Algunos enlaces sobre la metodología SCRUM:
http://albertoromeu.com/scrum/
Sitio donde organizar tarjetas:
Método Kanban:
http://www.elornitorrincoenmascarado.com/2014/05/a-todo-kanban-una-introduccion-kanb
En la cabecera del modelo Usuarios ponemos lo siguiente
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
Y dentro de la clase la siguiente función:
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new BlowfishPasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
En la cabecera de UsuariosController ponemos lo siguiente
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
Y dentro de la clase la siguiente función:
public function beforeFilter() {
parent::beforeFilter();
// Allow users to register and logout.
$this->Auth->allow('add');
}
Ponemos lo siguiente en la cabecera del AppController:
App::uses('AuthComponent', 'Controller/Component');
Y esto dentro de la clase:
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array(
'controller' => 'entradas',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'usuarios',
'action' => 'login'
),
'authenticate' => array(
'Form' => array('userModel' => 'Usuario', 'passwordHasher' => 'Blowfish')
),
'loginAction' => array('controller' => 'usuarios', 'action' => 'login')
)
);
También podemos permitir ciertas acciones si ponemos lo siguiente en el beforeFilter:
$this->Auth->allow('index');
La vista en Usuarios:
<div class="usuarios form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('Usuario'); ?>
<fieldset>
<legend>
<?php echo __('Please enter your username and password'); ?>
</legend>
<?php echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>
Para probar si funcionan bien los webservices creados vamos a crear una web que los ‘consuma’. En cualquier cakephp (puede ser el mismo) crearemos un controlador ClienteController:
<?php
App::uses('AppController', 'Controller');
App::uses('HttpSocket', 'Network/Http');
class ClienteController extends AppController {
public $components = array('Security', 'RequestHandler');
//Aquí pondréis la url de vuestra web
public $url = "http://localhost/cakeempresa/";
public function index() {
}
public function rest_index() {
$link = $this->url . 'rest_productos.json';
$data = null;
$httpSocket = new HttpSocket();
$response = $httpSocket->get($link, $data);
$this->set('response_code', $response->code);
$this->set('response_body', $response->body);
$this->render('/Cliente/respuesta');
}
public function rest_view($id) {
$link = $this->url . 'rest_productos/' . $id . '.json';
$data = null;
$httpSocket = new HttpSocket();
$response = $httpSocket->get($link, $data);
$this->set('response_code', $response->code);
$this->set('response_body', $response->body);
$this->render('/Cliente/respuesta');
}
public function rest_add() {
$link = $this->url . "rest_productos.json";
$data = null;
$httpSocket = new HttpSocket();
$data['Producto']['precio'] = 74;
$data['Producto']['proveedor_id'] = 1;
$data['Producto']['referencia'] = 'Extra';
$response = $httpSocket->post($link, $data);
$this->set('response_code', $response->code);
$this->set('response_body', $response->body);
$this->render('/Cliente/respuesta');
}
public function rest_edit($id) {
$link = $this->url . 'rest_productos/' . $id . '.json';
$data = null;
$httpSocket = new HttpSocket();
$data['Producto']['precio'] = 27;
$data['Producto']['referencia'] = 'Actualizada referencia';
$response = $httpSocket->put($link, $data);
$this->set('response_code', $response->code);
$this->set('response_body', $response->body);
$this->render('/Cliente/respuesta');
}
public function rest_delete($id) {
// remotely post the information to the server
$link = $this->url . 'rest_productos/' . $id . '.json';
$data = null;
$httpSocket = new HttpSocket();
$response = $httpSocket->delete($link, $data);
$this->set('response_code', $response->code);
$this->set('response_body', $response->body);
$this->render('/Cliente/respuesta');
}
}
Vista en View\Cliente\index.ctp:
<h1>Acciones</h1>
<p>
Escoja
<ul>
<li><?php echo $this->Html->link('Lista Productos', array('controller' => 'cliente', 'action' => 'rest_index')); ?></li><li><?php echo $this->Html->link('Ver producto con ID 1', array('controller' => 'cliente', 'action' => 'rest_view', 1)); ?></li>
<li><?php echo $this->Html->link('Añadir producto', array('controller' => 'cliente', 'action' => 'rest_add')); ?></li>
<li><?php echo $this->Html->link('Actualizar producto 2', array('controller' => 'cliente', 'action' => 'rest_edit', 2)); ?></li>
<li><?php echo $this->Html->link('Borrar producto 3', array('controller' => 'cliente', 'action' => 'rest_delete', 3)); ?></li></ul> </p>
Vista en View\Cliente\respuesta.ctp:
<h1>Código respuesta</h1> <p><?php echo $response_code; ?></p> <h1>Cuerpo respuesta</h1> <p><?php echo $response_body; ?></p>
Añadimos las siguientes líneas en routes.php (antes de’ require CAKE . ‘Config’ . DS . ‘routes.php’;’):
Router::mapResources('rest_productos');
Router::parseExtensions();
Y añadimos el controlador restProductos:
class RestProductosController extends AppController {
public $uses = array('Producto');
public $components = array('RequestHandler');
public function index() {
$productos = $this->Producto->find('all');
$this->set(array(
'productos' => $productos,
'_serialize' => array('productos')
));
}
public function add() {
$this->Producto->create();
if ($this->Producto->save($this->request->data)) {
$message = 'Created';
} else {
$message = 'Error';
}
$this->set(array(
'message' => $message,
'_serialize' => array('message')
));
}
public function view($id) {
$producto = $this->Producto->findById($id);
$this->set(array(
'producto' => $producto,
'_serialize' => array('producto')
));
}
public function edit($id) {
$this->Producto->id = $id;
if ($this->Producto->save($this->request->data)) {
$message = 'Saved';
} else {
$message = 'Error';
}
$this->set(array(
'message' => $message,
'_serialize' => array('message')
));
}
public function delete($id) {
if ($this->Producto->delete($id)) {
$message = 'Deleted';
} else {
$message = 'Error';
}
$this->set(array(
'message' => $message,
'_serialize' => array('message')
));
}
}
Poner una validación personalizada para el NIF:
'nif' => array(
'notBlank' => array(
'rule' => array('notBlank'),
'message' => 'El nif no puede estar en blanco',
),
'alfa' => array(
'rule' => array('custom', '/^(X(-|\.)?0?\d{7}(-|\.)?[A-Z]|[A-Z](-|\.)?\d{7}(-|\.)?[0-9A-Z]|\d{8}(-|\.)?[A-Z])$/i'),
'message' => 'Debe ser un nif válido',
),
)
Los productos no se borran, sólo pasan a ser inactivos. En el delete no borramos el producto, solo pasamos el campo activo a 0:
public function delete($id = null) {
$this->Producto->id = $id;
if (!$this->Producto->exists()) {
throw new NotFoundException(__('Invalid producto'));
}
$this->request->allowMethod('post', 'delete');
if ($this->Producto->saveField('activo', 0)) {
$this->Flash->success(__('The producto has been deleted.'));
} else {
$this->Flash->error(__('The producto could not be deleted. Please, try again.'));
}
return $this->redirect(array('action' => 'index'));
}
En el beforefind del modelo productos ponemos como condición que activo sea 1:
public function beforeFind($query) {
$query['conditions']['activo'] = 1;
return $query;
}
En la base de datos ponemos como valor por defecto de activo ‘1’ y eliminamos de cualquier vista la referencia al campo activo.
En la acción upload del controlador Productos compruebo que lo que me suben es una imagen:
$archivo = $this->request->data['Producto']['archivo'];
if (explode('/', $archivo['type'])[0] == 'image') {
move_uploaded_file($archivo['tmp_name'], WWW_ROOT . 'img' . DS . $this->request->data['Producto']['referencia'] . DS . $archivo['name']);
$this->Flash->success(__('Archivo subido.'));
} else {
$this->Flash->error(__('Solo se permiten imágenes.'));
}
Para ver las imágenes que hemos subido dentro de la vista de producto. En el controlador pasamos las imágenes encontradas:
public function view($id = null) {
if (!$this->Producto->exists($id)) {
throw new NotFoundException(__('Invalid producto'));
}
$options = array('conditions' => array('Producto.' . $this->Producto->primaryKey => $id));
$producto = $this->Producto->find('first', $options);
$this->set('producto', $producto);
$dir = new Folder(WWW_ROOT . "img/" . $producto['Producto']['referencia']."/");
$this->set('files', $dir->find(".*"));
}
En la vista (view.ctp) añadimos las líneas que nos mostrarán las imágenes:
<?php foreach ($files as $file): $this->Html->image($producto['Producto']['referencia']."/".$file); endforeach; ?>
class UtilidadesComponent extends Component {
public $components = array();
function areaCirculo($radio) {
return pi() * $radio * $radio;
}
function Circulo($radio) {
return 2 * pi() * $radio;
}
public function frase() {
$spam = array('Muy bueno', 'Estupenda entrada', 'Eres un crack', 'Lo mejor que he leído', 'Ole y ole', 'Me ha gustado', 'Bastante bueno', 'Muy interesante', 'De gran utilidad', 'Está bastante bien', 'Me ha hecho pensar');
$com = $spam[rand(0, count($spam) - 1)];
return $com;
}
function importeConIva($cantidad) {
return $cantidad * 1.21;
}
}