wiki:WF/camadamodel

Version 2 (modified by viani, 16 years ago) (diff)

--

Camada de Modelo

A camada Model define o que o processo vai fazer e como implementá-lo, ou seja, as regras de negócio do sistema. Ela possibilita o desenvolvimento de recursos, independentemente da forma como os dados serão exibidos (interface) e do momento em que serão executados (fluxo). Essa camada deve saber somente como executar cada recurso do sistema.

Assim como na camada de Controle, a camada Model, também é subdivida em três níveis:

  • Nível módulo: representado pela classe BaseModel;
  • Nível processo: representado pela classe Model;
  • Nível atividade: representado pela classe AtividadeModel?.

Os três níveis unem-se por herança no seguinte esquema:

BaseModel -> Model -> AtividadeModel?

A classe BaseModel está declarada no módulo workflow e vale para todos os processos. Nela estão codificados atributos e métodos de uso geral a serem usados pelas camadas Model das atividades.

Atributos da classe BaseModel:

  • instance: objeto da instância em execução;
  • activity: objeto da atividade em execução;
  • DAO: objeto da camada de abstração de banco de dados;
  • request: array com os dados submetidos pelo formulário da camada View;
  • workflow: array com as variáveis do ambiente de execução da atividade;
  • natural: objeto para conexão com o mainframe;
  • factory: objeto para a requisição de instâncias das classes auxiliares, como organograma, ldap, etc;
  • viewData: array contendo os dados a serem exibidos na camada View
  • Contém atributos privados da camada model;
  • Contém atributos que representam as propriedades da instância em execução;
  • Pode conter outros atributos para armazenamento de instâncias de classes de negócio (como paginação, filtros, etc);

Em especial o atributo viewData, seu objetivo é armazenar os dados a serem retornados para a camada de Controle. Esta é a forma ideal para que um método de negócio da Model faça o retorno de dados.

Os atributos da instância, por padrão, deverão começar com o caracter underline para diferenciá-los dos atributos privados da classe.

Métodos da classe BaseModel:

  • getAttributes: retorna os atributos da instância (aqueles iniciados por underline);
  • getRequest: cria atributos na classe para as variáveis do array Request;
  • addViewVar: adiciona uma variável ao array viewData;
  • getViewVar: recupera uma variável do array viewData;
  • setWfProperty: seta o valor de uma variável do ambiente de execução;
  • getWfProperty: recupera o valor de uma variável do ambiente;
  • setNameInstance: seta o valor do identificador da instância;
  • updateInstance: transfere os atributos de instância que estão na classe para o objeto instance;
  • updateAttributes: carrega nos atributos de instância da classe os valores que estão no objeto instance;
  • commitInstance: sinaliza para o módulo workflow que a instância deve ser salva em disco.

A maneira de representar uma classe model é criando um arquivo no formato class.Atividade.Model.inc.php, e armazenando este arquivo no diretório 'code' da estrutura de diretórios do processo, semelhante ao que foi feito anteriormente com a camada de Controle. O arquivo deverá conter:

  • Uma classe com nome no formato AtividadeModel, que extenda a classe Model do processo;
  • Métodos que implementam cada uma das ações solicitadas pelo usuário e encaminhadas pelo Controller;
  • Resultados booleanos indicando sucesso ou falha na requisição feita pelo usuário.

Abaixo um exemplo de camada Model de uma atividade:

<?php
/**
 * Implementa a atividade Compor do processo Atos Administrativos.
 * @author carloseduardo
 * @author viani
 * @author aleheil
 * @version 1.4
 * @license http://www.gnu.org/copyleft/gpl.html GPL 
 * @package Atos_Administrativos.
 */
class ComporModel extends Model
{
	/**
	 * Implementa acao padrao da atividade Compor.
         * @license http://www.gnu.org/copyleft/gpl.html GPL. 
	 * @access public.
	 * @return boolean.
	 */
	function defaultAction()
	{	
		$ano = date('Y');
		$this->addViewVar("categoria"	, 	"10000"				);
		$this->addViewVar("categlist"	, 	$this->lista_categorias()	);
		$this->addViewVar("ano"		,  	$ano				);
		$this->addViewVar("lista_anos"	,  	$this->lista_anos($ano)		);
		return true;			
	}
	
	/**
	 * Implementa acao Salvar - Atribui valor as variaveis da instancia e passa
	 *  para a proxima atividade
	 * @return bool
	 * @access public
	 */
	function salvarAction()
	{
		if (!count($erro = $this->verifica_erros($this->request)))
		{
			$this->_usuario  	=  	$this->getWfProperty('wf_user_name');
			$this->_categoria	=	trim($this->request['categoria']);
			$this->_numero		=	trim($this->request['numero']	);
			$this->_area		=	trim($this->request['area']		);
			$this->_assunto		=	trim($this->request['assunto']	);
			$this->_texto		=	trim($_POST['texto']			);
			$this->_ano		=	$this->request['ano'];
			
			$this->updateInstance();
			$this->instance->setNextUser($this->getWfProperty('wf_user_id'));
			$this->setNameInstance($this->_assunto);
			$this->commitInstance();
			return true;
		}
		else
		{
			$this->addViewVar("msg"		,	$erro				);
			$this->addViewVar("icon_msg"	, 	"icon_msg_erro.png"		);
			$this->addViewVar("class_msg"	, 	"msg_erro"			);
			$this->addViewVar("categoria"	,	$this->request['categoria']	);
			$this->addViewVar("numero"	,	$this->request['numero']	);
			$this->addViewVar("area"	,	$this->request['area']		);
			$this->addViewVar("assunto"	,	$this->request['assunto']	);
			$this->addViewVar("texto"	,	$_POST['texto']			);
			$this->addViewVar("ano"		,	$this->request['ano']		);
			$this->addViewVar("categlist"	, 	$this->lista_categorias()	);
			$this->addViewVar("lista_anos"	,  	$this->lista_anos(date('Y')));
			return false;
		}
	}
}
?>

