Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrating all model callbacks to the CakeEventManager, fixing some mi…
…nor bugs. All tests passing again
- Loading branch information
Showing
6 changed files
with
104 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,9 @@ | |
App::uses('ModelBehavior', 'Model'); | ||
App::uses('ConnectionManager', 'Model'); | ||
App::uses('Xml', 'Utility'); | ||
App::uses('CakeEvent', 'Event'); | ||
App::uses('CakeEventListener', 'Event'); | ||
App::uses('CakeEventManager', 'Event'); | ||
|
||
/** | ||
* Object-relational mapper. | ||
|
@@ -39,7 +42,7 @@ | |
* @package Cake.Model | ||
* @link http://book.cakephp.org/2.0/en/models.html | ||
*/ | ||
class Model extends Object { | ||
class Model extends Object implements CakeEventListener { | ||
|
||
/** | ||
* The name of the DataSource connection that this Model uses | ||
|
@@ -607,6 +610,14 @@ class Model extends Object { | |
'neighbors' => true, 'list' => true, 'threaded' => true | ||
); | ||
|
||
/** | ||
* Instance of the CakeEventManager this model is using | ||
* to dispatch inner events. | ||
* | ||
* @var CakeEventManager | ||
*/ | ||
protected $_eventManager = null; | ||
|
||
/** | ||
* Constructor. Binds the model's database table to the object. | ||
* | ||
|
@@ -712,6 +723,40 @@ public function __construct($id = false, $table = null, $ds = null) { | |
$this->Behaviors->init($this->alias, $this->actsAs); | ||
} | ||
|
||
/** | ||
* Returns a list of all events that will fire in the model during it's lifecycle. | ||
* You can override this function to add you own listener callbacks | ||
* | ||
* @return array | ||
*/ | ||
public function implementedEvents() { | ||
return array( | ||
'Model.beforeFind' => array('callable' => 'beforeFind', 'passParams' => true), | ||
'Model.afterFind' => array('callable' => 'afterFind', 'passParams' => true), | ||
'Model.beforeValidate' => array('callable' => 'beforeValidate', 'passParams' => true), | ||
'Model.beforeSave' => array('callable' => 'beforeSave', 'passParams' => true), | ||
'Model.afterSave' => array('callable' => 'afterSave', 'passParams' => true), | ||
'Model.beforeDelete' => array('callable' => 'beforeDelete', 'passParams' => true, 'priority' => 9), | ||
'Model.afterDelete' => array('callable' => 'afterDelete'), | ||
); | ||
} | ||
|
||
/** | ||
* Returns the CakeEventManager manager instance that is handling any callbacks. | ||
* You can use this instance to register any new listeners or callbacks to the | ||
* controller events, or create your own events and trigger them at will. | ||
* | ||
* @return CakeEventManager | ||
*/ | ||
public function getEventManager() { | ||
if (empty($this->_eventManager)) { | ||
$this->_eventManager = new CakeEventManager(); | ||
$this->_eventManager->attach($this->Behaviors); | ||
$this->_eventManager->attach($this); | ||
} | ||
return $this->_eventManager; | ||
} | ||
|
||
/** | ||
* Handles custom method calls, like findBy<field> for DB models, | ||
* and custom RPC calls for remote data sources. | ||
|
@@ -1585,10 +1630,10 @@ public function save($data = null, $validate = true, $fieldList = array()) { | |
} | ||
|
||
if ($options['callbacks'] === true || $options['callbacks'] === 'before') { | ||
$result = $this->Behaviors->trigger('beforeSave', array(&$this, $options), array( | ||
'break' => true, 'breakOn' => array(false, null) | ||
)); | ||
if (!$result || !$this->beforeSave($options)) { | ||
$event = new CakeEvent('Model.beforeSave', $this, array($options)); | ||
list($event->break, $event->breakOn) = array(true, array(false, null)); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
lorenzo
Author
Member
|
||
$this->getEventManager()->dispatch($event); | ||
if (!$event->result) { | ||
$this->whitelist = $_whitelist; | ||
return false; | ||
} | ||
|
@@ -1672,8 +1717,8 @@ public function save($data = null, $validate = true, $fieldList = array()) { | |
} | ||
} | ||
if ($options['callbacks'] === true || $options['callbacks'] === 'after') { | ||
$this->Behaviors->trigger('afterSave', array(&$this, $created, $options)); | ||
$this->afterSave($created); | ||
$event = new CakeEvent('Model.afterSave', $this, array($created, $options)); | ||
$this->getEventManager()->dispatch($event); | ||
} | ||
if (!empty($this->data)) { | ||
$success = Set::merge($success, $this->data); | ||
|
@@ -2236,13 +2281,11 @@ public function delete($id = null, $cascade = true) { | |
} | ||
$id = $this->id; | ||
|
||
if ($this->beforeDelete($cascade)) { | ||
$filters = $this->Behaviors->trigger( | ||
'beforeDelete', | ||
array(&$this, $cascade), | ||
array('break' => true, 'breakOn' => array(false, null)) | ||
); | ||
if (!$filters || !$this->exists()) { | ||
$event = new CakeEvent('Model.beforeDelete', $this, array($cascade)); | ||
list($event->break, $event->breakOn) = array(true, array(false, null)); | ||
$this->getEventManager()->dispatch($event); | ||
if (!$event->isStopped()) { | ||
if (!$this->exists()) { | ||
return false; | ||
} | ||
$db = $this->getDataSource(); | ||
|
@@ -2272,8 +2315,7 @@ public function delete($id = null, $cascade = true) { | |
if ($updateCounterCache) { | ||
$this->updateCounterCache($keys[$this->alias]); | ||
} | ||
$this->Behaviors->trigger('afterDelete', array(&$this)); | ||
$this->afterDelete(); | ||
$this->getEventManager()->dispatch(new CakeEvent('Model.afterDelete', $this)); | ||
$this->_clearCache(); | ||
$this->id = false; | ||
return true; | ||
|
@@ -2566,24 +2608,13 @@ public function buildQuery($type = 'first', $query = array()) { | |
$query['order'] = array($query['order']); | ||
|
||
if ($query['callbacks'] === true || $query['callbacks'] === 'before') { | ||
$return = $this->Behaviors->trigger( | ||
'beforeFind', | ||
array(&$this, $query), | ||
array('break' => true, 'breakOn' => array(false, null), 'modParams' => 1) | ||
); | ||
|
||
$query = (is_array($return)) ? $return : $query; | ||
|
||
if ($return === false) { | ||
return null; | ||
} | ||
|
||
$return = $this->beforeFind($query); | ||
$query = (is_array($return)) ? $return : $query; | ||
|
||
if ($return === false) { | ||
$event = new CakeEvent('Model.beforeFind', $this, array($query)); | ||
list($event->break, $event->breakOn, $event->modParams) = array(true, array(false, null), 0); | ||
$this->getEventManager()->dispatch($event); | ||
if ($event->isStopped()) { | ||
return null; | ||
} | ||
$query = $event->data[0]; | ||
} | ||
|
||
return $query; | ||
|
@@ -2814,15 +2845,10 @@ protected function _findThreaded($state, $query, $results = array()) { | |
* @return array Set of filtered results | ||
*/ | ||
protected function _filterResults($results, $primary = true) { | ||
$return = $this->Behaviors->trigger( | ||
'afterFind', | ||
array(&$this, $results, $primary), | ||
array('modParams' => 1) | ||
); | ||
if ($return !== true) { | ||
$results = $return; | ||
} | ||
return $this->afterFind($results, $primary); | ||
$event = new CakeEvent('Model.afterFind', $this, array($results, $primary)); | ||
$event->modParams = 0; | ||
$this->getEventManager()->dispatch($event); | ||
return $event->result; | ||
} | ||
|
||
/** | ||
|
@@ -2936,14 +2962,10 @@ public function validates($options = array()) { | |
* @see Model::validates() | ||
*/ | ||
public function invalidFields($options = array()) { | ||
if ( | ||
!$this->Behaviors->trigger( | ||
'beforeValidate', | ||
array(&$this, $options), | ||
array('break' => true, 'breakOn' => false) | ||
) || | ||
$this->beforeValidate($options) === false | ||
) { | ||
$event = new CakeEvent('Model.beforeValidate', $this, array($options)); | ||
list($event->break, $event->breakOn) = array(true, false); | ||
$this->getEventManager()->dispatch($event); | ||
if ($event->isStopped()) { | ||
return false; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Lorenzo,
If a behavior returns null from a
beforeSave()
(or neglects to return anything), this code appears to appears to stop other behaviors' beforeSave() functions running, but still allows the save to go ahead. Is that the intended outcome?