Ejemplo n.º 1
0
 /**
  * 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;
 }