Skip to content

Instantly share code, notes, and snippets.

@redoPop
Created April 28, 2011 13:48
Show Gist options
  • Save redoPop/946379 to your computer and use it in GitHub Desktop.
Save redoPop/946379 to your computer and use it in GitHub Desktop.
CakePHP Behavior that makes ContainableBehavior respect a Model's default order
<?php
/**
* Behavior to enhance CakePHP ContainableBehavior by respecting default Model order
*
* Makes ContainableBehavior respect Model::order when no other order is specified in
* the containment. Must be placed before ContainableBehavior in the actsAs array of
* the Model being queried, like so:
*
* var $actsAs = array('OrderedContainable', 'Containable');
*
* @author joe bartlett (xo@jdbartlett.com)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
* @package OrderedContainableBehavior
*/
class OrderedContainableBehavior extends ModelBehavior {
/**
* Runs before a Model::find() operation. Examines the query's containments
* and supplements them with each Model's default order property if no other
* is set.
*
* @param object $Model Model using this ModelBehavior
* @param array $query Query parameters
* @return array
* @access public
*/
public function beforeFind(&$Model, $query) {
if (!empty($query['contain'])) {
$query['contain'] = (array)$query['contain'];
$containments = $Model->Behaviors->Containable->containments($Model, $query['contain']);
$containmentModelNames = array_keys($containments['models']);
$this->__addOrdersToContainments($Model, $query['contain'], $containmentModelNames);
}
return $query;
}
/**
* Called by ::beforeFind() to recursively examine a containment and add
* order information where appropriate.
*
* @param object $Model Model $contain applies to
* @param array $contain Containment from the query being examined
* @param array $containmentModelNames List of Model names contained in the query
* @access private
*/
private function __addOrdersToContainments(&$Model, &$contain, &$containmentModelNames) {
foreach ($contain as $modelName => $containment) {
if (!is_array($containment) && in_array($containment, $containmentModelNames)) {
unset($contain[$modelName]);
$contain[$containment] = array();
}
}
foreach ($contain as $modelName => &$containment) {
if (is_array($containment) && in_array($modelName, $containmentModelNames)) {
if (!array_key_exists('order', $containment) && !empty($Model->$modelName->order)) {
$containment['order'] = $Model->$modelName->order;
}
$lookDeeper = FALSE;
foreach ($containmentModelNames as $containmentModelName) {
if (in_array($containmentModelName, $containment)) {
$lookDeeper = TRUE;
break;
}
if (array_key_exists($containmentModelName, $containment)) {
$lookDeeper = TRUE;
break;
}
}
if ($lookDeeper) {
$this->__addOrdersToContainments($Model->$modelName, $containment, $containmentModelNames);
}
}
}
}
}
@josegonzalez
Copy link

You can fork the cake core, add your patches, add test cases, and then issue a pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment