Exemple #1
0
 protected function buildRecord($row)
 {
     $joined = array();
     foreach ($row as $key => $value) {
         if (is_null($value)) {
             unset($row[$key]);
         } else {
             $parts = explode('.', $key, 2);
             if (count($parts) > 1) {
                 if (substr($parts[0], 0, 3) != '___') {
                     if (!isset($joined[$parts[0]])) {
                         $joined[$parts[0]] = array();
                     }
                     //$joined[$parts[0]][$parts[1]] = $value;
                     $this->_recurseRecordKeys($joined[$parts[0]], $parts[1], $value);
                 } else {
                     $this->_recurseRecordKeys($joined, $parts[1], $value);
                 }
                 unset($row[$key]);
             }
         }
     }
     $row = array_merge($row, $joined);
     $record = new Dbi_Record($this->_model, $row);
     $components = $this->_model->components();
     $subqueries = $components->subqueries;
     foreach ($subqueries as $subquery) {
         $cls = $subquery['model'];
         $m = new $cls();
         $tokens = Dbi_Sql_Tokenizer::Tokenize($subquery['statement']);
         // TODO: This token replacement is apparently limited in that it
         // will only work for two levels of subqueries. I say "apparently"
         // because I'm not completely sure how or why it works.
         foreach ($tokens as &$t) {
             $t = str_replace("{$subquery['name']}.", $m->name() . ".", $t);
             $words = explode('.', $t);
             if (count($words) == 2 && $words[0] == $this->_model->name() && $this->_model->name() != $m->name()) {
                 array_shift($words);
                 $t = '?';
                 $subquery['args'][] = $record[$words[0]];
             } else {
                 if (count($words) == 1 && $this->_model->field($words[0])) {
                     $t = '?';
                     $subquery['args'][] = $record[$words[0]];
                 }
             }
         }
         $statement = implode(' ', $tokens);
         $args = array_merge(array($statement), $subquery['args']);
         call_user_func_array(array($m, 'where'), $args);
         $record[$subquery['name']] = $m;
     }
     return $record;
 }
Exemple #2
0
 private function _build(Dbi_Sql_Query_Select $select, Dbi_Model $query, $components, $parent = '', $forceLeft = false)
 {
     $subs = array();
     if (count($components['fields'])) {
         $select->field($components['fields']);
     } else {
         foreach ($query->fields() as $name => $field) {
             if ($parent) {
                 $select->field('`' . substr($parent, 0, -1) . "`.`{$name}` AS `{$parent}{$name}`");
             } else {
                 $select->field("`{$components['table']}`.`{$name}` AS `{$parent}{$name}`");
             }
         }
         foreach ($components['innerJoins'] as $innerJoin) {
             $subquery = $innerJoin['model'];
             $subcomponents = $subquery->components();
             $subcomponents['table'] = $innerJoin['name'];
             $subs[] = array('query' => $subquery, 'components' => $subcomponents, 'forceLeft' => $forceLeft);
         }
         foreach ($components['leftJoins'] as $join) {
             $subquery = $join['model'];
             $subcomponents = $subquery->components();
             $subcomponents['table'] = $join['name'];
             $subs[] = array('query' => $subquery, 'components' => $subcomponents, 'forceLeft' => true);
         }
         foreach ($components['rightJoins'] as $join) {
             $subquery = $join['model'];
             $subcomponents = $subquery->components();
             $subcomponents['table'] = $join['name'];
             $subs[] = array('query' => $subquery, 'components' => $subcomponents, 'forceLeft' => true);
         }
     }
     foreach ($components['calculated'] as $calc) {
         $select->field($calc);
     }
     // Where criteria
     $fields = array_keys($query->fields());
     foreach ($components['where'] as $where) {
         $orStatements = array();
         $orParameters = array();
         foreach ($where->expressions() as $or) {
             $statement = $or->statement();
             $tokens = Dbi_Sql_Tokenizer::Tokenize($statement);
             foreach ($tokens as &$token) {
                 if (in_array($token, $fields)) {
                     $token = "{$parent}{$components['table']}.{$token}";
                 }
             }
             $compiled = implode(' ', $tokens);
             // Functions in MySql cannot have a space before the parenthesis
             $compiled = str_replace(' (', '(', $compiled);
             $orStatements[] = $compiled;
             $orParameters = array_merge($orParameters, $or->parameters());
         }
         $args = array_merge(array(implode(' OR ', $orStatements)), $orParameters);
         call_user_func_array(array($select, 'where'), $args);
     }
     if (!$forceLeft) {
         foreach ($components['innerJoins'] as $join) {
             $args = $join['args'];
             array_unshift($args, $join['model']->prefix() . $join['model']->name() . ' AS `' . $parent . $join['name'] . '`');
             $tokens = Dbi_Sql_Tokenizer::Tokenize($args[1]);
             foreach ($tokens as &$token) {
                 if (in_array($token, $fields)) {
                     $token = '`' . ($parent ? substr($parent, 0, -1) : $components['table']) . "`.`{$token}`";
                 } else {
                     if (substr($token, 0, strlen($join['name']) + 1) == "{$join['name']}.") {
                         $token = "`{$parent}{$join['name']}`.`" . substr($token, strlen($join['name']) + 1) . "`";
                     } else {
                         //echo "token {$token} for " . get_class($join['model']) . "<br/>";
                     }
                 }
             }
             $args[1] = implode(' ', $tokens);
             if ($forceLeft) {
                 call_user_func_array(array($select, 'leftJoin'), $args);
             } else {
                 call_user_func_array(array($select, 'innerJoin'), $args);
             }
         }
     }
     $leftJoins = $components['leftJoins'];
     if ($forceLeft) {
         $leftJoins = array_merge($leftJoins, $components['innerJoins']);
     }
     foreach ($leftJoins as $join) {
         $args = $join['args'];
         array_unshift($args, $join['model']->prefix() . $join['model']->name() . ' AS `' . $parent . $join['name'] . '`');
         $tokens = Dbi_Sql_Tokenizer::Tokenize($args[1]);
         foreach ($tokens as &$token) {
             if (in_array($token, $fields)) {
                 //$token = "`{$components['table']}`.`{$token}`";
                 $token = '`' . ($parent ? substr($parent, 0, -1) : $components['table']) . "`.`{$token}`";
             } else {
                 if (substr($token, 0, strlen($join['name']) + 1) == "{$join['name']}.") {
                     $token = "`{$parent}{$join['name']}`.`" . substr($token, strlen($join['name']) + 1) . "`";
                 }
             }
         }
         $args[1] = implode(' ', $tokens);
         call_user_func_array(array($select, 'leftJoin'), $args);
     }
     foreach ($components['rightJoins'] as $join) {
         $args = $join['args'];
         array_unshift($args, $join['model']->prefix() . $join['model']->name() . ' AS `' . $parent . $join['name'] . '`');
         $tokens = Dbi_Sql_Tokenizer::Tokenize($args[1]);
         foreach ($tokens as &$token) {
             if (in_array($token, $fields)) {
                 //$token = "`{$components['table']}`.`{$token}`";
                 $token = '`' . ($parent ? substr($parent, 0, -1) : $components['table']) . "`.`{$token}`";
             } else {
                 if (substr($token, 0, strlen($join['name']) + 1) == "{$join['name']}.") {
                     $token = "`{$parent}{$join['name']}`.`" . substr($token, strlen($join['name']) + 1) . "`";
                 }
             }
         }
         $args[1] = implode(' ', $tokens);
         call_user_func_array(array($select, 'rightJoin'), $args);
     }
     foreach ($components['groups'] as $group) {
         $select->group($group);
     }
     foreach ($components['having'] as $having) {
         $orStatements = array();
         $orParameters = array();
         foreach ($having->expressions() as $or) {
             $statement = $or->statement();
             $tokens = Dbi_Sql_Tokenizer::Tokenize($statement);
             foreach ($tokens as &$token) {
                 if (in_array($token, $fields)) {
                     $token = "{$parent}{$components['table']}.{$token}";
                 }
             }
             $compiled = implode(' ', $tokens);
             // Functions in MySql cannot have a space before the parenthesis
             $compiled = str_replace(' (', '(', $compiled);
             $orStatements[] = $compiled;
             $orParameters = array_merge($orParameters, $or->parameters());
         }
         $args = array_merge(array(implode(' OR ', $orStatements)), $orParameters);
         call_user_func_array(array($select, 'having'), $args);
     }
     foreach ($subs as $sub) {
         $this->_build($select, $sub['query'], $sub['components'], $parent . ($sub['components']['table'] ? $sub['components']['table'] . '.' : ''), $sub['forceLeft']);
     }
 }
