Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/cakephp/src/ORM/LazyEagerLoader.php
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         3.1.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\ORM;

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

/**
 * Contains methods that are capable of injecting eagerly loaded associations into
 * entities or lists of entities by using the same syntax as the EagerLoader.
 *
 * @internal
 */
class LazyEagerLoader
{
   
/**
     * Loads the specified associations in the passed entity or list of entities
     * by executing extra queries in the database and merging the results in the
     * appropriate properties.
     *
     * The properties for the associations to be loaded will be overwritten on each entity.
     *
     * @param \Cake\Datasource\EntityInterface|array $entities a single entity or list of entities
     * @param array $contain A `contain()` compatible array.
     * @see \Cake\ORM\Query::contain()
     * @param \Cake\ORM\Table $source The table to use for fetching the top level entities
     * @return \Cake\Datasource\EntityInterface|array
     */
   
public function loadInto($entities, array $contain, Table $source)
    {
       
$returnSingle = false;

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

       
$entities = new Collection($entities);
       
$query = $this->_getQuery($entities, $contain, $source);
       
$associations = array_keys($query->getContain());

       
$entities = $this->_injectResults($entities, $query, $associations, $source);

        return
$returnSingle ? array_shift($entities) : $entities;
    }

   
/**
     * Builds a query for loading the passed list of entity objects along with the
     * associations specified in $contain.
     *
     * @param \Cake\Collection\CollectionInterface $objects The original entities
     * @param array $contain The associations to be loaded
     * @param \Cake\ORM\Table $source The table to use for fetching the top level entities
     * @return \Cake\ORM\Query
     */
   
protected function _getQuery($objects, $contain, $source)
    {
       
$primaryKey = $source->getPrimaryKey();
       
$method = is_string($primaryKey) ? 'get' : 'extract';

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

       
/** @var \Cake\ORM\Query $query */
       
$query = $source
           
->find()
            ->
select((array)$primaryKey)
            ->
where(function ($exp, $q) use ($primaryKey, $keys, $source) {
                if (
is_array($primaryKey) && count($primaryKey) === 1) {
                   
$primaryKey = current($primaryKey);
                }

                if (
is_string($primaryKey)) {
                   
/** @var \Cake\Database\Expression\QueryExpression $exp */
                   
return $exp->in($source->aliasField($primaryKey), $keys->toList());
                }

               
/** @var \Cake\ORM\Query $q */
               
$types = array_intersect_key($q->getDefaultTypes(), array_flip($primaryKey));
               
$primaryKey = array_map([$source, 'aliasField'], $primaryKey);

                return new
TupleComparison($primaryKey, $keys->toList(), $types, 'IN');
            })
            ->
enableAutoFields()
            ->
contain($contain);

        foreach (
$query->getEagerLoader()->attachableAssociations($source) as $loadable) {
           
$config = $loadable->getConfig();
           
$config['includeFields'] = true;
           
$loadable->setConfig($config);
        }

        return
$query;
    }

   
/**
     * Returns a map of property names where the association results should be injected
     * in the top level entities.
     *
     * @param \Cake\ORM\Table $source The table having the top level associations
     * @param string[] $associations The name of the top level associations
     * @return array
     */
   
protected function _getPropertyMap($source, $associations)
    {
       
$map = [];
       
$container = $source->associations();
        foreach (
$associations as $assoc) {
           
$map[$assoc] = $container->get($assoc)->getProperty();
        }

        return
$map;
    }

   
/**
     * Injects the results of the eager loader query into the original list of
     * entities.
     *
     * @param \Cake\Datasource\EntityInterface[]|\Traversable $objects The original list of entities
     * @param \Cake\Collection\CollectionInterface|\Cake\Database\Query $results The loaded results
     * @param string[] $associations The top level associations that were loaded
     * @param \Cake\ORM\Table $source The table where the entities came from
     * @return array
     */
   
protected function _injectResults($objects, $results, $associations, $source)
    {
       
$injected = [];
       
$properties = $this->_getPropertyMap($source, $associations);
       
$primaryKey = (array)$source->getPrimaryKey();
       
$results = $results
           
->indexBy(function ($e) use ($primaryKey) {
               
/** @var \Cake\Datasource\EntityInterface $e */
               
return implode(';', $e->extract($primaryKey));
            })
            ->
toArray();

        foreach (
$objects as $k => $object) {
           
$key = implode(';', $object->extract($primaryKey));
            if (!isset(
$results[$key])) {
               
$injected[$k] = $object;
                continue;
            }

           
/** @var \Cake\Datasource\EntityInterface $loaded */
           
$loaded = $results[$key];
            foreach (
$associations as $assoc) {
               
$property = $properties[$assoc];
               
$object->set($property, $loaded->get($property), ['useSetters' => false]);
               
$object->setDirty($property, false);
            }
           
$injected[$k] = $object;
        }

        return
$injected;
    }
}