Neste exemplo estão codificados duas ações da atividade: default e salvar. Ambos serão acionados pela camada de controle conforme as ações forem solicitadas. O método defaultAction() é encarregado de preparar os dados a serem exibidos na camada de visualização quando a atividade for executada a primeira vez. Já o método SalvarAction?() implementa o que fazer quando o usuário clicar no botão Salvar do formulário da atividade. Analisando mais a fundo este método, ele começa fazendo uma consistência nos dados vindos do formulário (representado pelo objeto Request). Caso sejam válidos realiza as seguintes operações:

  • Armazena os dados do formulário como atributos da camada Model;
  • Em seguida executa o método updateInstance() que irá transferir para a instância os atributos da camada Model;
  • Seta qual o próximo usuário que irá receber a instância. Isso é feito pelo método setNextUser();
  • Executa o método commitInstance(), que fará a atualização da instância definitivamente e encerrará a execução da atividade;
  • Retorna indicativo de sucesso da operação

Caso exista inconsistência nos dados do formulário, irá:

  • Preparar os dados para serem exibidos novamente ao usuário. Cada chamada ao método addViewVar cria uma variável a ser passada para a camada de visualização;
  • Retornar indicativo de insucesso da operação.

Isso conclui a camada Model a nível de atividade.

Agora é necessário definir a camada Model a nível de processo, cuja finalidade é difinir os atributos da instância e também os métodos de modelo que são comuns a todo o processo.

Eis um exemplo de camada de Modelo a nível de processo:

<?php
/**
 * Implementa o modelo do processo Atos Administrativos.
 * @author carloseduardo
 * @author viani
 * @author aleheil
 * @version 1.4
 * @license http://www.gnu.org/copyleft/gpl.html GPL 
 * @package Atos_Administrativos.
 */ 
class Model extends BaseModel 
{	
	/**
	 * @var $filter
	 * @warning NOMES DE ATRIBUTOS DE PROCESSO COMEÇAM COM O CARACTERE _
	 * @access protected.
	 */	
	var $filter;	

	/**
	 * @var $_categoria
	 * @access protected
	 */	
	var $_categoria;
	
	/**
	 * @var $_ano
	 * @access protected
	 */	
	var $_ano; 
	
	/**
	 * @var $_numero
	 * @access protected
	 */	
	var $_numero;
	
	/**
	 * @var $_area
	 * @access protected
	 */	
	var $_area;
	
	/**
	 * @var $_assunto
	 * @access protected
	 */	
	var $_assunto;

	/**
	 * @var $_texto
	 * @access protected
	 */	
	var $_texto;
	
	/**
	 * @var $_email
	 * @access protected
	 */	
	var $_email;
	
	/**
	 * @var $_usuario
	 * @access protected
	 */	
	var $_usuario;
	 
	/**
	 * Monta um array com o resultado da busca ao banco de dados - array com todas as categorias
	 * cadastradas na tabela categorias.
	 * @return array Resultado da seleção.
	 * @access public
	 */
	function lista_categorias()
	{
		$commandText = "
			SELECT 
				* 
			FROM 
				atos.categoria
			ORDER BY 
				categoria_id";
				
		$resultSet = $this->DAO->query($commandText);
		$categorias = array(""	=>	"----- Selecione -----");
		while ($res = $resultSet->fetchRow(DB_FETCHMODE_ASSOC)) {
			$indice = $res['categoria_id'];
			$categorias[$indice] = $res['descricao'];
		}	
		
		return $categorias;	
	}
	
	/**
	 * Função que monta um array de sequencia de anos para que o usuario possa escolher o ano do ato
	 * @author aleheil
	 * @return array array com uma sequencia de dois anos antes ao corrente e dois depois do corrente
	 */
	function lista_anos($ano_atual)
	{
		$lista_anos = array();
		$ano 		= $ano_atual-2;
		
		while ($ano <= ($ano_atual+2))
		{
			$lista_anos[$ano] = $ano;
			$ano = $ano+1;
		}
		
		return $lista_anos;
	}
	
	/**
	 * Valida dados do formulário.
	 * @return array Resultado da validação.
	 * @access public
	 */
	function verifica_erros()
	{
		$erro = array();
		
		if ($_REQUEST['categoria'] == "" ) 
			$erro[] = "Escolha uma categoria correspondente ao Ato Administrativo.";
		
		if (trim($_REQUEST['numero']) == "") 
			$erro[] = "O preenchimento do campo Número é obrigatório.";
		elseif (!ereg ("^[0-9]{1,3}$", trim($_REQUEST['numero'])))
			$erro[] = "Número de Ato inválido.";
		
		if ( trim($_REQUEST['area']) == "" ) 
			$erro[] = "O preenchimento do campo Área é obrigatório.";
		
		if (trim($_REQUEST['assunto']) == "") 
			$erro[] = "O preenchimento do campo Assunto é obrigatório.";
		
		if ( trim($_REQUEST['texto']) == "" ) 
			$erro[] = "O preenchimento do campo Texto é obrigatório.";
		
		return $erro;
	}
	
	 /**
	  * Construtor da camada Model em nivel de processo.
	  * @param array $env Configuracao MVC.
	  * @return Model.
	  * @license http://www.gnu.org/copyleft/gpl.html GPL 
	  * @access protected
	  */
	function Model(&$env) 
	{
	   $this->super(&$env);
    	   $this->filter	=	& new Filtro();  
	}	
}
?>