@@ -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 ' ))
@@ -857,21 +857,33 @@ public function buildPhpDocs(array $definition)
857857 return $ ret ;
858858 }
859859
860+ /**
861+ * find class matching $name
862+ *
863+ * @param $name
864+ * @return string
865+ */
866+ private function findTemplateClassMatchingName ($ name )
867+ {
868+ $ classname = $ name ;
869+ if (class_exists ("Doctrine_Template_ $ name " , true )) {
870+ $ classname = "Doctrine_Template_ $ name " ;
871+ }
872+
873+ return $ classname ;
874+ }
875+
860876 /**
861877 * emit a behavior assign
862878 *
863879 * @param int $level
864880 * @param string $name
865881 * @param string $option
882+ * @param string $classname
866883 * @return string assignation code
867884 */
868- private function emitAssign ($ level , $ name , $ option )
885+ private function emitAssign ($ level , $ name , $ option, $ classname )
869886 {
870- // find class matching $name
871- $ classname = $ name ;
872- if (class_exists ("Doctrine_Template_ $ name " , true )) {
873- $ classname = "Doctrine_Template_ $ name " ;
874- }
875887 return " \$" . strtolower ($ name ) . "$ level = new $ classname( $ option); " . PHP_EOL ;
876888 }
877889
@@ -904,11 +916,12 @@ private function emitActAs($level, $name)
904916 /**
905917 * buildActAs: builds a complete actAs code. It supports hierarchy of plugins
906918 * @param array $actAs array of plugin definitions and options
919+ * @param array $actAsColumns contains on output an array of columns defined by actAs behaviors
907920 */
908- public function buildActAs ($ actAs )
921+ public function buildActAs ($ actAs, array & $ actAsColumns = array () )
909922 {
910923 $ emittedActAs = array ();
911- $ build = $ this ->innerBuildActAs ($ actAs , 0 , null , $ emittedActAs );
924+ $ build = $ this ->innerBuildActAs ($ actAs , 0 , null , $ emittedActAs, $ actAsColumns );
912925 foreach ($ emittedActAs as $ str ) {
913926 $ build .= $ str ;
914927 }
@@ -922,9 +935,10 @@ public function buildActAs($actAs)
922935 * @param int $level current indentation level
923936 * @param string $parent name of the parent template/plugin
924937 * @param array $emittedActAs contains on output an array of actAs command to be appended to output
938+ * @param array $actAsColumns contains on output an array of columns defined by actAs behaviors
925939 * @return string actAs full definition
926940 */
927- private function innerBuildActAs ($ actAs , $ level = 0 , $ parent = null , array &$ emittedActAs = array ())
941+ private function innerBuildActAs ($ actAs , $ level = 0 , $ parent = null , array &$ emittedActAs = array (), array & $ actAsColumns = array () )
928942 {
929943 // rewrite special case of actAs: [Behavior] which gave [0] => Behavior
930944 if (is_array ($ actAs ) && isset ($ actAs [0 ]) && !is_array ($ actAs [0 ])) {
@@ -943,9 +957,10 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
943957 $ currentParent = $ parent ;
944958 if (is_array ($ actAs )) {
945959 foreach ($ actAs as $ template => $ options ) {
960+ $ className = $ this ->findTemplateClassMatchingName ($ template );
946961 if ($ template == 'actAs ' ) {
947962 // found another actAs
948- $ build .= $ this ->innerBuildActAs ($ options , $ level + 1 , $ parent , $ emittedActAs );
963+ $ build .= $ this ->innerBuildActAs ($ options , $ level + 1 , $ parent , $ emittedActAs, $ actAsColumns );
949964 } else if (is_array ($ options )) {
950965 // remove actAs from options
951966 $ realOptions = array ();
@@ -959,17 +974,19 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
959974 }
960975
961976 $ optionPHP = $ this ->varExport ($ realOptions );
962- $ build .= $ this ->emitAssign ($ level , $ template , $ optionPHP );
977+ $ build .= $ this ->emitAssign ($ level , $ template , $ optionPHP , $ className );
978+ $ this ->addActAsColumnsToDefinition ($ className , $ realOptions , $ actAsColumns );
963979 if ($ level == 0 ) {
964980 $ emittedActAs [] = $ this ->emitActAs ($ level , $ template );
965981 } else {
966982 $ build .= $ this ->emitAddChild ($ level , $ currentParent , $ template );
967983 }
968984 // descend for the remainings actAs
969985 $ parent = $ template ;
970- $ build .= $ this ->innerBuildActAs ($ leftActAs , $ level , $ template , $ emittedActAs );
986+ $ build .= $ this ->innerBuildActAs ($ leftActAs , $ level , $ template , $ emittedActAs, $ actAsColumns );
971987 } else {
972- $ build .= $ this ->emitAssign ($ level , $ template , null );
988+ $ build .= $ this ->emitAssign ($ level , $ template , null , $ className );
989+ $ this ->addActAsColumnsToDefinition ($ className , array ($ options ), $ actAsColumns );
973990 if ($ level == 0 ) {
974991 $ emittedActAs [] = $ this ->emitActAs ($ level , $ template );
975992 } else {
@@ -979,7 +996,9 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
979996 }
980997 }
981998 } else {
982- $ build .= $ this ->emitAssign ($ level , $ actAs , null );
999+ $ className = $ this ->findTemplateClassMatchingName ($ actAs );
1000+ $ build .= $ this ->emitAssign ($ level , $ actAs , null , $ className );
1001+ $ this ->addActAsColumnsToDefinition ($ className , array (), $ actAsColumns );
9831002 if ($ level == 0 ) {
9841003 $ emittedActAs [] = $ this ->emitActAs ($ level , $ actAs );
9851004 } else {
@@ -990,6 +1009,56 @@ private function innerBuildActAs($actAs, $level = 0, $parent = null, array &$emi
9901009 return $ build ;
9911010 }
9921011
1012+ /**
1013+ * Adds the columns of the used actAs behaviors to the comment block.
1014+ *
1015+ * @param string $className
1016+ * @param array $instanceOptions
1017+ * @param array $actAsColumns
1018+ *
1019+ * @throws Doctrine_Import_Builder_Exception
1020+ */
1021+ private function addActAsColumnsToDefinition ($ className , $ instanceOptions , &$ actAsColumns )
1022+ {
1023+ // No class specified or class does not exist.
1024+ if (!$ className || !class_exists ($ className )) {
1025+ return ;
1026+ }
1027+
1028+ $ actAsInstance = new $ className ($ instanceOptions );
1029+ $ options = $ actAsInstance ->getOptions ();
1030+
1031+ if (count ($ options ) == 0 ) {
1032+ return ;
1033+ }
1034+
1035+ // Some behaviors do not contain an array of columns, e.g. SoftDelete.
1036+ if (!is_array (reset ($ options ))) {
1037+ $ options = array ($ options );
1038+ }
1039+
1040+ foreach ($ options as $ name => $ column ) {
1041+ if (!is_array ($ column ) || !array_key_exists ('name ' , $ column ) || !array_key_exists ('type ' , $ column )) {
1042+ // 'name' or 'type' not found. Unfortunately there is no logger. What is the best way to abort here?
1043+ continue ;
1044+ }
1045+
1046+ if (array_key_exists ('disabled ' , $ column ) && $ column ['disabled ' ]) {
1047+ // Column has been disabled.
1048+ continue ;
1049+ }
1050+
1051+ // Add field, if it does not exist already.
1052+ if (
1053+ !array_key_exists ($ name , $ actAsColumns )
1054+ && !array_key_exists ($ column ['name ' ], $ actAsColumns )
1055+ ) {
1056+ $ actAsColumns [$ name ] = $ column ;
1057+ }
1058+ }
1059+ }
1060+
1061+
9931062 /**
9941063 * Build php code for adding record listeners
9951064 *
@@ -1122,9 +1191,10 @@ public function buildDefinition(array $definition)
11221191 $ className = $ definition ['className ' ];
11231192 $ extends = isset ($ definition ['inheritance ' ]['extends ' ]) ? $ definition ['inheritance ' ]['extends ' ]:$ this ->_baseClassName ;
11241193
1194+ $ actAsColumns = array ();
11251195 if ( ! (isset ($ definition ['no_definition ' ]) && $ definition ['no_definition ' ] === true )) {
11261196 $ tableDefinitionCode = $ this ->buildTableDefinition ($ definition );
1127- $ setUpCode = $ this ->buildSetUp ($ definition );
1197+ $ setUpCode = $ this ->buildSetUp ($ definition, $ actAsColumns );
11281198 } else {
11291199 $ tableDefinitionCode = null ;
11301200 $ setUpCode = null ;
@@ -1136,7 +1206,7 @@ public function buildDefinition(array $definition)
11361206
11371207 $ setUpCode .= $ this ->buildToString ($ definition );
11381208
1139- $ docs = PHP_EOL . $ this ->buildPhpDocs ($ definition );
1209+ $ docs = PHP_EOL . $ this ->buildPhpDocs ($ definition, $ actAsColumns );
11401210
11411211 $ content = sprintf (self ::$ _tpl , $ docs , $ abstract ,
11421212 $ className ,
0 commit comments