/** * checa se o objeto possui relacionamentos e remove os objetos relacionados ou restringe. * Se houver relacionamentos no modo RESTRICT (ao menos um), Lumine não irá remover. * Se todos forem CASCADE, Lumine irá remover todos. * Se o relacionamento no mapeameanto for definido de qualquer outra forma a não ser RESTRICT ou CASCADE, * será interpretado como RESTRICT. * @author Hugo Ferreira da Silva * @access public * @param LumineBase $obj Um objeto que extende a classe LumineBase * @return array * @static */ function removeAll(&$obj) { if (is_a($obj, 'luminebase') == false) { LumineLog::logger(2, 'O objeto não extende a classe LumineBase', __FILE__, __LINE__); return false; } LumineLog::logger(1, 'Recuperando relacionamentos de ' . get_class($obj), __FILE__, __LINE__); $fks = $obj->oTable->getForeignKeys(); // var que diz q passa $pass = true; // para cada um encontrado foreach ($fks as $fkname => $prop) { // para as que são OTM if ($prop['type'] == LUMINE_OTM) { // recupera a classe relacionada $o = Util::Import($prop['class']); // pega as fk's da outra classe $fko = $o->oTable->getForeignKeys(); // se for restrict if (isset($fko['ondelete']) && strtolower($fko['ondelete']) != 'cascade') { // pega o valor do relacionamento $v = $obj->{$fko[$prop['linkOn']]['linkOn']}; // se o valor for nulo, passa para a próxima iteração if ($v == '') { continue; } $o->{$prop}['linkOn'] = $v; // se o valor não for nulo, procura por elementos $total = $o->count(); // se encontrar if ($total > 0) { LumineLog::logger(1, 'Objeto relacionado encontrado em ' . $prop['class'] . ': parando remoção', __FILE__, __LINE__); // pára o loop e não deixa remover $pass = false; break; } } } // olhando pelas many-to-many if ($prop['type'] == LUMINE_MTM) { if (!isset($prop['ondelete']) || strtolower($prop['ondelete']) != 'cascade') { // tenta recuperar o link $x = $obj->getLink($fkname); // se estiver vazio if (count($x) == 0) { LumineLog::logger(1, 'Objeto relacionado encontrado em ' . $prop['class'] . ': parando remoção', __FILE__, __LINE__); // passa para a próxima iteração continue; } // diz que não pode remover $pass = false; // pára o loop break; } } } // se passou if ($pass) { // remove todos os objetos relacionados a este reset($fks); foreach ($fks as $fkname => $prop) { if ($prop['type'] == LUMINE_OTM) { LumineLog::logger(1, 'Removendo objetos de ' . $prop['class'], __FILE__, __LINE__); $o = Util::Import($prop['class']); $fko = $o->oTable->getForeignKeys(); $v = $obj->{$fko}[$prop['linkOn']]['linkOn']; if ($v != '') { $o->{$prop}['linkOn'] = $v; $o->delete(); } } if ($prop['type'] == LUMINE_MTM) { LumineLog::logger(1, 'Removendo objetos de ' . $prop['class'], __FILE__, __LINE__); $obj->removeAll($fkname); } } return true; } return false; }
/** * Decriptografa um valor vindo do banco de dados * @param array $prop Array contendo as propriedades do campo * @param string $value O valor a ser decriptografado * @return string Valor decriptografado * @author Hugo Ferreira da Silva */ function _getDecryptValue($prop, $value) { if (isset($prop['crypt']) && $prop['crypt'] == 'true') { LumineLog::Logger(1, 'Decriptografando o campo ' . $prop['name'], __FILE__, __LINE__); $value = Util::decrypt($value, $this); // o valor foi "escapado" antes de inserir/atualizar... tempos que retirar as contra-barras if (isset($this->oTable->config->config['escape']) && $this->oTable->config->config['escape'] == 1) { $value = stripslashes($value); } } return $value; }
function CreateControls($xmlfile) { LumineLog::setLevel(3); LumineLog::setOutput('browser'); $this->conf = new LumineConfiguration($xmlfile); }
/></td> </tr> <tr> <td align="right"> </td> <td><input name="acao" type="submit" id="acao" value="Iniciar" /> <input name="create-classes" type="hidden" id="create-classes" value="1" /> <input name="create-maps" type="hidden" id="create-maps" value="1" /> <input name="escape" type="hidden" id="escape" value="1" /> <input name="empty-as-null" type="hidden" id="empty-as-null" value="1" /></td> </tr> </table> </form> <?php if (@$_POST['acao'] == 'Iniciar') { echo '<div class="result">'; LumineLog::setLevel(4); LumineLog::setOutput(); if ($_POST['use-cache'] != '') { $_POST['use-cache'] = $_POST['class-path'] . '/' . $_POST['use-cache']; } else { unset($_POST['use-cache']); } $obj = new LumineReverse($_POST); $obj->doReverse(); echo '</div>'; } ?> </body> </html>
/** * Get's the entity by tablename or false if no entity with provided name was found * * @param string $table Tablename of desired entity * @access public * @return mixed False on failure, Entity on success */ function getEntityByTable($table) { for ($i = 0, $max = count($this->tables); $i < $max; $i++) { if ($this->tables[$i]->tablename == $table) { LumineLog::logger(1, 'Retornando a entidade para a tabela <b>' . $table . '</b>', __FILE__, __LINE__); return $this->tables[$i]; } } LumineLog::logger(2, 'Não foram encontradas entidades para a tabela ' . $table, __FILE__, __LINE__); return false; }
/** * Import a class from the current class-path and return a new instance of it * * @author Hugo Ferreira da Silva * @return mixed A new instance of class or false on failure * @access public * @param string $class A class to import (like my.package.Classname) */ function Import($class) { $listConf =& $GLOBALS['__LumineConf']; // primeiro, vemos se é uma entidade foreach ($listConf as $conf) { for ($j = 0; $j < count($conf->tables); $j++) { // achamos a entidade relacionada if ($conf->tables[$j]->class == $class) { $file = $conf->config['class-path'] . "/" . str_replace(".", "/", $class) . ".php"; if (file_exists($file)) { require_once $file; $className = array_pop(explode(".", $class)); $x = new $className(); return $x; } else { LumineLog::logger(3, 'O arquivo não existe', __FILE__, __LINE__); return false; } } } } // ok, não é uma entidade, então vamos procurar simplesmente por uma classe dentro de todas as // class-paths definidas e usaremos a primeira que encontrar reset($listConf); foreach ($listConf as $conf) { $file = $conf->config['class-path'] . "/" . str_replace(".", "/", $class) . ".php"; // se existir if (file_exists($file)) { // importa a classe require_once $file; $className = array_pop(explode(".", $class)); $x = new $className(); return $x; } } return false; }
function getColumnProperties($entity, $column) { if (isset($entity['many-to-one']) && is_array($entity['many-to-one'])) { foreach ($entity['many-to-one'] as $mto) { if ($mto['column'] == $column) { LumineLog::logger(1, 'Retornando many-to-one para ' . $column, __FILE__, __LINE__); return $mto; } } } // agora nos campos foreach ($entity['fields'] as $field) { // se for igual if ($field['name'] == $column) { //retorna LumineLog::logger(1, 'Retornando campo para ' . $column, __FILE__, __LINE__); return $field; } } return false; }
/** * Parse the XML file provided in the contructor of class * This entity will be stocked in the LumineConfiguration Object created * @param String $xmlMap XML file that describe this entity * @author Hugo Ferreira da Silva */ function parse($xmlMap, &$conf) { if (!file_exists($xmlMap)) { LumineLog::logger(1, 'Arquivo não existente (' . $xmlMap . ')'); return; } $conf =& new DOMIT_Document(); $conf->resolveErrors(true); if (!$conf->loadXML($xmlMap)) { echo "<pre><strong>Erro no XML de Classe:</strong> " . $conf->getErrorString() . " (" . $conf->getErrorCode() . ")<br>"; echo "Classe: {$xmlMap}</pre>"; exit; } $cfg = $conf->getElementsByPath('/lumine-map'); if ($cfg->getLength() == 0) { LumineLog::logger(1, 'XML incorreto (não foi encontrado o elemento lumine-map)'); return; } if (!$cfg->arNodeList[0]->hasAttribute('table')) { LumineLog::logger(1, 'nome da tabela não informado'); return; } if (!$cfg->arNodeList[0]->hasAttribute('class')) { LumineLog::logger(1, 'Classe não informada)'); return; } $this->tablename = $cfg->arNodeList[0]->getAttribute('table'); $this->class = $cfg->arNodeList[0]->getAttribute('class'); $this->extends = $cfg->arNodeList[0]->getAttribute('extends'); // pega o campo de ID $idNode =& $conf->getElementsByPath('/lumine-map/id', 1); if ($idNode != null) { $id = array(); if (!$idNode->hasAttribute('name')) { LumineLog::logger(1, 'Você deve informar o attributo name'); return; } if (!$idNode->hasAttribute('column')) { $id['column'] = $idNode->getAttribute('name'); } else { $id['column'] = $idNode->getAttribute('column'); } $this->sequence_key = $idNode->getAttribute("name"); $gen =& $conf->getElementsByPath('/lumine-map/id/generator'); if ($gen->getLength() > 0) { $gen = $gen->item(0); $this->sequence_generator = $gen->getAttribute('class'); $this->sequence_generator_method = $gen->getAttribute('method'); } else { $this->sequence_generator = 'default'; } // verifica se linka com algum campo caso esteja extendendo uma classe if ($idNode->hasAttribute("linkOn")) { $id['linkOn'] = $idNode->getAttribute("linkOn"); } //if($idNode->getAttribute('primary-key') == 'true') { $this->primary_keys[] = $idNode->getAttribute('name'); //} $id['primary_key'] = true; $this->columns[$idNode->getAttribute('name')] = $id; } // pega os campos normais $columns =& $conf->getElementsByPath('/lumine-map/property'); if ($columns->getLength() > 0) { $total = $columns->getLength(); for ($i = 0; $i < $total; $i++) { $node = $columns->item($i); if ($node->hasAttribute('name') == false) { LumineLog::logger(1, 'Você deve informar o attributo name para (tabela ' . $this->tablename . ')'); break; } if ($node->hasAttribute('type') == false) { LumineLog::logger(1, 'Você deve informar o attributo type para (tabela ' . $this->tablename . ', campo ' . $node->getAttribute('name') . ')'); break; } $fName = $node->getAttribute('name'); while (list($att, $value) = each($node->attributes->arNodeMap)) { if ($att != 'name') { $this->columns[$fName][$att] = $value->nodeValue; } if ($att == 'primary-key' && $value->nodeValue == 'true') { $this->columns[$fName]['primary_key'] = true; $this->primary_keys[] = $fName; } } if (($c = $node->getAttribute('column')) != '') { $this->columns[$fName]['column'] = $c; } else { $this->columns[$fName]['column'] = $node->getAttribute('name'); } } } // relacionamentos one-to-many $otm = $conf->getElementsByPath('/lumine-map/many-to-one'); for ($i = 0, $max = $otm->getLength(); $i < $max; $i++) { $fk = $otm->arNodeList[$i]->getAttribute('name'); $this->foreign_keys[$fk]['type'] = 'many-to-one'; $this->foreign_keys[$fk]['class'] = $otm->arNodeList[$i]->childNodes[0]->getAttribute('name'); $this->foreign_keys[$fk]['column'] = $otm->arNodeList[$i]->childNodes[0]->getAttribute('column'); $this->foreign_keys[$fk]['ondelete'] = $otm->arNodeList[$i]->childNodes[0]->getAttribute('ondelete'); $this->foreign_keys[$fk]['onupdate'] = $otm->arNodeList[$i]->childNodes[0]->getAttribute('onupdate'); $this->foreign_keys[$fk]['linkOn'] = $otm->arNodeList[$i]->childNodes[0]->getAttribute('linkOn'); $this->foreign_keys[$fk]['lazy'] = $otm->arNodeList[$i]->getAttribute('lazy'); $this->foreign_keys[$fk]['foreign'] = true; $this->foreign_keys[$fk]['name'] = $fk; if ($otm->arNodeList[$i]->getAttribute('primary-key') == 'true') { $this->primary_keys[] = $fk; } $this->columns[$fk] =& $this->foreign_keys[$fk]; } // relacionamentos many-to-one $mto = $conf->getElementsByPath('/lumine-map/one-to-many'); for ($i = 0, $max = $mto->getLength(); $i < $max; $i++) { $fk = $mto->arNodeList[$i]->getAttribute('name'); $this->foreign_keys[$fk]['name'] = $fk; $this->foreign_keys[$fk]['type'] = 'one-to-many'; $this->foreign_keys[$fk]['class'] = $mto->arNodeList[$i]->childNodes[0]->getAttribute('name'); $this->foreign_keys[$fk]['column'] = $mto->arNodeList[$i]->childNodes[0]->getAttribute('column'); $this->foreign_keys[$fk]['linkOn'] = $mto->arNodeList[$i]->childNodes[0]->getAttribute('linkOn'); $this->foreign_keys[$fk]['lazy'] = $mto->arNodeList[$i]->getAttribute('lazy'); $this->foreign_keys[$fk]['foreign'] = true; $this->columns[$fk] =& $this->foreign_keys[$fk]; } // relacionamentos many-to-many $mtm = $conf->getElementsByPath('/lumine-map/many-to-many'); for ($i = 0, $max = $mtm->getLength(); $i < $max; $i++) { $node = $mtm->item($i); $fk = $node->getAttribute('name'); $this->foreign_keys[$fk]['name'] = $fk; $this->foreign_keys[$fk]['type'] = 'many-to-many'; $this->foreign_keys[$fk]['linkOn'] = $node->firstChild->hasAttribute('linkOn') ? $node->firstChild->getAttribute('linkOn') : $node->getAttribute('name'); $this->foreign_keys[$fk]['table'] = $node->getAttribute('table'); $this->foreign_keys[$fk]['foreign'] = true; $this->foreign_keys[$fk]['class'] = $node->firstChild->getAttribute('name'); $this->foreign_keys[$fk]['lazy'] = $node->getAttribute('lazy'); //$this->columns[$fk] = &$this->foreign_keys[$fk]; } }
/** * Sets the log level * * @param number $level The level o log * @param mixed $output Where to put the output * @author Hugo Ferreira da Silva * @access public */ function setLevel($level, $output = false) { $GLOBALS['__LumineLog']['log-level'] = $level; if ($output !== false) { LumineLog::setOutput($output); } }
/** * Create the database tables * <code> * require_once 'pah_to_lumine/LumineSchema.php'; * $schema = new LumineSchema('your-conf-file.xml'); * $schema->createSchema(); * </code> * @author Hugo Ferreira da Silva * @access public * @return boolean True on success */ function createSchema() { LumineLog::logger(1, 'Criando nova instancia do XML DOMIT', __FILE__, __LINE__); $doc =& new DOMIT_Document(); $doc->resolveErrors(true); if (!$doc->loadXML($this->xml)) { LumineLog::logger(3, 'Arquivo de configuração com erros: ' . $doc->getErrorString(), __FILE__, __LINE__); $this->dienice("Erro no XML: " . $doc->getErrorString()); } // item de configração LumineLog::logger(1, 'Verificando o bloco de configuração', __FILE__, __LINE__); $item =& $doc->getElementsByPath("/lumine-configuration/configuration", 1); if (!$item) { LumineLog::logger(3, 'Bloco de configuração não encontrado', __FILE__, __LINE__); $this->dienice("Elemento de configuração (<strong>configuration</strong>) não encontrado!"); } // pega as configurações LumineLog::logger(1, 'Analisando itens da configuração', __FILE__, __LINE__); $config = array(); for ($i = 0; $i < count($item->childNodes); $i++) { if ($item->childNodes[$i]->nodeType == 1) { $key = $item->childNodes[$i]->nodeName; $config[$key] = $item->childNodes[$i]->firstChild->nodeValue; } } // mapeamentos LumineLog::logger(1, 'Analisando mapeamentos', __FILE__, __LINE__); $maplist =& $doc->getElementsByPath("/lumine-configuration/mapping", 1); if (!$maplist) { LumineLog::logger(3, 'Bloco de mapeamentos não encontrado', __FILE__, __LINE__); $this->dienice("Bloco de mapemaento de entidades não encontrado"); } // checa os itens do mapeamento LumineLog::logger(1, 'Solicitando itens dos mapeamentos', __FILE__, __LINE__); $maps =& $maplist->getElementsByPath("item"); if ($maps->getLength() == 0) { LumineLog::logger(3, 'Não há mapeamentos para serem criados no banco', __FILE__, __LINE__); $this->dienice("Não há mapeamentos dentro da lista de mapas"); } // checa se os arquivos informados existem LumineLog::logger(1, 'Checando existencia de itens', __FILE__, __LINE__); $files = array(); for ($i = 0; $i < $maps->getLength(); $i++) { $it =& $maps->item($i); $file = $config['class-path'] . "/" . str_replace(".", "/", $it->getAttribute("src")) . ".xml"; if (!file_exists($file)) { LumineLog::logger(3, 'Arquivo de mapeamento ' . $file . ' não existe!', __FILE__, __LINE__); $this->dienice("O arquivo de confiração do mapeamento <strong>{$file}</strong> não existe"); } // checa o xml do mapeamento para ver se não há erros LumineLog::logger(1, 'Checando mapeamento: ' . $file, __FILE__, __LINE__); $xmlMap =& new DOMIT_Document(); $xmlMap->resolveErrors(true); if (!$xmlMap->loadXML($file)) { LumineLog::logger(3, 'Arquivo de configuração ' . $file . ' com erros: ' . $xmlMap->getErrorString(), __FILE__, __LINE__); $this->dienice("Erro no arquivo de configuração <strong>{$file}</strong>: " . $xmlMap->getErrorString()); } // carrega o xml de cada um e coloca numa matriz $files[$file] =& $xmlMap; } // recupera os tipo require_once LUMINE_INCLUDE_PATH . '/LumineTypes.php'; LumineTypes::start($config['dialect']); // checa se o dialeto não foi informado if ($config['dialect'] == '') { LumineLog::logger(3, 'Dialeto não informado para conexão com o banco', __FILE__, __LINE__); $this->dienice("Dialeto não informado"); } // checa se o dialeto existe LumineLog::logger(1, 'Incluindo arquivo de conexão com o banco: ' . $config['dialect'] . '.php', __FILE__, __LINE__); // importa a classe ADODB include_once LUMINE_INCLUDE_PATH . '/adodb/adodb.inc.php'; // se não conseguir criar a instância do banco if (!($conn =& ADONewConnection($config['dialect']))) { LumineLog::logger(3, 'Classe de conexão <i>' . $config['dialect'] . '</i> não encontrada!', __FILE__, __LINE__); exit; } $this->cn =& $conn; $this->cn->SetFetchMode(ADODB_FETCH_ASSOC); if (!defined('LUMINE_RANDOM_FUNC')) { define('LUMINE_RANDOM_FUNC', $this->cn->random); } $ifschema = ''; // verifica se foi informado o schema if (isset($config['schema']) && $config['schema'] != '') { // então cria o schema no banco $this->cn->query("CREATE SCHEMA " . $config['schema']); $ifschema = $config['schema'] . '.'; } else { if (isset($config['schema-authorization']) && $config['schema-authorization'] != '') { // verifica se foi informado o schema-authorization // então cria o schema no banco $this->cn->query("CREATE SCHEMA AUTHORIZATION " . $config['schema-authorization']); $ifschema = $config['schema-authorization'] . '.'; } } // se o schema foi informado, mudamos para ele if ($ifschema != '') { $this->cn->query("SET search_path TO " . substr($ifschema, 0, strlen($ifschema) - 1)); } // inicia a escrita das tabelas $td =& $this->classes; foreach ($files as $file => $entity) { $first =& $entity->getElementsByPath("/lumine-map", 1); if (!$first) { $this->dienice("Elemento de definição incorreto para <strong>{$file}</strong>"); } // table definition $table = $first->getAttribute("table"); $td[$table]['class'] = $first->getAttribute("class"); $td[$table]['tablename'] = $table; $td[$table]['extends'] = $first->getAttribute("extends"); $id =& $first->getElementsByPath("id", 1); if ($id) { if ($id->getAttribute("name") == '') { $this->dienice("O atributo <strong>name</strong> deve ser informado na definição da chave de sequencia do arquivo <strong>{$file}</strong>"); } $generator =& $id->getElementsByPath("generator", 1); $column = @$id->getAttribute("column") == '' ? $id->getAttribute("name") : $id->getAttribute('column'); $name = $id->getAttribute("name"); //********************************************************** //** classes extendidas //********************************************************** if (!$generator && $id->hasAttribute("linkOn")) { $td[$table]['primary-keys'][] = $column; $fk =& $this->_getDefinitionByClass($td[$table]['extends']); $fd =& $this->_getFieldDefinition($fk, $id->getAttribute('linkOn')); $td[$table]['foreign-keys'][$name]['linkOn'] = $fd['column']; $td[$table]['foreign-keys'][$name]['references'] = $fk['tablename']; $td[$table]['foreign-keys'][$name]['ondelete'] = 'cascade'; $td[$table]['foreign-keys'][$name]['onupdate'] = 'cascade'; $td[$table]['foreign-keys'][$name]['not-null'] = true; } else { if ($generator) { $td[$table]['sequence-key']['column'] = $column; $td[$table]['sequence-key']['name'] = $id->getAttribute('name'); $td[$table]['sequence-key']['generator'] = $generator->getAttribute("class"); $td[$table]['primary-keys'][] = $column; } else { LumineLog::logger(3, "Erro de definição de {$file}", __FILE__, __LINE__); $this->dienice("não foi informado se a classe extende outra ou ao menos o gerador de sequencia desta classe"); } } } // propriedades $prop =& $first->getElementsByPath("property"); for ($i = 0; $i < $prop->getLength(); $i++) { $node =& $prop->item($i); $name = $node->getAttribute("name"); $type = $node->getAttribute("type"); $notnull = $node->getAttribute("not-null") == 'true' ? true : false; $primary = $node->getAttribute("primary-key") == 'true' ? true : false; $default = $node->getAttribute("default"); $column = $node->getAttribute("column") == '' ? $name : $node->getAttribute("column"); if ($name == '') { $this->dienice("O atributo <strong>name</strong> deve ser informado no elemento {$i} do arquivo <strong>{$file}</strong>"); } if ($type == '') { $this->dienice("Você deve informa o tipo da coluna"); } $td[$table]['columns'][$name]['column'] = $column; $td[$table]['columns'][$name]['type'] = $type; if ($default != '') { $td[$table]['columns'][$name]['default'] = $default; } if ($notnull == true) { $td[$table]['columns'][$name]['not-null'] = true; } if ($primary == true) { $td[$table]['primary-keys'][] = $column; } } } // reinicia a matriz, para procurarmos por chaves estrangeiras reset($files); // many-to-many relationships $many_to_many = array(); $chaves = array_keys($files); foreach ($files as $file => $entity) { // procura many-to-one $first =& $entity->getElementsByPath("/lumine-map", 1); $table = $first->getAttribute("table"); // chaves many-to-one $mto =& $first->getElementsByPath("many-to-one"); for ($i = 0; $i < $mto->getLength(); $i++) { $node =& $mto->item($i); $class =& $node->getElementsByPath("class", 1); //echo "$file: " . $class->getAttribute("name") . "<br>"; if (!$class) { $this->dienice("A classe para a chave estrangeira <strong>{$name}</strong> não foi informada no arquivo <strong>{$file}</strong>"); } $fk = $this->_getDefinitionByClass($class->getAttribute("name")); $name = $node->getAttribute("name"); $reftable = $fk['tablename']; $linkOn = $class->getAttribute("linkOn"); $column = $class->getAttribute("column"); $ondelete = $class->getAttribute("ondelete"); $onupdate = $class->getAttribute("onupdate"); $notnull = $class->getAttribute("not-null") == 'true'; //echo "$table, $name, $reftable, $linkOn, $column, $ondelete, $onupdate, $notnull<br>"; if ($node->getAttribute("primary-key") == 'true') { $td[$table]['primary-keys'][] = $column; } $td[$table]['foreign-keys'][$name]['column'] = $column; if ($linkOn == $fk['sequence-key']['column'] || $linkOn == $fk['sequence-key']['name']) { $td[$table]['foreign-keys'][$name]['type'] = SEQUENCE_TYPE; $linkOn = $fk['sequence-key']['column']; } else { $td[$table]['foreign-keys'][$name]['type'] = $fd['type']; $linkOn = $fd['column']; } $td[$table]['foreign-keys'][$name]['linkOn'] = $linkOn; $td[$table]['foreign-keys'][$name]['references'] = $reftable; $td[$table]['foreign-keys'][$name]['ondelete'] = $ondelete; $td[$table]['foreign-keys'][$name]['onupdate'] = $onupdate; $td[$table]['foreign-keys'][$name]['not-null'] = $notnull; } // procurando por chaves many-to-many $mtm = $first->getElementsByPath("many-to-many"); for ($i = 0; $i < $mtm->getLength(); $i++) { $node =& $mtm->item($i); $class = $node->getElementsByPath("class", 1); if (!$class) { $this->dienice("O elemento <strong>class</strong> necessário para chaves many-to-many não foi encontrado no arquivo <strong>{$file}</strong>"); } $name = $node->getAttribute("name"); $classname = $class->getAttribute("name"); $linkOn = $class->getAttribute("linkOn"); $reftable = $node->getAttribute("table"); if ($name == '') { $this->dienice("O atributo <strong>name</strong> para criação da chave many-to-many no arquivo <strong>{$file}</strong> deve ser informado"); } if ($classname == '') { $this->dienice("O atributo <strong>class.name</strong> para criação da chave many-to-many no arquivo <strong>{$file}</strong> deve ser informado"); } if ($linkOn == '') { $this->dienice("O atributo <strong>class.linkOn</strong> para criação da chave many-to-many no arquivo <strong>{$file}</strong> deve ser informado"); } if ($reftable == '') { $this->dienice("O atributo <strong>class.table</strong> para criação da chave many-to-many no arquivo <strong>{$file}</strong> deve ser informado"); } $fk = $this->_getDefinitionByClass($classname); $c = array(); $c['column'] = $fk['sequence-key']['column'] || $column == $fk['sequence-key']['name'] ? $fk['sequence-key']['column'] : $linkOn; // if($linkOn == $fk['sequence-key']['column'] || $linkOn == $fk['sequence-key']['name']) { $c['type'] = SEQUENCE_TYPE; // } else { //$c['type'] = $fk['columns'][$column]['type']; // } $c['references'] = $fk['tablename']; $c['ondelete'] = $class->getAttribute("ondelete"); $c['onupdate'] = $class->getAttribute("onupdate"); $many_to_many[$reftable][] = $c; } } // agora começaremos a criar as tabelas $tables = array(); $alters = array(); foreach ($this->classes as $name => $def) { $sql = "CREATE TABLE {$ifschema}{$name} ("; // sequence key if (isset($def['sequence-key']) && $def['sequence-key']) { $sql .= $def['sequence-key']['column'] . ' ' . SEQUENCE_DEFINITION . ', '; } // foreign keys if (isset($def['foreign-keys']) && is_array($def['foreign-keys'])) { foreach ($def['foreign-keys'] as $fkname => $fkp) { if (isset($fkp['column'])) { $sql .= $fkp['column'] . ' ' . $fkp['type']; } else { if (isset($fkp['linkOn']) && isset($def['primary-keys']) && in_array($fkname, $def['primary-keys'])) { $class_tmp = $this->classes[$fkp['references']]; $fk_tmp = $this->_getFieldDefinition($class_tmp, $fkp['linkOn']); $sql .= $fkname . ' ' . SEQUENCE_TYPE; } } if (isset($fkp['not-null']) && $fkp['not-null']) { $sql .= ' not null'; } $sql .= ', '; } } // campos if (is_array($def['columns'])) { foreach ($def['columns'] as $cname => $cdef) { $sql .= $cdef['column'] . ' ' . $cdef['type']; if (isset($cdef['not-null']) && $cdef['not-null'] == true) { $sql .= ' not null'; } $sql .= ', '; } } // colocando os INDEX para chaves estrangeiras if (isset($def['foreign-keys']) && is_array($def['foreign-keys'])) { reset($def['foreign-keys']); foreach ($def['foreign-keys'] as $fname => $fkp) { if (CREATE_INDEX_FOR_FK) { $sql .= "INDEX `FK_" . strtoupper(substr(md5(rand(0, time())), 0, 10)) . "`({$fkp['column']})"; $sql .= ', '; } $c = strtoupper(substr(md5(rand(0, time())), 0, 15)); if (!isset($fkp['column'])) { $fkp['column'] = $fname; } $alter = "ALTER TABLE {$ifschema}{$name} ADD FOREIGN KEY({$fkp['column']}) REFERENCES {$ifschema}{$fkp['references']}({$fkp['linkOn']})"; if ($fkp['ondelete'] != '') { $alter .= " ON DELETE {$fkp['ondelete']}"; } if ($fkp['onupdate'] != '') { $alter .= " ON UPDATE {$fkp['onupdate']}"; } $alters[] = $alter; } } // colocando as primary keys if (isset($def['primary-keys']) && is_array($def['primary-keys'])) { $sql .= "PRIMARY KEY("; foreach ($def['primary-keys'] as $pname) { $sql .= $pname . ", "; } $sql = substr($sql, 0, strlen($sql) - 2); $sql .= ")"; } if (substr($sql, strlen($sql) - 2) == ', ') { $sql = substr($sql, 0, strlen($sql) - 2); } $sql .= ") " . TABLE_DEFINITION; $tables[$name] = $sql; } // agora, as many-to-many foreach ($many_to_many as $name => $def) { $sql = "CREATE TABLE {$ifschema}{$name} ("; foreach ($def as $d) { $sql .= $d['column'] . ' ' . $d['type'] . ' not null, '; } $sql .= "PRIMARY KEY("; reset($def); foreach ($def as $d) { $sql .= $d['column'] . ', '; } $sql = substr($sql, 0, strlen($sql) - 2); $sql .= "), "; reset($def); foreach ($def as $d) { $x = strtoupper(substr(md5(rand(0, time())), 0, 15)); if (CREATE_INDEX_FOR_FK) { $sql .= "INDEX ({$d['column']}), "; } $alter = "ALTER TABLE " . $ifschema . $name . " ADD FOREIGN KEY({$d['column']}) REFERENCES {$ifschema}{$d['references']}({$d['column']})"; if ($d['ondelete'] != '') { $alter .= " ON DELETE {$d['ondelete']}"; } if ($d['onupdate'] != '') { $alter .= " ON UPDATE {$d['onupdate']}"; } $alters[] = $alter; } $sql = substr($sql, 0, strlen($sql) - 2); $sql .= ") " . TABLE_DEFINITION; $tables[$name] = $sql; } // agora, cria no banco de dados /////// PARA MYSQL (POR ENQUANTO) $this->cn->connect($config['host'], $config['user'], $config['password'], $config['database']); $fkc = LumineTypes::disableForeignKeys($config['dialect']); if ($fkc != '') { $this->cn->query($fck); } $TablesInDatabase = $this->cn->MetaTables(); foreach ($tables as $name => $sql) { if (in_array($name, $TablesInDatabase)) { LumineLog::logger(1, 'Dropando tabela existente: ' . $ifschema . $name, __FILE__, __LINE__); $this->cn->query("DROP TABLE " . $name); } LumineLog::logger(1, 'Executando SQL: ' . $sql, __FILE__, __LINE__); $this->cn->query($sql); } foreach ($alters as $sql) { LumineLog::logger(1, 'Executando SQL: ' . $sql, __FILE__, __LINE__); $this->cn->query($sql); } // se optou por criar as classes if ($config['create-classes'] == 1) { LumineLog::logger(1, 'Chamando rotina de criação das classes', __FILE__, __LINE__); $this->_createClasses($maps, $config); } // terminado return true; }
/** * Validate a given class * A static method to validate your classes<br> * <code> * require_once 'path_to_lumine_package/LumineValidation.php'; * $person = new Person; * $results = LumineValidation::validate($person); * if($results === true) { * $person->save(); * } else { * print_r( $results ); * } * </code> * or * <code> * require_once 'path_to_lumine_package/LumineValidation.php'; * $person = new Person; * $results = $person->validate(); * </code> * @return mixed True on sucess, false if $class is not a LumineBase object and associative array of field with errors * @author Hugo Ferreira da Silva * @access public * @param object $class A class that extends LumineBase */ function validate(&$class) { // não é da classe LumineBase if (!is_a($class, "luminebase")) { return false; } //pega os campos da classe $table = $class->table(); $table = array_merge($table, $class->oTable->getForeignKeys()); // procura pelo arquivo de validaçao classname-validation.xml dentro do diretorio de mapeamentos $maps = $class->oTable->config->config['maps']; $maps = str_replace(".", "/", $maps); $xml = $class->oTable->config->config['class-path'] . '/' . $maps; $xml .= '/' . array_pop(explode(".", $class->oTable->class)) . '-validation.xml'; // erros $errors = array(); // se encontrou o arquivo, iremos fazer a validaçao pelo arquivo if (file_exists($xml)) { LumineLog::logger(1, "XML encontrado: " . $xml, __FILE__, __LINE__); // criamos uma nova instancia do DOMIT_Document $val =& new DOMIT_Document(); $val->resolveErrors(true); if (!$val->loadXML($xml)) { // erro no XML LumineLog::logger(1, "XML com erro: " . $val->getErrorString(), __FILE__, __LINE__); return false; } // pega o primeiro nó $first = $val->getElementsByPath("/lumine-validator", 1); if ($first) { $filename = $first->getAttribute("messages_file"); $fileparts = explode('.', $filename); $ext = array_pop($fileparts); $file = implode('/', $fileparts) . '.' . $ext; $file = $class->oTable->config->config['class-path'] . '/' . $file; if (file_exists($file) && is_file($file)) { Messages::parseFile($file); } } // Pega os validator $validator_list = $val->getElementsByPath("/lumine-validator/field"); // para cada validator for ($i = 0; $i < $validator_list->getLength(); $i++) { $node = $validator_list->item($i); $itens = $node->getElementsByPath("validator"); // pega o nome do campo a ser validado $key = $node->getAttribute("name"); // se não encontrar if ($key == '') { LumineLog::logger(1, "Informe o nome do campo para validação no arquivo <b>{$xml}</b>"); return false; } // se o campo no validator não existe na entidade if (!array_key_exists($key, $table)) { continue; } // pega o valor na entidade $value = $class->{$key}; // para cada validator encontrado para este campo for ($j = 0; $j < $itens->getLength(); $j++) { $vnode = $itens->item($j); $type = $vnode->getAttribute("type"); $msg_key = Messages::getMessage($vnode->getAttribute("msg-key")); $msg = $msg_key == false ? $vnode->getAttribute("msg") : $msg_key; $rule = $vnode->getAttribute("rule"); $cname = $vnode->getAttribute("name"); $cmethod = $vnode->getAttribute("method"); $minlength = $vnode->getAttribute("minlength"); $maxlength = $vnode->getAttribute("maxlength"); $minvalue = $vnode->getAttribute("minvalue"); $maxvalue = $vnode->getAttribute("maxvalue"); // faz um switch no tipo switch ($type) { case "requiredString": if (!array_key_exists($key, $errors) || $errors[$key] === true) { if ($class->{$key} == '') { $errors[$key] = $msg; continue; } if ($minlength != '' && strlen($class->{$key}) < $minlength) { $errors[$key] = $msg; continue; } if ($maxlength != '' && strlen($class->{$key}) > $maxlength) { $errors[$key] = $msg; continue; } $errors[$key] = true; } break; case "requiredNumber": if (!array_key_exists($key, $errors) || $errors[$key] === true) { if (!is_numeric($class->{$key})) { $errors[$key] = $msg; continue; } if ($minvalue != '' && $class->{$key} < $minvalue) { $errors[$key] = $msg; continue; } if ($maxvalue != '' && $class->{$key} > $maxvalue) { $errors[$key] = $msg; continue; } $errors[$key] = true; } break; case 'unique': if (!array_key_exists($key, $errors) || $errors[$key] === true) { $testClass = Util::Import($class->oTable->class); // se não encontrou a classe if ($testClass === false) { $erros[$key] = $msg; continue; } // se já existir um registro com este valor $testClass->{$key} = $class->{$key}; if ($testClass->find() > 0) { // pega as chaves primárias $pks = $testClass->oTable->getPrimaryKeys(); $todos = true; while ($testClass->fetch()) { // para cada pk foreach ($pks as $p => $prop) { // se ao menos UMA chave primária for diferente if ($testClass->{$p} != $class->{$p}) { // não passou na validação $todos = false; break; } } if ($todos == false) { break; } } // se houver uma chave diferente if ($todos == false) { // não passou $errors[$key] = $msg; continue; } } $errors[$key] = true; } break; case "rule": if (!array_key_exists($key, $errors) || $errors[$key] === true) { if ($rule != '') { // coloca os valores para a regra $regra = preg_replace("/#(.*?)#/e", "\$class->\\1", $rule); // executa o código $x = eval('if(' . $regra . ') return true;'); // se for falso, significa que não passou no teste if (!$x) { $errors[$key] = $msg; continue; } else { $errors[$key] = true; continue; } } else { $errors[$key] = '-- You must provide a rule to validate this field (' . $key . ')'; } } break; case "class": if (!array_key_exists($key, $errors) || $errors[$key] === true) { if ($cname != '') { $classname = array_pop(explode(".", $cname)); if (!class_exists($classname)) { Util::Import($cname); } $x = new $classname(); if (method_exists($x, $cmethod)) { $r = $x->{$cmethod}($class->{$key}); if ($r === true) { $errors[$key] = true; continue; } else { $errors[$key] = $msg; continue; } } else { $errors[$key] = '-- You must provida a valid method for class ' . $classname . ' to validate the field ' . $key; continue; } } else { $errors[$key] = '-- You must provide a class to validate this field(' . $key . ')'; continue; } } break; case "requiredEmail": if (!array_key_exists($key, $errors) || $errors[$key] === true) { if (Util::validateEmail($class->{$key})) { $errors[$key] = true; continue; } else { $errors[$key] = $msg; continue; } } break; case 'requiredDate': if (!array_key_exists($key, $errors) || $errors[$key] === true) { $reg = array(); if (preg_match('@^([0-9]{2})/([0-9]{2})/([0-9]{4})$@', $class->{$key}, $reg)) { if (checkdate($reg[2], $reg[1], $reg[3]) || checkdate($reg[1], $reg[2], $reg[3])) { $errors[$key] = true; continue; } else { $errors[$key] = $msg; continue; } } else { $errors[$key] = $msg; continue; } } break; case 'requiredISODate': if (!array_key_exists($key, $errors) || $errors[$key] === true) { $reg = array(); if (preg_match('@^([0-9]{4})-([0-9]{2})-([0-9]{2})$@', $class->{$key}, $reg)) { if (checkdate($reg[2], $reg[3], $reg[1])) { $errors[$key] = true; continue; } else { $errors[$key] = $msg; continue; } } else { $errors[$key] = $msg; continue; } } break; } } } // checa validações na classse foreach ($table as $key => $prop) { $m = "validate" . ucfirst($key); if (method_exists($class, $m)) { $x = $class->{$m}(); if ($x !== true) { if (is_bool($x)) { $errors[$key] = Messages::getMessage($class->tablename() . "." . $key); } else { $errors[$key] = $x; } } else { $errors[$key] = true; } } } foreach ($errors as $key => $msg) { if ($msg !== true) { $_REQUEST[$key . '_error'] = $msg; } } reset($errors); // terminou a validação dessa classe, porém verificamos se ela é uma classe extendida if (isset($class->oTable->extends) && $class->oTable->extends != '') { $x = Util::Import($class->oTable->extends); if ($x !== false) { $x->setFrom($class->toArray()); $r = $x->validate(); if ($r !== true) { $errors = array_merge($errors, $r); } } } foreach ($errors as $key => $msg) { if (isset($errors[$key]) && $errors[$key] !== true) { return $errors; } } return true; } LumineLog::logger(1, "XML não encontrado: " . $xml, __FILE__, __LINE__); /* somente entrará nesta parte se não encontrar o arquivo de validação */ // para cada campo (não sendo chaves many-to-many e one-to-many) $errors = array(); foreach ($table as $field => $prop) { if (isset($prop['not-null']) && $prop['not-null'] == 'true' && $field != $class->oTable->sequence_key) { if (!isset($class->{$field}) || $class->{$field} == '') { $errors[$field] = false; } } else { $errors[$field] = true; } /* if(isset($prop['foreign'])) { if($prop['foreign'] == false || ($prop['foreign'] && $prop['type'] == 'many-to-one')) { } } */ } foreach ($errors as $key => $value) { if ($value === false) { reset($errors); return $errors; } } return true; }