Skip to content

Commit

Permalink
Merge pull request propelorm#635 from K-Phoen/behavior
Browse files Browse the repository at this point in the history
Allow behaviors to be applied more than once
  • Loading branch information
Marc J. Schmidt committed Jul 15, 2014
2 parents 7b200b3 + 45fdfb0 commit 0b7b240
Show file tree
Hide file tree
Showing 19 changed files with 210 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ class AggregateColumnBehavior extends Behavior
'foreign_schema' => null,
);

/**
* Multiple aggregates on the same table is OK.
*
* @return bool
*/
public function allowMultiple()
{
return true;
}

/**
* Add the aggregate key to the current table
*/
Expand All @@ -51,7 +61,9 @@ public function modifyTable()
if (!$foreignTable->hasBehavior('concrete_inheritance_parent')) {
$relationBehavior = new AggregateColumnRelationBehavior();
$relationBehavior->setName('aggregate_column_relation');
$relationBehavior->setId('aggregate_column_relation_'.$this->getId());
$relationBehavior->addParameter(array('name' => 'foreign_table', 'value' => $table->getName()));
$relationBehavior->addParameter(array('name' => 'aggregate_name', 'value' => $this->getColumn()->getPhpName()));
$relationBehavior->addParameter(array('name' => 'update_method', 'value' => 'update' . $this->getColumn()->getPhpName()));
$foreignTable->addBehavior($relationBehavior);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,22 @@ class AggregateColumnRelationBehavior extends Behavior
{
// default parameters value
protected $parameters = array(
'foreign_table' => '',
'update_method' => '',
'foreign_table' => '',
'update_method' => '',
'aggregate_name' => '',
);

public function allowMultiple()
{
return true;
}

public function postSave($builder)
{
$relationName = $this->getRelationName($builder);
$aggregateName = $this->getParameter('aggregate_name');

return "\$this->updateRelated{$relationName}(\$con);";
return "\$this->updateRelated{$relationName}{$aggregateName}(\$con);";
}

// no need for a postDelete() hook, since delete() uses Query::delete(),
Expand All @@ -39,11 +46,12 @@ public function objectAttributes($builder)
{
$relationName = $this->getRelationName($builder);
$relatedClass = $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($this->getForeignTable()));
$aggregateName = $this->getParameter('aggregate_name');

return "/**
* @var $relatedClass
*/
protected \$old{$relationName};
protected \$old{$relationName}{$aggregateName};
";
}

Expand All @@ -58,6 +66,7 @@ protected function addObjectUpdateRelated($builder)

return $this->renderTemplate('objectUpdateRelated', array(
'relationName' => $relationName,
'aggregateName' => $this->getParameter('aggregate_name'),
'variableName' => lcfirst($relationName),
'updateMethodName' => $this->getParameter('update_method'),
));
Expand All @@ -66,13 +75,14 @@ protected function addObjectUpdateRelated($builder)
public function objectFilter(&$script, $builder)
{
$relationName = $this->getRelationName($builder);
$aggregateName = $this->getParameter('aggregate_name');
$relatedClass = $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($this->getForeignTable()));
$search = " public function set{$relationName}({$relatedClass} \$v = null)
{";
$replace = $search . "
// aggregate_column_relation behavior
if (null !== \$this->a{$relationName} && \$v !== \$this->a{$relationName}) {
\$this->old{$relationName} = \$this->a{$relationName};
\$this->old{$relationName}{$aggregateName} = \$this->a{$relationName};
}";
$script = str_replace($search, $replace, $script);
}
Expand All @@ -90,8 +100,9 @@ public function preDeleteQuery($builder)
protected function getFindRelated($builder)
{
$relationName = $this->getRelationName($builder);
$aggregateName = $this->getParameter('aggregate_name');

return "\$this->findRelated{$relationName}s(\$con);";
return "\$this->findRelated{$relationName}{$aggregateName}s(\$con);";
}

public function postUpdateQuery($builder)
Expand All @@ -107,13 +118,15 @@ public function postDeleteQuery($builder)
protected function getUpdateRelated($builder)
{
$relationName = $this->getRelationName($builder);
$aggregateName = $this->getParameter('aggregate_name');

return "\$this->updateRelated{$relationName}s(\$con);";
return "\$this->updateRelated{$relationName}{$aggregateName}s(\$con);";
}

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

$script .= $this->addQueryFindRelated($builder);
$script .= $this->addQueryUpdateRelated($builder);

Expand All @@ -134,7 +147,8 @@ protected function addQueryFindRelated($builder)
return $this->renderTemplate('queryFindRelated', array(
'foreignTable' => $this->getForeignTable(),
'relationName' => $relationName,
'variableName' => lcfirst($relationName),
'aggregateName' => $this->getParameter('aggregate_name'),
'variableName' => lcfirst($relationName.$this->getParameter('aggregate_name')),
'foreignQueryName' => $foreignQueryBuilder->getClassName(),
'refRelationName' => $builder->getRefFKPhpNameAffix($foreignKey),
));
Expand All @@ -146,7 +160,8 @@ protected function addQueryUpdateRelated($builder)

return $this->renderTemplate('queryUpdateRelated', array(
'relationName' => $relationName,
'variableName' => lcfirst($relationName),
'aggregateName' => $this->getParameter('aggregate_name'),
'variableName' => lcfirst($relationName.$this->getParameter('aggregate_name')),
'updateMethodName' => $this->getParameter('update_method'),
));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
*
* @param ConnectionInterface $con A connection object
*/
protected function updateRelated<?=$relationName?>(ConnectionInterface $con)
protected function updateRelated<?=$relationName.$aggregateName?>(ConnectionInterface $con)
{
if ($<?=$variableName?> = $this->get<?=$relationName?>()) {
$<?=$variableName?>-><?=$updateMethodName?>($con);
}
if ($this->old<?=$relationName?>) {
$this->old<?=$relationName?>-><?=$updateMethodName?>($con);
$this->old<?=$relationName?> = null;
if ($this->old<?=$relationName.$aggregateName?>) {
$this->old<?=$relationName.$aggregateName?>-><?=$updateMethodName?>($con);
$this->old<?=$relationName.$aggregateName?> = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* @param ConnectionInterface $con A connection object
*/
protected function findRelated<?=$relationName?>s($con)
protected function findRelated<?=$relationName.$aggregateName?>s($con)
{
$criteria = clone $this;
if ($this->useAliasInSQL) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

protected function updateRelated<?=$relationName?>s($con)
protected function updateRelated<?=$relationName.$aggregateName?>s($con)
{
foreach ($this-><?=$variableName?>s as $<?=$variableName?>) {
$<?=$variableName?>-><?= $updateMethodName ?>($con);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ArchivableBehavior extends Behavior
public function modifyDatabase()
{
foreach ($this->getDatabase()->getTables() as $table) {
if ($table->hasBehavior($this->getName())) {
if ($table->hasBehavior($this->getId())) {
// don't add the same behavior twice
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class VersionableBehavior extends Behavior
public function modifyDatabase()
{
foreach ($this->getDatabase()->getTables() as $table) {
if ($table->hasBehavior($this->getName())) {
if ($table->hasBehavior($this->getId())) {
// don't add the same behavior twice
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ public function populateFromVersion(\$version, \$con = null, &\$loadedObjects =
$plural = false;
foreach ($this->behavior->getVersionableFks() as $fk) {
$foreignTable = $fk->getForeignTable();
$foreignVersionTable = $fk->getForeignTable()->getBehavior($this->behavior->getName())->getVersionTable();
$foreignVersionTable = $fk->getForeignTable()->getBehavior($this->behavior->getId())->getVersionTable();
$relatedClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($foreignTable));
$relatedVersionQueryClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($foreignVersionTable));
$fkColumnName = $fk->getLocalColumnName();
Expand Down Expand Up @@ -407,7 +407,7 @@ public function populateFromVersion(\$version, \$con = null, &\$loadedObjects =
$plural = false;
$fkPhpName = $this->builder->getRefFKPhpNameAffix($fk, $plural);
$foreignTable = $fk->getTable();
$foreignBehavior = $foreignTable->getBehavior($this->behavior->getName());
$foreignBehavior = $foreignTable->getBehavior($this->behavior->getId());
$foreignVersionTable = $foreignBehavior->getVersionTable();
$fkColumnIds = $this->behavior->getReferrerIdsColumn($fk);
$fkColumnVersions = $this->behavior->getReferrerVersionsColumn($fk);
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Builder/Om/AbstractOMBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ public function applyBehaviorModifierBase($hookName, $modifier, &$script, $tab =
continue;
}
$script .= "
" . $tab . '// ' . $behavior->getName() . " behavior
" . $tab . '// ' . $behavior->getId() . " behavior
";
$script .= preg_replace('/^/m', $tab, $addedScript);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Builder/Om/TableMapBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ public function getBehaviors()
return array(";
foreach ($behaviors as $behavior) {
$script .= "
'{$behavior->getName()}' => array(";
'{$behavior->getId()}' => array(";
foreach ($behavior->getParameters() as $key => $value) {
$script .= "'$key' => ";
if (is_array($value)) {
Expand Down
53 changes: 51 additions & 2 deletions src/Propel/Generator/Model/Behavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace Propel\Generator\Model;

use Propel\Generator\Builder\Util\PropelTemplate;
use Propel\Generator\Exception\LogicException;

/**
* Information about behaviors of a table.
Expand All @@ -34,6 +35,13 @@ class Behavior extends MappingModel
*/
protected $database;

/**
* The behavior id.
*
* @var string
*/
protected $id;

/**
* The behavior name.
*
Expand Down Expand Up @@ -88,6 +96,41 @@ class Behavior extends MappingModel
public function setName($name)
{
$this->name = $name;

if ($this->id === null) {
$this->id = $name;
}
}

/**
* Sets the id of the Behavior
*
* @param string $id The id of the behavior
*/
public function setId($id)
{
$this->id = $id;
}

/**
* Indicates whether the behavior can be applied several times on the same
* table or not.
*
* @return bool
*/
public function allowMultiple()
{
return false;
}

/**
* Returns the id of the Behavior
*
* @return string
*/
public function getId()
{
return $this->id;
}

/**
Expand Down Expand Up @@ -226,7 +269,7 @@ public function getTableModificationOrder()
public function modifyDatabase()
{
foreach ($this->getTables() as $table) {
if ($table->hasBehavior($this->getName())) {
if ($table->hasBehavior($this->getId())) {
// don't add the same behavior twice
continue;
}
Expand Down Expand Up @@ -335,7 +378,13 @@ public function getColumnForParameter($name)

protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->setName($this->getAttribute('name'));

if (!$this->allowMultiple() && $id = $this->getAttribute('id')) {
throw new LogicException(sprintf('Defining an ID (%s) on a behavior which does not allow multiple instances makes no sense', $id));
}

$this->id = $this->getAttribute('id', $this->name);
}

/**
Expand Down
29 changes: 20 additions & 9 deletions src/Propel/Generator/Model/BehaviorableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,19 @@ public function addBehavior($bdata)
{
if ($bdata instanceof Behavior) {
$behavior = $bdata;

// the new behavior is already registered
if ($this->hasBehavior($behavior->getId()) && $behavior->allowMultiple()) {
// the user probably just forgot to specify the "id" attribute
if ($behavior->getId() === $behavior->getName()) {
throw new BuildException(sprintf('Behavior "%s" is already registered. Specify a different ID attribute to register the same behavior several times.', $behavior->getName()));
} else { // or he copy-pasted it and forgot to update it.
throw new BuildException(sprintf('A behavior with ID "%s" is already registered.', $behavior->getId()));
}
}

$this->registerBehavior($behavior);
$this->behaviors[$behavior->getName()] = $behavior;
$this->behaviors[$behavior->getId()] = $behavior;

return $behavior;
}
Expand Down Expand Up @@ -92,24 +103,24 @@ public function getBehaviors()
/**
* check if the given behavior exists
*
* @param string $name the behavior name
* @param string $id the behavior id
* @return boolean True if the behavior exists
*/
public function hasBehavior($name)
public function hasBehavior($id)
{
return array_key_exists($name, $this->behaviors);
return array_key_exists($id, $this->behaviors);
}

/**
* Get behavior by name
* Get behavior by id
*
* @param string $name the behavior name
* @param string $id the behavior id
* @return Behavior a behavior object or null if the behavior doesn't exist
*/
public function getBehavior($name)
public function getBehavior($id)
{
if ($this->hasBehavior($name)) {
return $this->behaviors[$name];
if ($this->hasBehavior($id)) {
return $this->behaviors[$id];
}

return null;
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Model/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ public function joinSchemas(array $schemas)
}
// join database behaviors
foreach ($addDb->getBehaviors() as $addBehavior) {
if (!$db->hasBehavior($addBehavior->getName())) {
if (!$db->hasBehavior($addBehavior->getId())) {
$db->addBehavior($addBehavior);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/Propel/Generator/Schema/Dumper/XmlDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ private function appendBehaviorNode(Behavior $behavior, \DOMNode $parentNode)
$behaviorNode = $parentNode->appendChild($this->document->createElement('behavior'));
$behaviorNode->setAttribute('name', $behavior->getName());

if ($behavior->allowMultiple()) {
$behaviorNode->setAttribute('id', $behavior->getId());
}

foreach ($behavior->getParameters() as $name => $value) {
$parameterNode = $behaviorNode->appendChild($this->document->createElement('parameter'));
$parameterNode->setAttribute('name', $name);
Expand Down
Loading

0 comments on commit 0b7b240

Please sign in to comment.