Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/friendsofcake/crud/src/Listener/RelatedModelsListener.php
<?php
namespace Crud\Listener;

use
Cake\Event\Event;
use
Cake\ORM\Association;
use
Cake\Utility\Inflector;
use
RuntimeException;

/**
 * Implements beforeRender event listener to set related models' lists to
 * the view
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 */
class RelatedModelsListener extends BaseListener
{

   
/**
     * Returns a list of events this listener is interested in.
     *
     * @return array
     */
   
public function implementedEvents()
    {
        return [
           
'Crud.beforePaginate' => 'beforePaginate',
           
'Crud.beforeRender' => 'beforeRender',
        ];
    }

   
/**
     * Automatically parse and contain related table classes
     *
     * @param \Cake\Event\Event $event Before paginate event
     * @return void
     */
   
public function beforePaginate(Event $event)
    {
       
$method = 'contain';
        if (
method_exists($event->getSubject()->query, 'getContain')) {
           
$method = 'getContain';
        }
       
$contained = $event->getSubject()->query->$method();

        if (!empty(
$contained)) {
            return;
        }

       
$models = $this->models();
        if (empty(
$models)) {
            return;
        }

       
$event->getSubject()->query->contain(array_keys($models));
    }

   
/**
     * Fetches related models' list and sets them to a variable for the view
     *
     * @param Event $event Event
     * @return void
     * @codeCoverageIgnore
     */
   
public function beforeRender(Event $event)
    {
       
$entity = null;
        if (isset(
$event->getSubject()->entity)) {
           
$entity = $event->getSubject()->entity;
        }
       
$this->publishRelatedModels(null, $entity);
    }

   
/**
     * Find and publish all related models to the view
     * for an action
     *
     * @param null|string $action If NULL the current action will be used
     * @param null|\Cake\ORM\Entity $entity The optional entity for which we we trying to find related
     * @return void
     */
   
public function publishRelatedModels($action = null, $entity = null)
    {
       
$models = $this->models($action);

        if (empty(
$models)) {
            return;
        }

       
$controller = $this->_controller();

        foreach (
$models as $name => $association) {
            list(,
$associationName) = pluginSplit($association->getName());
           
$viewVar = Inflector::variable($associationName);
            if (
array_key_exists($viewVar, $controller->viewVars)) {
                continue;
            }

           
$finder = $this->finder($association);
           
$query = $association->find()->find($finder, $this->_findOptions($association));
           
$subject = $this->_subject(compact('name', 'viewVar', 'query', 'association', 'entity'));
           
$event = $this->_trigger('relatedModel', $subject);

           
$controller->set($event->getSubject()->viewVar, $event->getSubject()->query->toArray());
        }
    }

   
/**
     * Find keyField and valueField for find('list')
     *
     * This is useful for cases where the relation has a different binding key
     * than the primary key in the associated table (e.g. NOT 'id')
     *
     * @param Association $association The association that we process
     * @return array
     */
   
protected function _findOptions(Association $association)
    {
        return [
           
'keyField' => $association->getBindingKey(),
        ];
    }

   
/**
     * Get finder to use for provided association.
     *
     * @param \Cake\ORM\Association $association Association instance
     * @return string
     */
   
public function finder(Association $association)
    {
        if (
$association->getTarget()->behaviors()->has('Tree')) {
            return
'treeList';
        }

        return
'list';
    }

   
/**
     * Gets the list of associated model lists to be fetched for an action
     *
     * @param string|null $action name of the action
     * @return array
     */
   
public function models($action = null)
    {
       
$settings = $this->relatedModels(null, $action);

        if (
$settings === true) {
            return
$this->getAssociatedByType(['oneToOne', 'manyToMany', 'manyToOne']);
        }

        if (empty(
$settings)) {
            return [];
        }

        if (
is_string($settings)) {
           
$settings = [$settings];
        }

        return
$this->getAssociatedByName($settings);
    }

   
/**
     * Set or get the related models that should be found
     * for the action
     *
     * @param mixed $related Everything but `null` will change the configuration
     * @param string|null $action The action to configure
     * @return mixed
     */
   
public function relatedModels($related = null, $action = null)
    {
        if (
$related === null) {
            return
$this->_action($action)->getConfig('relatedModels');
        }

        return
$this->_action($action)->setConfig('relatedModels', $related, false);
    }

   
/**
     * Get associated tables based on the current table instance based on their
     * association type
     *
     * @param array $types Association types
     * @return array
     */
   
public function getAssociatedByType($types = [])
    {
       
$return = [];

       
$table = $this->_table();
        foreach (
$table->associations()->keys() as $association) {
           
$associationClass = $table->associations()->get($association);
            if (!
in_array($associationClass->type(), $types)) {
                continue;
            }

           
$return[$associationClass->getName()] = $associationClass;
        }

        return
$return;
    }

   
/**
     * Get associated tables based on the current table instance based on their
     * association name
     *
     * @param array $names Association names
     * @return array
     * @throws \RuntimeException when association not found.
     */
   
public function getAssociatedByName($names)
    {
       
$return = [];

       
$table = $this->_table();
        foreach (
$names as $association) {
           
$associationClass = $table->associations()->get($association);
            if (!
$associationClass) {
                throw new
RuntimeException(sprintf(
                   
'Table "%s" is not associated with "%s"',
                   
get_class($table),
                   
$association
               
));
            }
           
$return[$associationClass->getName()] = $associationClass;
        }

        return
$return;
    }
}