Skip to content

Commit

Permalink
Merge pull request propelorm#919 from SCIF/master
Browse files Browse the repository at this point in the history
Some improvements of DelegateBehavior
  • Loading branch information
marcj committed May 1, 2015
2 parents 8b32cd2 + 06914b7 commit 350e3c4
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 0 deletions.
150 changes: 150 additions & 0 deletions src/Propel/Generator/Behavior/Delegate/DelegateBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@

namespace Propel\Generator\Behavior\Delegate;

use Propel\Generator\Builder\Om\QueryBuilder;
use Propel\Generator\Model\Behavior;
use Propel\Generator\Model\Column;
use Propel\Generator\Model\ForeignKey;
use Propel\Generator\Util\PhpParser;
use Propel\Runtime\Exception\PropelException;

/**
* Gives a model class the ability to delegate methods to a relationship.
Expand Down Expand Up @@ -136,4 +140,150 @@ public function objectCall($builder)

return $script;
}

public function objectFilter(&$script)
{
$p = new PhpParser($script, true);
$text = $p->findMethod('toArray', true);
$matches = [];
preg_match('/(\$result = array\(([^;]+)\);)/U', $text, $matches);
$values = rtrim($matches[2]) . "\n";
$new_result = '';
$indent = ' ';

foreach ($this->delegates as $key => $value) {
$delegateTable = $this->getDelegateTable($key);

$ns = $delegateTable->getNamespace() ? '\\'.$delegateTable->getNamespace() : '';
$new_result .= "\$keys_{$key} = {$ns}\\Map\\{$delegateTable->getPhpName()}TableMap::getFieldNames(\$keyType);\n";
$i = 0;
foreach ($delegateTable->getColumns() as $column) {
if (!$this->isColumnForeignKeyOrDuplicated($column)) {
$values .= "{$indent} \$keys_{$key}[{$i}] => \$this->get{$column->getPhpName()}(),\n";
}
$i++;
}
}

$new_result .= "{$indent}\$result = array({$values}\n{$indent});";
$text = str_replace($matches[1], $new_result , $text);
$p->replaceMethod('toArray', $text);
$script = $p->getCode();

return $script;
}

/**
* @param Column $column
*
* @return bool
*
* @throws PropelException
*/
protected function isColumnForeignKeyOrDuplicated(Column $column)
{
$delegateTable = $column->getTable();
$table = $this->getTable();

$fks = [];
foreach ($delegateTable->getForeignKeysReferencingTable($table->getName()) as $fk) {
/** @var \Propel\Generator\Model\ForeignKey $fk */
$fks[] = $fk->getForeignColumnName();
}
foreach ($table->getForeignKeysReferencingTable($delegateTable->getName()) as $fk) {
$fks[] = $fk->getForeignColumnName();
}

if (in_array($column->getName(), $fks)) {
return true;
} else {
if ($table->hasColumn($column->getName())) {
throw new PropelException('Column with name «'.$column->getName().'» (delegated from table «'.$delegateTable->getName().'») already exists in table «'.$table->getName().'». Probably database design mistake');
}

return false;
}
}

public function queryAttributes()
{
$script = '';
$collations = '';

foreach ($this->delegates as $delegate => $type) {
$delegateTable = $this->getDelegateTable($delegate);

foreach ($delegateTable->getColumns() as $column) {
if (!$this->isColumnForeignKeyOrDuplicated($column)) {
$collations .= " '{$column->getPhpName()}' => '{$delegateTable->getPhpName()}',\n";
}
}
}

if ($collations) {
$collations = substr($collations, 0, -1);
$script .= "
protected \$delegatedFields = [
{$collations}
];
";
}

return $script;
}

public function queryMethods(QueryBuilder $builder)
{
$script = '';

foreach ($this->delegates as $delegate => $type) {
$delegateTable = $this->getDelegateTable($delegate);

foreach ($delegateTable->getColumns() as $column) {
if (!$this->isColumnForeignKeyOrDuplicated($column)) {
$phpName = $column->getPhpName();
$fieldName = $column->getName();
$tablePhpName = $delegateTable->getPhpName();
$childClassName = 'Child' . $builder->getUnprefixedClassName();

$script .= $this->renderTemplate('queryMethodsTemplate', compact('tablePhpName', 'phpName', 'childClassName', 'fieldName'));
}

}
}

if ($this->delegates) {
$script .= "
/**
* Adds a condition on a column based on a column phpName and a value
* Uses introspection to translate the column phpName into a fully qualified name
* Warning: recognizes only the phpNames of the main Model (not joined tables)
* <code>
* \$c->filterBy('Title', 'foo');
* </code>
*
* @see Criteria::add()
*
* @param string \$column A string representing thecolumn phpName, e.g. 'AuthorId'
* @param mixed \$value A value for the condition
* @param string \$comparison What to use for the column comparison, defaults to Criteria::EQUAL
*
* @return \$this|ModelCriteria The current object, for fluid interface
*/
public function filterBy(\$column, \$value, \$comparison = Criteria::EQUAL)
{
if (isset(\$this->delegatedFields[\$column])) {
\$methodUse = \"use{\$this->delegatedFields[\$column]}Query\";
return \$this->{\$methodUse}()->filterBy(\$column, \$value, \$comparison)->endUse();
} else {
return \$this->add(\$this->getRealColumnName(\$column), \$value, \$comparison);
}
}
";
}

return $script;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Filter the query by <?=$fieldName?> column
*
* Example usage:
* <code>
* $query->filterBy<?=$phpName?>(1234); // WHERE <?=$fieldName?> = 1234
* $query->filterBy<?=$phpName?>(array(12, 34)); // WHERE <?=$fieldName?> IN (12, 34)
* $query->filterBy<?=$phpName?>(array('min' => 12)); // WHERE <?=$fieldName?> > 12
* </code>
*
* @param mixed $value The value to use as filter.
* Use scalar values for equality.
* Use array values for in_array() equivalent.
* Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
*
* @return $this|<?=$childClassName?> The current query, for fluid interface
*/
public function filterBy<?=$phpName?>($value = null, $comparison = null)
{
return $this->use<?=$tablePhpName?>Query()->filterBy<?=$phpName?>($value, $comparison)->endUse();
}

/**
* Adds an ORDER BY clause to the query
* Usability layer on top of Criteria::addAscendingOrderByColumn() and Criteria::addDescendingOrderByColumn()
* Infers $column and $order from $columnName and some optional arguments
* Examples:
* $c->orderBy('Book.CreatedAt')
* => $c->addAscendingOrderByColumn(BookTableMap::CREATED_AT)
* $c->orderBy('Book.CategoryId', 'desc')
* => $c->addDescendingOrderByColumn(BookTableMap::CATEGORY_ID)
*
* @param string $order The sorting order. Criteria::ASC by default, also accepts Criteria::DESC
*
* @return $this|ModelCriteria The current object, for fluid interface
*/
public function orderBy<?=$phpName?>($order = Criteria::ASC)
{
return $this->use<?=$tablePhpName?>Query()->orderBy<?=$phpName?>($order)->endUse();
}

0 comments on commit 350e3c4

Please sign in to comment.