Ejemplo n.º 1
0
 /**
  * Returns referenced row.
  * @param  ActiveRow
  * @param  string
  * @param  string|NULL
  * @return ActiveRow|NULL|FALSE NULL if the row does not exist, FALSE if the relationship does not exist
  */
 public function getReferencedTable(ActiveRow $row, $table, $column = NULL)
 {
     if (!$column) {
         $belongsTo = $this->conventions->getBelongsToReference($this->name, $table);
         if (!$belongsTo) {
             return FALSE;
         }
         list($table, $column) = $belongsTo;
     }
     if (!$row->accessColumn($column)) {
         return FALSE;
     }
     $checkPrimaryKey = $row[$column];
     $referenced =& $this->refCache['referenced'][$this->getSpecificCacheKey()]["{$table}.{$column}"];
     $selection =& $referenced['selection'];
     $cacheKeys =& $referenced['cacheKeys'];
     if ($selection === NULL || $checkPrimaryKey !== NULL && !isset($cacheKeys[$checkPrimaryKey])) {
         $this->execute();
         $cacheKeys = [];
         foreach ($this->rows as $row) {
             if ($row[$column] === NULL) {
                 continue;
             }
             $key = $row[$column];
             $cacheKeys[$key] = TRUE;
         }
         if ($cacheKeys) {
             $selection = $this->createSelectionInstance($table);
             //search for foreign key column name which is referenced from activeRow parent table to table from which is selection made
             $foreign = $this->conventions->getForeign($row->getTable()->getName(), $column);
             $primary = $foreign == NULL ? $selection->getPrimary() : $foreign;
             $selection->where($primary, array_keys($cacheKeys));
         } else {
             $selection = NULL;
         }
     }
     return $selection;
     //return isset($selection[$checkPrimaryKey]) ? $selection[$checkPrimaryKey] : NULL;
 }
Ejemplo n.º 2
0
    public function parseJoinsCb(&$joins, $match)
    {
        $chain = $match['chain'];
        if (!empty($chain[0]) && ($chain[0] !== '.' && $chain[0] !== ':')) {
            $chain = '.' . $chain;
            // unified chain format
        }
        preg_match_all('~
			(?(DEFINE)
				(?P<word> [\\w_]*[a-z][\\w_]* )
			)
			(?P<del> [.:])?(?P<key> (?&word))(\\((?P<throughColumn> (?&word))\\))?
		~xi', $chain, $keyMatches, PREG_SET_ORDER);
        $parent = $this->tableName;
        $parentAlias = preg_replace('#^(.*\\.)?(.*)$#', '$2', $this->tableName);
        // join schema keyMatch and table keyMatch to schema.table keyMatch
        if ($this->driver->isSupported(ISupplementalDriver::SUPPORT_SCHEMA) && count($keyMatches) > 1) {
            $tables = $this->getCachedTableList();
            if (!isset($tables[$keyMatches[0]['key']]) && isset($tables[$keyMatches[0]['key'] . '.' . $keyMatches[1]['key']])) {
                $keyMatch = array_shift($keyMatches);
                $keyMatches[0]['key'] = $keyMatch['key'] . '.' . $keyMatches[0]['key'];
                $keyMatches[0]['del'] = $keyMatch['del'];
            }
        }
        // do not make a join when referencing to the current table column - inner conditions
        // check it only when not making backjoin on itself - outer condition
        if ($keyMatches[0]['del'] === '.') {
            if ($parent === $keyMatches[0]['key']) {
                return "{$parent}.{$match['column']}";
            } elseif ($parentAlias === $keyMatches[0]['key']) {
                return "{$parentAlias}.{$match['column']}";
            }
        }
        foreach ($keyMatches as $keyMatch) {
            if ($keyMatch['del'] === ':') {
                if (isset($keyMatch['throughColumn'])) {
                    $table = $keyMatch['key'];
                    $belongsTo = $this->conventions->getBelongsToReference($table, $keyMatch['throughColumn']);
                    if (!$belongsTo) {
                        throw new Nette\InvalidArgumentException("No reference found for \${$parent}->{$keyMatch['key']}.");
                    }
                    list(, $primary) = $belongsTo;
                } else {
                    $hasMany = $this->conventions->getHasManyReference($parent, $keyMatch['key']);
                    if (!$hasMany) {
                        throw new Nette\InvalidArgumentException("No reference found for \${$parent}->related({$keyMatch['key']}).");
                    }
                    list($table, $primary) = $hasMany;
                }
                $column = $this->conventions->getPrimary($parent);
            } else {
                $belongsTo = $this->conventions->getBelongsToReference($parent, $keyMatch['key']);
                if (!$belongsTo) {
                    throw new Nette\InvalidArgumentException("No reference found for \${$parent}->{$keyMatch['key']}.");
                }
                list($table, $column) = $belongsTo;
                $foreign = $this->conventions->getForeign($parent, $column);
                //check for foreign key instead primary key in referenced table
                $primary = $foreign == NULL ? $this->conventions->getPrimary($table) : $foreign;
            }
            $tableAlias = $keyMatch['key'] ?: preg_replace('#^(.*\\.)?(.*)$#', '$2', $table);
            // if we are joining itself (parent table), we must alias joining table
            if ($parent === $table) {
                $tableAlias = $parentAlias . '_ref';
            }
            $joins[$tableAlias . $column] = [$table, $tableAlias, $parentAlias, $column, $primary];
            $parent = $table;
            $parentAlias = $tableAlias;
        }
        return $tableAlias . ".{$match['column']}";
    }