diff --git a/Model/Behavior/InheritableBehavior.php b/Model/Behavior/InheritableBehavior.php index fcbdc61..9efc1ec 100644 --- a/Model/Behavior/InheritableBehavior.php +++ b/Model/Behavior/InheritableBehavior.php @@ -44,7 +44,7 @@ class InheritableBehavior extends ModelBehavior { * Set up the behavior. * Finds parent model and determines type field settings * - * @param Model $Model + * @param Model $Model Model to determine parent and type field setting * @param array $config Behavior configuration * @internal param \Model $model * @return void @@ -69,7 +69,7 @@ public function setup(Model $Model, $config = array()) { * Before find callback * Filter query conditions with the correct `type' field condition. * - * @param Model $model + * @param Model $Model Model * @param array $query Find query * @return array Updated query */ @@ -95,9 +95,9 @@ public function beforeFind(Model $Model, $query) { * After find callback * In case of CTI inheritance, data contained in the 'ParentAlias' key are merged with Model data * - * @param Model $Model - * @param array $results - * @param boolean $primary + * @param Model $Model Model + * @param array $results results + * @param bool $primary primary * @return array Results */ public function afterFind(Model $Model, $results = array(), $primary = false) { @@ -141,8 +141,8 @@ public function afterFind(Model $Model, $results = array(), $primary = false) { * * Set the `type' field before saving the record in case of STI model * - * @param Model $Model - * @param array $options + * @param Model $Model Model + * @param array $options options * @return true */ public function beforeSave(Model $Model, $options = array()) { @@ -159,7 +159,7 @@ public function beforeSave(Model $Model, $options = array()) { * After delete callback * Deletes the parent model in case of CTI model * - * @param Model $Model + * @param Model $Model Model * @return true */ public function afterDelete(Model $Model) { @@ -174,7 +174,7 @@ public function afterDelete(Model $Model) { * * Deconstructs complex types by calling model parent's method * - * @param Model $Model + * @param Model $Model Model * @param array $options * @return true */ @@ -191,7 +191,7 @@ public function beforeValidate(Model $Model, $options = array()) { /** * Beforefind callback for STI models * - * @param Model $Model + * @param Model $Model Model * @param array $query Find query * @return Updated query */ @@ -222,7 +222,7 @@ protected function _singleTableBeforeFind(Model $Model, $query) { * BeforeSave callback for STI models * Sets the inheritance field to the correct Model alias * - * @param Model $Model + * @param Model $Model Model * @return true */ protected function _singleTableBeforeSave(Model $Model) { @@ -239,8 +239,8 @@ protected function _singleTableBeforeSave(Model $Model) { /** * Binds the parent model for a CTI model * - * @param Model $Model - * @return boolean Success of the binding + * @param Model $Model Model + * @return bool Success of the binding */ public function classTableBindParent(Model $Model) { $bind = array('belongsTo' => array( @@ -250,18 +250,48 @@ public function classTableBindParent(Model $Model) { 'foreignKey' => $Model->primaryKey ) )); + $assocs = array_flip($Model->parent->getAssociated()); + $ppk = $Model->parent->primaryKey; + if (array_key_exists('hasOne', $assocs)) { + $hasOne = $this->classParentAssociations($ppk, 'hasOne', $assocs); + $bind = array_merge($bind, $hasOne); + } + if (array_key_exists('hasMany', $assocs)) { + $hasMany = $this->classParentAssociations($ppk, 'hasMany', $assocs); + $bind = array_merge($bind, $hasMany); + } $success = $Model->bindModel($bind, false); - //Putting the parent association as the first one, so any dependent join on the parent model will be in the right order + //Putting the parent association as the first one, + //so any dependent join on the parent model will be in the right order $assoc = $Model->belongsTo[$Model->parent->alias]; unset($Model->belongsTo[$Model->parent->alias]); $Model->belongsTo = array_merge(array($Model->parent->alias => $assoc), $Model->belongsTo); return $success; } +/** + * Return the parent model association for a CTI model + * + * @param string $ppk Parent primary key + * @param string $name Association name + * @param array $assoc Association parent array + * @return array Association parent model + */ + + public function classParentAssociations($ppk, $name, $assoc) { + $data = array($name => array( + Hash::get($assoc, $name) => array( + 'className' => Hash::get($assoc, $name), + 'foreignKey' => $ppk + ) + )); + return $data; + } + /** * Binds additional belongsTo association from the parent for a CTI model * - * @param Model $Model + * @param Model $Model Model * @param array $binds, additional models to bind. They will be filtered to left only belongsTo associations */ protected function _classTableBindContains(Model $Model, $binds) { @@ -287,7 +317,7 @@ protected function _classTableBindContains(Model $Model, $binds) { * After save callback for CTI models * Saves data for the parent model * - * @param Model $Model + * @param Model $Model Model * @return true */ protected function _saveParentModel(Model $Model) { diff --git a/Test/Case/Model/Behavior/InheritableTest.php b/Test/Case/Model/Behavior/InheritableTest.php index f3270aa..8e6d8ff 100644 --- a/Test/Case/Model/Behavior/InheritableTest.php +++ b/Test/Case/Model/Behavior/InheritableTest.php @@ -38,13 +38,13 @@ class InheritableAsset extends CakeTestModel { public $name = 'Asset'; - public $validate = array('title' => array('rule' => 'notEmpty')); + public $validate = array('title' => array('rule' => 'notBlank')); } class Asset extends CakeTestModel { public $validate = array( - 'title' => array('rule' => 'notEmpty'), + 'title' => array('rule' => 'notBlank'), 'expiration' => array('rule' => 'date', 'allowEmpty' => true) ); } @@ -55,7 +55,7 @@ class InheritableLink extends InheritableAsset { public $actsAs = array('Utils.Inheritable' => array('method' => 'CTI')); - public $validate = array('url' => array('rule' => 'notEmpty')); + public $validate = array('url' => array('rule' => 'notBlank')); } class InheritableImage extends InheritableAsset { @@ -65,6 +65,16 @@ class InheritableImage extends InheritableAsset { public $actsAs = array('Utils.Inheritable' => array('method' => 'CTI')); } +class Person extends CakeTestModel { + + public $hasOne = 'Address'; +} + +class Client extends Person { + + public $actsAs = array('Utils.Inheritable' => array('method' => 'CTI')); +} + /** * InheritableTest class @@ -84,7 +94,9 @@ class InheritableTest extends CakeTestCase { 'plugin.utils.content', 'plugin.utils.asset', 'plugin.utils.link', - 'plugin.utils.image' + 'plugin.utils.image', + 'plugin.utils.person', + 'plugin.utils.address' ); /** @@ -108,6 +120,8 @@ public function setUp() { $this->Asset = ClassRegistry::init('InheritableAsset'); $this->Link = ClassRegistry::init('InheritableLink'); $this->Image = ClassRegistry::init('InheritableImage'); + $this->Client = ClassRegistry::init('Client'); + $this->Person = ClassRegistry::init('Person'); } /** @@ -433,6 +447,20 @@ public function testComplexTypeValidation() { $this->assertFalse($this->Link->validates()); } +/** + * testClassParentAssociations + * + * @link https://github.com/CakeDC/utils/issues/83 + * @return void + */ + public function testClassParentAssociations() { + $parentAssociations = array_flip($this->Person->getAssociated()); + $this->Client->Behaviors->load('Inheritable'); + $this->Client->Behaviors->Inheritable->classParentAssociations($this->Client->parent->primaryKey, 'hasOne', $parentAssociations); + $this->Client->Behaviors->unload('Inheritable'); + $this->assertTrue(isset($this->Client->Address)); + } + /** * Convenience function to assert Matches using Set::matches * diff --git a/Test/Fixture/AddressFixture.php b/Test/Fixture/AddressFixture.php new file mode 100644 index 0000000..aee58a7 --- /dev/null +++ b/Test/Fixture/AddressFixture.php @@ -0,0 +1,40 @@ + array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'person_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'direction' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * Records + * + * @var array + */ + public $records = array( + array( + 'id' => 1, + 'person_id' => 1, + 'direction' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'created' => '2015-07-08 23:12:27', + 'modified' => '2015-07-08 23:12:27' + ), + ); + +} \ No newline at end of file diff --git a/Test/Fixture/BankAccountFixture.php b/Test/Fixture/BankAccountFixture.php new file mode 100644 index 0000000..96b5685 --- /dev/null +++ b/Test/Fixture/BankAccountFixture.php @@ -0,0 +1,40 @@ + array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'client_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'number_account' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 50, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * Records + * + * @var array + */ + public $records = array( + array( + 'id' => 1, + 'client_id' => 1, + 'number_account' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-07-08 23:14:14', + 'modified' => '2015-07-08 23:14:14' + ), + ); + +} \ No newline at end of file diff --git a/Test/Fixture/ClientFixture.php b/Test/Fixture/ClientFixture.php new file mode 100644 index 0000000..a021a7d --- /dev/null +++ b/Test/Fixture/ClientFixture.php @@ -0,0 +1,42 @@ + array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'bank_account_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false), + 'number' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * Records + * + * @var array + */ + public $records = array( + array( + 'id' => 1, + 'parent_id' => 1, + 'bank_account_id' => 1, + 'number' => 1, + 'created' => '2015-07-08 23:15:03', + 'modified' => '2015-07-08 23:15:03' + ), + ); + +} \ No newline at end of file diff --git a/Test/Fixture/PersonFixture.php b/Test/Fixture/PersonFixture.php new file mode 100644 index 0000000..2caab7f --- /dev/null +++ b/Test/Fixture/PersonFixture.php @@ -0,0 +1,38 @@ + array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'), + 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 50, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'modified' => array('type' => 'datetime', 'null' => true, 'default' => null), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1) + ), + 'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB') + ); + +/** + * Records + * + * @var array + */ + public $records = array( + array( + 'id' => 1, + 'name' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-07-08 23:15:18', + 'modified' => '2015-07-08 23:15:18' + ), + ); + +} \ No newline at end of file