Skip to content

Commit a2ed8ed

Browse files
committed
Adding columns defined in actAs-templates to the docblock of the generated model class.
1 parent 33bebf2 commit a2ed8ed

File tree

2 files changed

+105
-18
lines changed

2 files changed

+105
-18
lines changed

lib/Doctrine/Import/Builder.php

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,11 @@ public function buildTableDefinition(array $definition)
396396
/**
397397
* buildSetUp
398398
*
399-
* @param array $options
400-
* @param array $columns
401-
* @param array $relations
399+
* @param array $definition
400+
* @param array $actAsColumns
402401
* @return string
403402
*/
404-
public function buildSetUp(array $definition)
403+
public function buildSetUp(array $definition, array &$actAsColumns = array())
405404
{
406405
$ret = array();
407406
$i = 0;
@@ -483,7 +482,7 @@ public function buildSetUp(array $definition)
483482
}
484483

485484
if (isset($definition['actAs']) && is_array($definition['actAs']) && !empty($definition['actAs'])) {
486-
$ret[$i] = $this->buildActAs($definition['actAs']);
485+
$ret[$i] = $this->buildActAs($definition['actAs'], $actAsColumns);
487486
$i++;
488487
}
489488

@@ -640,8 +639,9 @@ public function buildAccessors(array $definition)
640639
* Build the phpDoc for a class definition
641640
*
642641
* @param array $definition
642+
* @param array $actAsColumns
643643
*/
644-
public function buildPhpDocs(array $definition)
644+
public function buildPhpDocs(array $definition, array $actAsColumns = array())
645645
{
646646
$ret = array();
647647
$ret[] = $definition['className'];
@@ -654,7 +654,7 @@ public function buildPhpDocs(array $definition)
654654
$setters = array();
655655

656656
if ((isset($definition['is_base_class']) && $definition['is_base_class']) || ! $this->generateBaseClasses()) {
657-
foreach ($definition['columns'] as $name => $column) {
657+
foreach (array_merge($definition['columns'], $actAsColumns) as $name => $column) {
658658
$name = isset($column['name']) ? $column['name']:$name;
659659
// extract column name & field name
660660
if (stripos($name, ' as '))
@@ -865,7 +865,7 @@ public function buildPhpDocs(array $definition)
865865
* @param string $option
866866
* @return string assignation code
867867
*/
868-
private function emitAssign($level, $name, $option)
868+
private function emitAssign($level, $name, $option, &$classname)
869869
{
870870
// find class matching $name
871871
$classname = $name;
@@ -904,11 +904,12 @@ private function emitActAs($level, $name)
904904
/**
905905
* buildActAs: builds a complete actAs code. It supports hierarchy of plugins
906906
* @param array $actAs array of plugin definitions and options
907+
* @param array $actAsColumns contains on output an array of columns defined by actAs behaviors
907908
*/
908-
public function buildActAs($actAs)
909+
public function buildActAs($actAs, array &$actAsColumns = array())
909910
{
910911
$emittedActAs = array();
911-
$build = $this->innerBuildActAs($actAs, 0, null, $emittedActAs);
912+
$build = $this->innerBuildActAs($actAs, 0, null, $emittedActAs, $actAsColumns);
912913
foreach($emittedActAs as $str) {
913914
$build .= $str;
914915
}
@@ -922,9 +923,10 @@ public function buildActAs($actAs)
922923
* @param int $level current indentation level
923924
* @param string $parent name of the parent template/plugin
924925
* @param array $emittedActAs contains on output an array of actAs command to be appended to output
926+
* @param array $actAsColumns contains on output an array of columns defined by actAs behaviors
925927
* @return string actAs full definition
926928
*/
927-
private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emittedActAs = array())
929+
private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emittedActAs = array(), array &$actAsColumns = array())
928930
{
929931
// rewrite special case of actAs: [Behavior] which gave [0] => Behavior
930932
if (is_array($actAs) && isset($actAs[0]) && !is_array($actAs[0])) {
@@ -945,7 +947,7 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
945947
foreach($actAs as $template => $options) {
946948
if ($template == 'actAs') {
947949
// found another actAs
948-
$build .= $this->innerBuildActAs($options, $level + 1, $parent, $emittedActAs);
950+
$build .= $this->innerBuildActAs($options, $level + 1, $parent, $emittedActAs, $actAsColumns);
949951
} else if (is_array($options)) {
950952
// remove actAs from options
951953
$realOptions = array();
@@ -959,17 +961,19 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
959961
}
960962

961963
$optionPHP = $this->varExport($realOptions);
962-
$build .= $this->emitAssign($level, $template, $optionPHP);
964+
$build .= $this->emitAssign($level, $template, $optionPHP, $className);
965+
$this->addActAsColumnsToDefinition($className, $realOptions, $actAsColumns);
963966
if ($level == 0) {
964967
$emittedActAs[] = $this->emitActAs($level, $template);
965968
} else {
966969
$build .= $this->emitAddChild($level, $currentParent, $template);
967970
}
968971
// descend for the remainings actAs
969972
$parent = $template;
970-
$build .= $this->innerBuildActAs($leftActAs, $level, $template, $emittedActAs);
973+
$build .= $this->innerBuildActAs($leftActAs, $level, $template, $emittedActAs, $actAsColumns);
971974
} else {
972-
$build .= $this->emitAssign($level, $template, null);
975+
$build .= $this->emitAssign($level, $template, null, $className);
976+
$this->addActAsColumnsToDefinition($className, array($options), $actAsColumns);
973977
if ($level == 0) {
974978
$emittedActAs[] = $this->emitActAs($level, $template);
975979
} else {
@@ -979,7 +983,8 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
979983
}
980984
}
981985
} else {
982-
$build .= $this->emitAssign($level, $actAs, null);
986+
$build .= $this->emitAssign($level, $actAs, null, $className);
987+
$this->addActAsColumnsToDefinition($className, array(), $actAsColumns);
983988
if ($level == 0) {
984989
$emittedActAs[] = $this->emitActAs($level, $actAs);
985990
} else {
@@ -990,6 +995,56 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
990995
return $build;
991996
}
992997

998+
/**
999+
* Adds the columns of the used actAs behaviors to the comment block.
1000+
*
1001+
* @param string $className
1002+
* @param array $instanceOptions
1003+
* @param array $actAsColumns
1004+
*
1005+
* @throws Doctrine_Import_Builder_Exception
1006+
*/
1007+
private function addActAsColumnsToDefinition($className, $instanceOptions, &$actAsColumns)
1008+
{
1009+
// No class specified or class does not exist.
1010+
if (!$className || !class_exists($className)) {
1011+
return;
1012+
}
1013+
1014+
$actAsInstance = new $className($instanceOptions);
1015+
$options = $actAsInstance->getOptions();
1016+
1017+
if (count($options) == 0) {
1018+
return;
1019+
}
1020+
1021+
// Some behaviors do not contain an array of columns, e.g. SoftDelete.
1022+
if (!is_array(reset($options))) {
1023+
$options = [$options];
1024+
}
1025+
1026+
foreach ($options as $name => $column) {
1027+
if (!is_array($column) || !array_key_exists('name', $column) || !array_key_exists('type', $column)) {
1028+
// 'name' or 'type' not found. Unfortunately there is no logger. What is the best way to abort here?
1029+
continue;
1030+
}
1031+
1032+
if (array_key_exists('disabled', $column) && $column['disabled']) {
1033+
// Column has been disabled.
1034+
continue;
1035+
}
1036+
1037+
// Add field, if it does not exist already.
1038+
if (
1039+
!array_key_exists($name, $actAsColumns)
1040+
&& !array_key_exists($column['name'], $actAsColumns)
1041+
) {
1042+
$actAsColumns[$name] = $column;
1043+
}
1044+
}
1045+
}
1046+
1047+
9931048
/**
9941049
* Build php code for adding record listeners
9951050
*
@@ -1122,9 +1177,10 @@ public function buildDefinition(array $definition)
11221177
$className = $definition['className'];
11231178
$extends = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends']:$this->_baseClassName;
11241179

1180+
$actAsColumns = array();
11251181
if ( ! (isset($definition['no_definition']) && $definition['no_definition'] === true)) {
11261182
$tableDefinitionCode = $this->buildTableDefinition($definition);
1127-
$setUpCode = $this->buildSetUp($definition);
1183+
$setUpCode = $this->buildSetUp($definition, $actAsColumns);
11281184
} else {
11291185
$tableDefinitionCode = null;
11301186
$setUpCode = null;
@@ -1136,7 +1192,7 @@ public function buildDefinition(array $definition)
11361192

11371193
$setUpCode.= $this->buildToString($definition);
11381194

1139-
$docs = PHP_EOL . $this->buildPhpDocs($definition);
1195+
$docs = PHP_EOL . $this->buildPhpDocs($definition, $actAsColumns);
11401196

11411197
$content = sprintf(self::$_tpl, $docs, $abstract,
11421198
$className,

tests/Ticket/gh110TestCase.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
class Doctrine_Ticket_gh110_TestCase extends Doctrine_UnitTestCase
4+
{
5+
public function testAddActAsColumnsToDocBlock()
6+
{
7+
$builder = new Doctrine_Import_Builder();
8+
$class = $builder->buildDefinition(
9+
array(
10+
'className' => 'Ticket_gh110_TestRecord',
11+
'topLevelClassName' => 'Ticket_gh110_TestRecord',
12+
'is_base_class' => true,
13+
'columns' => array(
14+
'id' => array(
15+
'type' => 'integer',
16+
'length' => 4,
17+
)
18+
),
19+
'actAs' => array(
20+
'SoftDelete' => array(),
21+
'Timestampable' => array(),
22+
)
23+
)
24+
);
25+
26+
$this->assertTrue(preg_match('/@property int\s*\$id/', $class));
27+
$this->assertTrue(preg_match('/@property string\s*\$deleted_at/', $class));
28+
$this->assertTrue(preg_match('/@property string\s*\$created_at/', $class));
29+
$this->assertTrue(preg_match('/@property string\s*\$updated_at/', $class));
30+
}
31+
}

0 commit comments

Comments
 (0)