Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Moving beforeFind to the Query class
This allows listeners to have as much information as possible before
before acting. This also allows to carerctly stack finders without
firing beforeFind callback per each finder that is stacked
  • Loading branch information
lorenzo committed Sep 1, 2013
1 parent 87b2f4b commit cebe72c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 11 deletions.
33 changes: 33 additions & 0 deletions lib/Cake/ORM/Query.php
Expand Up @@ -16,6 +16,7 @@
*/
namespace Cake\ORM;

use Cake\Event\Event;
use Cake\Database\Query as DatabaseQuery;
use Cake\Database\Statement\BufferedStatement;
use Cake\Database\Statement\CallbackStatement;
Expand Down Expand Up @@ -108,6 +109,14 @@ class Query extends DatabaseQuery {
*/
protected $_mapReduce = [];

/**
* Holds any custom options passed using applyOptions that could not be processed
* by any method in this class.
*
* @var array
*/
protected $_options = [];

/**
* @param Cake\Database\Connection $connection
* @param Cake\ORM\Table $table
Expand Down Expand Up @@ -386,6 +395,9 @@ public function setResult($results) {
* @return Cake\ORM\ResultCollectionTrait
*/
public function execute() {
$table = $this->repository();
$event = new Event('Model.beforeFind', $table, [$this, $this->_options]);
$table->getEventManager()->dispatch($event);
if (isset($this->_results)) {
return $this->_results;
}
Expand Down Expand Up @@ -522,12 +534,33 @@ public function applyOptions(array $options) {
foreach ($options as $option => $values) {
if (isset($valid[$option])) {
$this->{$valid[$option]}($values);
} else {
$this->_options[$option] = $values;
}
}

return $this;
}

/**
* Returns an array with the custom options that where applied to this query
* and that were not already processed by another method in this class.
*
* ###Example:
*
* {{{
* $query->applyOptions(['doABarrelRoll' => true, 'fields' => ['id', 'name']);
* $query->getOptions(); // Returns ['doABarrelRoll' => true]
* }}}
*
* @see \Cake\ORM\Query::applyOptions() to read about the options that will
* be processed by this class and not returned by this function
* @return array
*/
public function getOptions() {
return $this->_options;
}

/**
* Register a new MapReduce routine to be executed on top of the database results
* Both the mapper and caller callable should be invokable objects.
Expand Down
13 changes: 2 additions & 11 deletions lib/Cake/ORM/Table.php
Expand Up @@ -16,9 +16,8 @@
*/
namespace Cake\ORM;

use Cake\Database\Schema\Table as Schema;
use Cake\Event\Event;
use Cake\Event\EventManager;
use Cake\Database\Schema\Table as Schema;
use Cake\ORM\Association\BelongsTo;
use Cake\ORM\Association\BelongsToMany;
use Cake\ORM\Association\HasMany;
Expand Down Expand Up @@ -492,9 +491,7 @@ public function belongsToMany($associated, array $options = []) {
* ### Model.beforeFind event
*
* Each find() will trigger a `Model.beforeFind` event for all attached
* listeners. Any listener can stop the event to prevent the default
* find handler from being called. When a find() is stopped the Query
* object will still be returned.
* listeners. Any listener can set a valid result set using $query
*
* @param string $type the type of query to perform
* @param array $options
Expand All @@ -503,12 +500,6 @@ public function belongsToMany($associated, array $options = []) {
public function find($type, $options = []) {
$query = $this->_buildQuery();
$query->select()->applyOptions($options);

$event = new Event('Model.beforeFind', $this, [$query, $options]);
$this->_eventManager->dispatch($event);
if ($event->isStopped()) {
return $query;
}
return $this->{'find' . ucfirst($type)}($query, $options);
}

Expand Down
17 changes: 17 additions & 0 deletions lib/Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -903,6 +903,23 @@ public function testApplyOptions() {
$this->assertEquals($expected, $query->contain());
}

/**
* Tests getOptions() method
*
* @return void
*/
public function testGetOptions() {
$options = ['doABarrelRoll' => true, 'fields' => ['id', 'name']];
$query = new Query($this->connection, $this->table);
$query->applyOptions($options);
$expected = ['doABarrelRoll' => true];
$this->assertEquals($expected, $query->getOptions());

$expected = ['doABarrelRoll' => false, 'doAwesome' => true];
$query->applyOptions($expected);
$this->assertEquals($expected, $query->getOptions());
}

/**
* Tests registering mappers with mapReduce()
*
Expand Down

0 comments on commit cebe72c

Please sign in to comment.