Skip to content

Commit

Permalink
Extracting loadInto implementation to another class
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Jun 28, 2015
1 parent b7a7106 commit ee658ba
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 66 deletions.
95 changes: 95 additions & 0 deletions src/ORM/LazyEagerLoader.php
@@ -0,0 +1,95 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.1.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\ORM;

use Cake\Collection\Collection;
use Cake\Database\Expression\TupleComparison;
use Cake\Datasource\EntityInterface;
use Cake\ORM\Table;


class LazyEagerLoader
{

public function loadInto($objects, array $contain, Table $source)
{
$returnSingle = false;

if ($objects instanceof EntityInterface) {
$objects = [$objects];
$returnSingle = true;
}

$objects = new Collection($objects);
$primaryKey = $source->primaryKey();
$method = is_string($primaryKey) ? 'get' : 'extract';

$keys = $objects->map(function ($entity) use ($primaryKey, $method) {
return $entity->{$method}($primaryKey);
});

$query = $source
->find()
->where(function ($exp) use ($primaryKey, $keys, $source) {
if (is_array($primaryKey) && count($primaryKey) === 1) {
$primaryKey = current($primaryKey);
}

if (is_string($primaryKey)) {
return $exp->in($source->aliasField($primaryKey), $keys->toList());
}

$primaryKey = array_map([$source, 'aliasField'], $primaryKey);
return new TupleComparison($primaryKey, $keys->toList());
})
->contain($contain);

$properties = (new Collection($source->associations()))
->indexBy(function ($assoc) {
return $assoc->name();
})
->map(function ($assoc) {
return $assoc->property();
})
->toArray();

$contain = $query->contain();
$primaryKey = (array)$primaryKey;
$results = $query
->indexBy(function ($e) use ($primaryKey) {
return implode(';', $e->extract($primaryKey));
})
->toArray();

$objects = $objects
->map(function ($object) use ($results, $contain, $properties, $primaryKey) {
$key = implode(';', $object->extract($primaryKey));
if (!isset($results[$key])) {
return $object;
}

$loaded = $results[$key];
foreach ($contain as $assoc => $config) {
$property = $properties[$assoc];
$object->set($property, $loaded->get($property), ['useSetters' => false]);
$object->dirty($property, false);
}
return $object;
});

return $returnSingle ? $objects->first() : $objects->toList();
}

}
67 changes: 1 addition & 66 deletions src/ORM/Table.php
Expand Up @@ -16,7 +16,6 @@

use ArrayObject;
use BadMethodCallException;
use Cake\Collection\Collection;
use Cake\Core\App;
use Cake\Database\Connection;
use Cake\Database\Schema\Table as Schema;
Expand Down Expand Up @@ -2184,71 +2183,7 @@ public function buildRules(RulesChecker $rules)

public function loadInto($objects, array $contain)
{
$returnSingle = false;

if ($objects instanceof EntityInterface) {
$objects = [$objects];
$returnSingle = true;
}

$objects = new Collection($objects);
$primaryKey = $this->primaryKey();
$method = is_string($primaryKey) ? 'get' : 'extract';

$keys = $objects->map(function ($entity) use ($primaryKey, $method) {
return $entity->{$method}($primaryKey);
});

$query = $this
->find()
->where(function ($exp) use ($primaryKey, $keys) {
if (is_array($primaryKey) && count($primaryKey) === 1) {
$primaryKey = current($primaryKey);
}

if (is_string($primaryKey)) {
return $exp->in($this->aliasField($primaryKey), $keys->toList());
}

$primaryKey = array_map([$this, 'aliasField'], $primaryKey);
return new \Cake\Database\Expression\TupleComparison($primaryKey, $keys->toList());
})
->contain($contain);

$properties = (new Collection($this->associations()))
->indexBy(function ($assoc) {
return $assoc->name();
})
->map(function ($assoc) {
return $assoc->property();
})
->toArray();

$contain = $query->contain();
$primaryKey = (array)$primaryKey;
$results = $query
->indexBy(function ($e) use ($primaryKey) {
return implode(';', $e->extract($primaryKey));
})
->toArray();

$objects = $objects
->map(function ($object) use ($results, $contain, $properties, $primaryKey) {
$key = implode(';', $object->extract($primaryKey));
if (!isset($results[$key])) {
return $object;
}

$loaded = $results[$key];
foreach ($contain as $assoc => $config) {
$property = $properties[$assoc];
$object->set($property, $loaded->get($property), ['useSetters' => false]);
$object->dirty($property, false);
}
return $object;
});

return $returnSingle ? $objects->first() : $objects->toList();
return (new LazyEagerLoader)->loadInto($objects, $contain, $this);
}

/**
Expand Down

0 comments on commit ee658ba

Please sign in to comment.