/** * Recupera os nos filhos de uma arvore * * Efetua a consulta uma unica vez. * Depois que os nos filhos estao populados, sempre * utiliza os nos encontrados * * @author Hugo Ferreira da Silva * @param boolean $loadSubChilds Indica se os filhos deverao carregar seus sub-filhos * @return Lumine_Tree_NodeList */ public function getChildNodes($loadSubChilds = false) { // se ainda nao buscou os nos filhos if (is_null($this->childNodes)) { // cria um node list $this->childNodes = new Lumine_Tree_NodeList(); // pega o codigo deste objeto $code = $this->obj->{$this->fieldId}; // se tiver um codigo if (!is_null($code)) { // inicia a reflexao $ref = new ReflectionClass($this->obj->_getName()); // recupera uma nova instancia $inst = $ref->newInstance(); // consulta os filhos $inst->where('{' . $this->fieldParentId . '} = ?', $code)->find(); // para cada filho encontrado while ($inst->fetch()) { // cria uma nova instancia $temp = $ref->newInstanceArgs(); // popula com os dados encontrados $temp->_setFrom($inst->toArray()); // cria um no $node = new Lumine_Tree_Node($temp, $this->fieldId, $this->fieldParentId); // informa que este objeto eh o parentNode $node->parentNode = $this; if (!is_null($this->getTree())) { // informa a arvore $node->setTree($this->getTree()); } if ($loadSubChilds) { $node->getChildNodes($loadSubChilds); } // coloca na lista $this->childNodes->add($node); } // destroi o objetode consulta $inst->destroy(); } } // retorna os nos filhos return $this->childNodes; }
/** * @param Lumine_Base $obj Objeto a ser validado * @return array - Retorna array contendo erros caso validacao invalida * @author Cairo Lincoln de Morais Noleto * @link http://caironoleto.wordpress.com * @author Hugo Ferreira da Silva * @link http://www.hufersil.com.br **/ public static function validate(Lumine_Base $obj) { $fieldList = !empty(self::$validateList[$obj->_getName()]) ? self::$validateList[$obj->_getName()] : array(); $errors = array(); foreach ($fieldList as $fieldName => $validators) { // se ja houver um erro para o campo atual if (self::checkStackError($errors, $fieldName) == true) { // passa para o proximo campo continue; } foreach ($validators as $array) { // se ja houver um erro para o campo atual if (self::checkStackError($errors, $fieldName) == true) { // passa para o proximo campo break; } switch ($array["tipoValidacao"]) { //Verifica se e String case 'requiredString': if (!is_string($obj->{$array}["campo"]) || strlen($obj->{$array}["campo"]) == 0) { self::stackError($errors, $fieldName, $array['message']); } if (isset($array["minimo"]) && strlen($obj->{$array}['campo']) < $array['minimo']) { self::stackError($errors, $fieldName, $array['message']); } // se foi informado o tamanho maximo if (isset($array['maximo'])) { // pega o campo $field = $obj->_getField($fieldName); // se o tamanho informado for maior que o comprimento if (isset($field['length']) && $array['maximo'] > $field['length']) { throw new Lumine_Exception('Tamanho invalido para o campo ' . $fieldName, Lumine_Exception::WARNING); } // alterado para se o usuario // informou um tamanho minimo, mas nao o maximo, // o maximo passa a ser o do campo } else { if (!isset($array['maximo']) && isset($array['minimo'])) { $field = $obj->_getField($fieldName); if (isset($field['length'])) { $array['maximo'] = $field['length']; } } } if (isset($array["maximo"]) && strlen($obj->{$array}['campo']) > $array['maximo']) { self::stackError($errors, $fieldName, $array['message']); } break; //Verifica se e Numero //Verifica se e Numero case 'requiredNumber': if (!is_numeric($obj->{$array}["campo"])) { self::stackError($errors, $fieldName, $array['message']); } else { if (is_numeric($obj->{$array}['campo'])) { if (!is_null($array['minimo']) && $obj->{$array}['campo'] < $array['minimo']) { self::stackError($errors, $fieldName, $array['message']); } else { if (!is_null($array['maximo']) && $obj->{$array}['campo'] > $array['maximo']) { self::stackError($errors, $fieldName, $array['message']); } } } } break; //Verifica se Tamanho invalido //Verifica se Tamanho invalido case 'requiredLength': if (isset($array["minimo"])) { if (strlen($obj->{$array}["campo"]) < $array["minimo"]) { self::stackError($errors, $fieldName, $array['message']); } } if (isset($array["maximo"])) { if (strlen($obj->{$array}["campo"]) > $array["maximo"]) { self::stackError($errors, $fieldName, $array['message']); } } break; //Verifica se e email //Verifica se e email case 'requiredEmail': //Lumine_Util::validateEmail( $val ); $res = Lumine_Util::validateEmail($obj->{$array}["campo"]); if ($res === false) { self::stackError($errors, $fieldName, $array['message']); } break; //Verifica se e uma data //Verifica se e uma data case 'requiredDate': $val = $obj->{$array}["campo"]; if (!preg_match('@^((\\d{2}\\/\\d{2}\\/\\d{4})|(\\d{4}-\\d{2}-\\d{2}))$@', $val, $reg)) { self::stackError($errors, $fieldName, $array['message']); // se digitou no formato com barras } else { if (!empty($reg[2])) { list($dia, $mes, $ano) = explode('/', $reg[2]); // se nao for formato brasileiro e norte-americano if (!checkdate($mes, $dia, $ano) && !checkdate($dia, $mes, $ano)) { self::stackError($errors, $fieldName, $array['message']); } // se digitou no formato ISO } else { if (!empty($reg[3])) { list($ano, $mes, $dia) = explode('-', $reg[3]); // se for uma data valida if (!checkdate($mes, $dia, $ano)) { self::stackError($errors, $fieldName, $array['message']); } } } } break; //Verifica se e uma data/hora //Verifica se e uma data/hora case 'requiredDateTime': $val = $obj->{$array}["campo"]; if (!preg_match('@^((\\d{2}\\/\\d{2}\\/\\d{4})|(\\d{4}-\\d{2}-\\d{2})) (\\d{2}:\\d{2}(:\\d{2})?)$@', $val, $reg)) { self::stackError($errors, $fieldName, $array['message']); // se digitou no formato com barras } else { if (!empty($reg[2])) { list($dia, $mes, $ano) = explode('/', $reg[2]); // se nao for formato brasileiro e norte-americano if (!checkdate($mes, $dia, $ano) && !checkdate($dia, $mes, $ano)) { self::stackError($errors, $fieldName, $array['message']); } // se digitou no formato ISO } else { if (!empty($reg[3])) { list($ano, $mes, $dia) = explode('-', $reg[3]); // se for uma data valida if (!checkdate($mes, $dia, $ano)) { self::stackError($errors, $fieldName, $array['message']); } } } } break; //Verifica uniquidade // - Alteracao por Hugo: Aqui fiz uma mudanca, porque // se fosse feita um update, daria erro. por isso, checamos as chaves primarias //Verifica uniquidade // - Alteracao por Hugo: Aqui fiz uma mudanca, porque // se fosse feita um update, daria erro. por isso, checamos as chaves primarias case 'requiredUnique': $reflection = new ReflectionClass($obj->_getName()); $objeto = $reflection->newInstance(); $objeto->{$fieldName} = $obj->{$fieldName}; $objeto->find(); $todas = true; while ($objeto->fetch()) { $pks = $objeto->_getPrimaryKeys(); foreach ($pks as $def) { if ($objeto->{$def}['name'] != $obj->{$def}['name']) { $todas = false; self::stackError($errors, $fieldName, $array['message']); break; } if ($todas == false) { break; } } } unset($objeto, $reflection); break; //Verifica uma funcao //Verifica uma funcao case 'requiredFunction': // se for um array if (is_array($array['message'])) { $result = call_user_func_array($array['message'], array($obj, $fieldName, $obj->{$fieldName})); if ($result !== true) { self::stackError($errors, $fieldName, $result); break; } } if (is_string($array['message'])) { $function = new ReflectionFunction($array['message']); $result = $function->invoke($obj, $fieldName, $obj->{$fieldName}); if ($result !== true) { //$errors[] = $result; self::stackError($errors, $fieldName, $result); } unset($function); } break; //Verifica se e CPF //Verifica se e CPF case 'requiredCpf': $res = ValidateCPF::execute($obj->{$array}["campo"]); if ($res === false) { self::stackError($errors, $fieldName, $array['message']); } break; //Verifica se e CNPJ //Verifica se e CNPJ case 'requiredCnpj': $res = ValidateCNPJ::execute($obj->{$array}["campo"]); if ($res === false) { self::stackError($errors, $fieldName, $array['message']); } break; default: return true; break; } } } return $errors; }
/** * Efetua a validacao * * @author Hugo Ferreira da Silva * @link http://www.hufersil.com.br/ * @param Lumine_Base $obj Objeto a ser validado * @return array Array contendo os erros encontrados */ public function doValidation() { // nao possui arquivo XML para validacao, sempre retorna true if (empty($this->xml)) { return true; } $xml = new DomDocument(); $xml->validateOnParse = true; $xml->load($this->xml); $errors = libxml_get_errors(); libxml_clear_errors(); if (!empty($errors)) { Lumine_Log::error('A validacao de "' . $this->obj->_getName() . '" nao pode ser executada por erros na formacao do XML. Analise o retorno do metodo "validate" para ver os erros'); foreach ($errors as $error) { $this->errors[] = trim($error->message); } return false; } // ok, o XML nao contem erros // vamos pegar os campos da validacao $xpath = new DOMXPath($xml); $DOMFieldList = $xpath->query('//lumine-validator/field'); $errors = array(); foreach ($DOMFieldList as $DOMField) { // verifica se o campo existe try { $field = $this->obj->_getField($DOMField->getAttribute('name')); $fieldname = $field['name']; // recupera a lista de validator para este campo $query = "//lumine-validator/field[@name='{$fieldname}']/validator"; $DOMValidatorList = $xpath->query($query); // para cada validator foreach ($DOMValidatorList as $DOMvalidator) { // se ja tiver validado o campo, houver outro validator // e nao passou no anterior, passa para proximo campo if (isset($errors[$fieldname]) && $errors[$fieldname] !== true) { break; } // pega os valores dos atributos $minlength = sprintf('%d', $DOMvalidator->getAttribute('minlength')); $maxlength = sprintf('%d', $DOMvalidator->getAttribute('maxlength')); $minvalue = $DOMvalidator->getAttribute('minvalue'); $maxvalue = $DOMvalidator->getAttribute('maxvalue'); $classname = $DOMvalidator->getAttribute('classname'); $msg = $DOMvalidator->getAttribute('msg'); $rule = $DOMvalidator->getAttribute('rule'); $method = $DOMvalidator->getAttribute('method'); $val = $this->obj->{$fieldname}; $res = false; if (empty($classname)) { $classname = $DOMvalidator->getAttribute('name'); } if ($minvalue != '') { $minvalue = (double) $minvalue; } else { $minvalue = null; } if ($maxvalue != '') { $maxvalue = (double) $maxvalue; } else { $maxvalue = null; } // ve o tipo switch ($DOMvalidator->getAttribute('type')) { case 'requiredString': $res = $this->validateRequiredString($val, $minlength, $maxlength); break; case 'requiredNumber': $res = $this->validateRequiredNumber($val, $minvalue, $maxvalue); break; case 'requiredEmail': $res = Lumine_Util::validateEmail($val); break; //Verifica se e uma data //Verifica se e uma data case 'requiredDate': if (!preg_match('@^((\\d{2}\\/\\d{2}\\/\\d{4})|(\\d{4}-\\d{2}-\\d{2}))$@', $val, $reg)) { $res = false; // se digitou no formato com barras } else { if (!empty($reg[2])) { list($dia, $mes, $ano) = explode('/', $reg[2]); // se nao for formato brasileiro e norte-americano if (!checkdate($mes, $dia, $ano) && !checkdate($dia, $mes, $ano)) { $res = false; } // se digitou no formato ISO } else { if (!empty($reg[3])) { list($ano, $mes, $dia) = explode('-', $reg[3]); // se for uma data valida if (!checkdate($mes, $dia, $ano)) { $res = false; } } else { $res = true; } } } break; //Verifica se e CPF //Verifica se e CPF case 'requiredCpf': $res = ValidateCPF::execute($val); break; //Verifica se e CNPJ //Verifica se e CNPJ case 'requiredCnpj': $res = ValidateCNPJ::execute($val); break; case 'unique': $res = $this->validateUnique($val, $fieldname); break; case 'class': $res = $this->validateByClass($val, $fieldname, $classname, $method); break; case 'rule': $res = $this->validateRule($val, $rule); break; default: throw new Lumine_Validator_Exception('Tipo de validator desconhecido: ' . $DOMValidator->getAttribute('type')); } if ($res === false) { $errors[$fieldname] = utf8_decode($msg); } else { $errors[$fieldname] = $res; } } } catch (Exception $e) { Lumine_Log::warning($e->getMessage()); } } // depois de todas as validacoes, vamos ver se deu erro em algum campo $tudo_ok = true; foreach ($errors as $chave => $erro) { if ($erro !== true) { $tudo_ok = false; $this->errors = $errors; break; } } // se realmente estiver tudo ok if ($tudo_ok === true) { return array(); } else { return $this->errors; } }
/** * Tenta recuperar dinamicamente os campos de identificacao * * Para trabalhar com uma estrutura de arvore, * e necessario que a tabela tenha: * - Uma unica chave primaria * - Uma chave estrangeira (FK) que referencie a chave primaria. * * Nestas condicoes, Lumine consegue identificar quais sao os campos * que compoe a arvore a partir de um dado objeto * * @author Hugo Ferreira da Silva * @param Lumine_Base $pObj * @return array Contendo os campos identificadores */ public static function getTreeFields(Lumine_Base $pObj) { $pFieldID = null; $pFieldParentId = null; // pega as definicoes do objeto $def = $pObj->_getDefinition(); // chave primaria $pk = null; // para cada definicao foreach ($def as $name => $item) { // se for chave primaria if (!empty($item['options']['primary'])) { // armazenamos seus dados $pk = $item; $pk['name'] = $name; continue; } // se for chave estrangeira if (!empty($item['options']['foreign'])) { // se o campo de linkagem for igual a pk e o nome da classe for o nome do objeto if ($item['options']['linkOn'] == $pk['name'] && $item['options']['class'] == $pObj->_getName()) { // encontramos os campos! $pFieldId = $pk['name']; $pFieldParentId = $name; break; } } } // se continuar nulo if (is_null($pFieldId) && is_null($pFieldParentId)) { // dispara excecao new Lumine_Exception('Os campos indicativos de arvore devem ser informados!'); } $data['fieldId'] = $pFieldId; $data['fieldParentId'] = $pFieldParentId; return $data; }
/** * Une uma classe com outra para efetuar uma consulta (inner|left|right) join * * <code> * $car = new Carro; * $pes = new Pessoa; * $car->join($car); * // SELECT pessoa.nome, pessoa.idpessoa, carro.modelo FROM pessoa inner join carro on(carro.idpessoa=pessoa.idpessoa) * </code> * @param Lumine_Base $obj Objeto para uniao * @param string $type Tipo de uniao (LEFT|INNER|RIGHT) * @param string $alias Alias para a tabela de uniao * @param string $linkName Nome especifico do link desta entidade * @param string $linkTo Nome da propriedade que se deseja linkar na outra entidade * @param string $extraCondition Condicao extra para adicionar a clausula ON da uniao * @author Hugo Ferreira da Silva * @link http://www.hufersil.com.br/lumine * @return Lumine_Base O proprio objeto */ public function join(Lumine_Base $obj, $type = 'INNER', $alias = '', $linkName = null, $linkTo = null, $extraCondition = null) { if (!preg_match('@^(INNER|LEFT|CROSS|RIGHT)$@i', $type)) { Lumine_Log::error('Tipo de uniao nao permitida: ' . $type); return $this; } $type = strtoupper($type); // verifica as chaves daqui pra la $name = $obj->_getName(); if (is_null($linkName)) { Lumine_Log::debug('Nome do link nao especificado. Tentando recuperar automaticamente de ' . $name); $opt = $this->_getRelation($name); } else { Lumine_Log::debug('Nome de link especificado: ' . $linkName); $opt = $this->_getField($linkName); } if (!empty($alias)) { Lumine_Log::debug('Alterando o alias de ' . $name . ' para ' . $alias); $obj->_setAlias($alias); } $dest = null; // link de destino if (!empty($linkTo)) { Lumine_Log::debug('Link de destino especificado: ' . $linkTo); $dest = $obj->_getField($linkTo); // pega o link de destino } if (!is_null($extraCondition)) { $args = func_get_args(); if (count($args) > 6) { $args = array_slice($args, 6); } else { $args = null; } $extraCondition = trim($extraCondition); // remove espacos em branco try { $extraCondition = Lumine_Parser::parsePart($obj, $extraCondition, $args); // faz o parser para certificacao que os campos existem certinho $extraCondition = Lumine_Parser::parseEntityNames($obj, $extraCondition); } catch (Exception $e) { try { $extraCondition = Lumine_Parser::parsePart($this, $extraCondition, $args); // faz o parser para certificacao que os campos existem certinho $extraCondition = Lumine_Parser::parseEntityNames($this, $extraCondition); } catch (Exception $e) { Lumine_Log::warning('Houve um erro na analise da condicao extra'); } } if (!preg_match('@^(ON|AND|OR)@i', $extraCondition)) { $extraCondition = " AND " . $extraCondition; // o padrao e AND } else { $extraCondition = " " . $extraCondition; } $extraCondition .= " "; // adiciona um espaco em branco para ficar certinho } $schema = ''; // schema das tabelas $cfg = $this->_getConfiguration(); // pega o objeto de configuracao if ($cfg->getOption('schema_name') != null) { $schema = $cfg->getOption('schema_name') . '.'; // coloca o nome do schema mais um ponto } // se a pessoa especificou um linkTo e linkName e ambos existem if ($opt != null && $dest != null) { Lumine_Log::debug('Ambos links especificados, fazendo uniao...'); // se for uma uniao many-to-many e ambas tabelas forem iguais if ($opt['type'] == self::MANY_TO_MANY && $dest['type'] == self::MANY_TO_MANY && $opt['table'] == $dest['table']) { Lumine_Log::debug('Link do tipo N-N'); $joinString = "%s JOIN %s ON %s.%s = %s.%s " . PHP_EOL; // prepara a string de uniao $joinString .= " %s JOIN %s %s ON %s.%s = %s.%s "; $this_link = $this->_getField($opt['linkOn']); // pega o campo referente a uniao desta entidade $dest_link = $obj->_getField($dest['linkOn']); // pega o campo referente a uniao da entidade que esta sendo unida $joinString = sprintf($joinString, $type, $schema . $opt['table'], $opt['table'], $opt['column'], $this->_getAlias(), $this_link['column'], $type, $schema . $obj->tablename(), $obj->_getAlias(), $obj->_getAlias(), $dest_link['column'], $dest['table'], $dest['column']); $this->_join[] = $joinString . $extraCondition; // coloca a string de uniao na lista } else { Lumine_Log::debug('Link do tipo 1-N'); $this_alias = $this->_getAlias() == '' ? $this->tablename() : $this->_getAlias(); $obj_alias = $obj->_getAlias() == '' ? $obj->tablename() : $obj->_getAlias(); $joinString = "%s JOIN %s %s ON %s.%s = %s.%s"; // inicia a string do join $joinString = sprintf($joinString, $type, $schema . $obj->tablename(), $obj_alias, $this_alias, $opt['column'], $obj_alias, $dest['column']); $this->_join[] = $joinString . $extraCondition; // adiciona a string montada na lista } } else { // mas se nao especificou o linkName e linkTo // achou o relacionamento na outra entidade // significa que la tem a chave que liga aqui ou vice-e-versa if ($opt != null) { Lumine_Log::debug('Join de ' . $obj->_getName() . ' com ' . $this->_getName() . ' do tipo ' . $opt['type'], __FILE__, __LINE__); switch ($opt['type']) { case self::MANY_TO_ONE: $res = $obj->_getField($opt['linkOn']); $this_alias = $this->_getAlias(); if (empty($this_alias)) { $this_alias = $this->tablename(); } $ent_alias = $obj->_getAlias(); $field = $this->_getField($opt['name']); $joinStr = $type . " JOIN " . $schema . $obj->tablename() . " " . $ent_alias . " ON "; if (empty($ent_alias)) { $ent_alias = $obj->tablename(); } $joinStr .= $ent_alias . '.' . $res['column'] . ' = '; $joinStr .= $this_alias . '.' . $field['column']; $this->_join[] = $joinStr . $extraCondition; break; case self::ONE_TO_MANY: $res = $obj->_getField($opt['linkOn']); $this_ref = $this->_getField($res['options']['linkOn']); $obj_alias = $obj->_getAlias(); $this_alias = $this->_getAlias(); if (empty($obj_alias)) { $obj_alias = $obj->tablename(); } if (empty($this_alias)) { $this_alias = $this->tablename(); } $joinStr = $type . " JOIN " . $schema . $obj->tablename() . ' ' . $obj_alias . ' ON '; $joinStr .= sprintf('%s.%s = %s.%s', $obj_alias, $res['column'], $this_alias, $this_ref['column']); $this->_join[] = $joinStr . $extraCondition; break; case self::MANY_TO_MANY: $lnk = $obj->_getRelation($this->_getName()); $this_table = $opt['table']; $obj_table = $lnk['table']; if ($this_table != $obj_table) { throw new Lumine_Exception('As tabelas de relacionamento devem ser iguais em ' . $obj->_getName() . ' e ' . $this->_getName(), Lumine_Exception::ERROR); } $schema = $this->_getConfiguration()->getOption('schema_name'); if (!empty($schema)) { $schema .= '.'; } $this_res = $this->_getField($opt['linkOn']); $obj_res = $obj->_getField($lnk['linkOn']); if (empty($opt['column'])) { $mtm_column = $this_res['column']; } else { $mtm_column = $opt['column']; } if (empty($lnk['column'])) { $mtm_column_2 = $obj_res['column']; } else { $mtm_column_2 = $lnk['column']; } $alias_1 = $this->_getAlias(); $alias_2 = $obj->_getAlias(); if (empty($alias_1)) { $alias_1 = $this->tablename(); } if (empty($alias_2)) { $alias_2 = $obj->tablename(); } $joinStr = sprintf('%s JOIN %s ON %s.%s = %s.%s', $type, $schema . $this_table, $this_table, $mtm_column, $alias_1, $this_res['column']); $this->_join[] = $joinStr; $joinStr = sprintf('%s JOIN %s %s ON %s.%s = %s.%s', $type, $schema . $obj->tablename(), $alias_2, $obj_table, $mtm_column_2, $alias_2, $obj_res['column']); $this->_join[] = $joinStr . $extraCondition; break; default: throw new Lumine_Exception('Tipo de uniao nao encontrada: ' . $opt['type'], Lumine_Exception::ERROR); } } } $list = $obj->_getObjectPart('_join_list'); reset($this->_join_list); foreach ($list as $ent) { $add = true; foreach ($this->_join_list as $this_ent) { if ($ent->_getName() == $this_ent->_getName() && $ent->_getAlias() == $this_ent->_getAlias()) { $add = false; break; } } if (!$add) { continue; } // ok pode adicionar $this->_join_list[] = $ent; $this->_join = array_merge($this->_join, $ent->_getStrJoinList()); $where = $ent->_makeWhereFromFields(); if (!empty($where)) { $this->where($where); } } $this->_join = array_unique($this->_join); return $this; }