= 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: {{{ 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: {{{ 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(); } } ?> }}}