Exemple #3
0
 /**
  * Set an array of data. This function is used internally for actions that
  * are allowed to modify primary keys.
  * @param array $data
  */
 private function _cleanArray(array $data)
 {
     $joinModels = array();
     $components = $this->_model->components();
     foreach ($components['leftJoins'] as $join) {
         if (!empty($join['name'])) {
             $joinModels[$join['name']] = $join['model'];
         }
     }
     foreach ($components['innerJoins'] as $join) {
         if (!empty($join['name'])) {
             $joinModels[$join['name']] = $join['model'];
         }
     }
     foreach ($data as $key => $value) {
         if (isset($joinModels[$key])) {
             $mod = $joinModels[$key];
             $value = new Dbi_Record($mod, $value);
         }
         $this->_data[$key] = $value;
     }
     foreach ($components['subqueries'] as $subquery) {
         $cls = $subquery['model'];
         $m = new $cls();
         $tokens = Dbi_Sql_Tokenizer::Tokenize($subquery['statement']);
         // TODO: This token replacement is apparently limited in that it
         // will only work for two levels of subqueries. I say "apparently"
         // because I'm not completely sure how or why it works.
         foreach ($tokens as &$t) {
             $t = str_replace("{$subquery['name']}.", $m->name() . ".", $t);
             $words = explode('.', $t);
             if (count($words) == 2 && $words[0] == $this->_model->name() && $this->_model->name() != $m->name()) {
                 array_shift($words);
                 $t = '?';
                 $subquery['args'][] = $this->_data[$words[0]];
             } else {
                 if (count($words) == 2 && $words[0] == $m->name()) {
                     //echo $m->name() . '.' . $record[$m->name() . "." . $words[1]] . "\n";
                     //array_shift($words);
                     //$t = '?';
                     //$subquery['args'][] = implode('.', $words); //$record[$words[0]];
                     //$subquery['args'][] = $m->name() . '.' . $record[$words[1]];
                     //$t = $m->name() . '.' . $words[1];
                 } else {
                     if (count($words) == 1 && $this->_model->field($words[0])) {
                         $t = '?';
                         $subquery['args'][] = $this->_data[$words[0]];
                     } else {
                         //echo "Model: " . get_class($this->_model) . "\n";
                     }
                 }
             }
         }
         $statement = implode(' ', $tokens);
         $args = array_merge(array($statement), $subquery['args']);
         call_user_func_array(array($m, 'where'), $args);
         $this->_data[$subquery['name']] = $m;
     }
 }