mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 11:28:25 +00:00
Adding Set::sort(), for sorting model results by association keys, tests included
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6412 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
39940856b8
commit
4e56b06f66
2 changed files with 142 additions and 2 deletions
|
@ -355,8 +355,10 @@ class Set extends Object {
|
|||
return $out;
|
||||
}
|
||||
/**
|
||||
* Gets a value from an array or object that maps a given path.
|
||||
* The special {n}, as seen in the Model::generateList method, is taken care of here.
|
||||
* Gets a value from an array or object that is contained in a given path using an array path syntax, i.e.:
|
||||
* "{n}.Person.{[a-z]+}" - Where "{n}" represents a numeric key, "Person" represents a string literal,
|
||||
* and "{[a-z]+}" (i.e. any string literal enclosed in brackets besides {n} and {s}) is interpreted as
|
||||
* a regular expression.
|
||||
*
|
||||
* @param array $data Array from where to extract
|
||||
* @param mixed $path As an array, or as a dot-separated string.
|
||||
|
@ -852,5 +854,53 @@ class Set extends Object {
|
|||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Flattens an array for sorting
|
||||
*
|
||||
* @param array $results
|
||||
* @param string $key
|
||||
* @return array
|
||||
* @access private
|
||||
*/
|
||||
function __flatten($results, $key = null) {
|
||||
$stack = array();
|
||||
foreach ($results as $k => $r) {
|
||||
if (is_array($r)) {
|
||||
$stack = am($stack, Set::__flatten($r, $k));
|
||||
} else {
|
||||
if (!$key) {
|
||||
$key = $k;
|
||||
}
|
||||
$stack[] = array('id' => $key, 'value' => $r);
|
||||
}
|
||||
}
|
||||
return $stack;
|
||||
}
|
||||
/**
|
||||
* Sorts an array by any value, determined by a Set-compatible path
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $path A Set-compatible path to the array value
|
||||
* @param string $dir asc/desc
|
||||
* @return array
|
||||
*/
|
||||
function sort($data, $path, $dir) {
|
||||
$result = Set::__flatten(Set::extract($data, $path));
|
||||
list($keys, $values) = array(Set::extract($result, '{n}.id'), Set::extract($result, '{n}.value'));
|
||||
|
||||
if ($dir == 'asc') {
|
||||
$dir = SORT_ASC;
|
||||
} elseif ($dir == 'desc') {
|
||||
$dir = SORT_DESC;
|
||||
}
|
||||
array_multisort($values, $dir, $keys, $dir);
|
||||
$sorted = array();
|
||||
|
||||
foreach ($keys as $k) {
|
||||
$sorted[] = $data[$k];
|
||||
}
|
||||
return $sorted;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -132,6 +132,46 @@ class SetTest extends UnitTestCase {
|
|||
$this->assertIdentical(Set::normalize(Set::merge($a, $b)), $expected);
|
||||
}
|
||||
|
||||
function testSort() {
|
||||
// ascending
|
||||
$a = array(
|
||||
0 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))),
|
||||
1 => array('Person' => array('name' => 'Tracy'),'Friend' => array(array('name' => 'Lindsay')))
|
||||
);
|
||||
$b = array(
|
||||
0 => array('Person' => array('name' => 'Tracy'),'Friend' => array(array('name' => 'Lindsay'))),
|
||||
1 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')))
|
||||
|
||||
);
|
||||
$a = Set::sort($a, '{n}.Friend.{n}.name', 'asc');
|
||||
$this->assertIdentical($a, $b);
|
||||
|
||||
// descending
|
||||
$b = array(
|
||||
0 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))),
|
||||
1 => array('Person' => array('name' => 'Tracy'),'Friend' => array(array('name' => 'Lindsay')))
|
||||
);
|
||||
$a = array(
|
||||
0 => array('Person' => array('name' => 'Tracy'),'Friend' => array(array('name' => 'Lindsay'))),
|
||||
1 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')))
|
||||
|
||||
);
|
||||
$a = Set::sort($a, '{n}.Friend.{n}.name', 'desc');
|
||||
$this->assertIdentical($a, $b);
|
||||
|
||||
// if every element doesn't have the matching key, the one without is compared as empty
|
||||
$a = array(
|
||||
0 => array('Person' => array('name' => 'Jeff')),
|
||||
1 => array('Shirt' => array('color' => 'black'))
|
||||
);
|
||||
$b = array(
|
||||
0 => array('Shirt' => array('color' => 'black')),
|
||||
1 => array('Person' => array('name' => 'Jeff')),
|
||||
);
|
||||
$a = Set::sort($a, '{n}.Person.name', 'asc');
|
||||
$this->assertIdentical($a, $b);
|
||||
}
|
||||
|
||||
function testExtract() {
|
||||
$a = array(
|
||||
array('Article' => array('id' => 1, 'title' => 'Article 1')),
|
||||
|
@ -978,5 +1018,55 @@ class SetTest extends UnitTestCase {
|
|||
$expected = array('Data' => array('Post' => array('title' => 'Title of this post', 'description' => 'cool')));
|
||||
$this->assertEqual($result, $expected);
|
||||
}
|
||||
|
||||
function __flatten($results, $key = null) {
|
||||
$stack = array();
|
||||
foreach ($results as $k => $r) {
|
||||
if (is_array($r)) {
|
||||
$stack = am($stack, Set::__flatten($r, $k));
|
||||
} else {
|
||||
if (!$key) {
|
||||
$key = $k;
|
||||
}
|
||||
$stack[] = array(
|
||||
'id' => $key,
|
||||
'value' => $r
|
||||
);
|
||||
}
|
||||
}
|
||||
return $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts an array by any value, determined by a Set-compatible path
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $path A Set-compatible path to the array value
|
||||
* @param string $dir asc/desc
|
||||
* @return unknown
|
||||
*/
|
||||
function sort($data, $path, $dir) {
|
||||
|
||||
$result = Set::extract($data, $path);
|
||||
$result = Set::__flatten($result);
|
||||
$keys = Set::extract($result, '{n}.id');
|
||||
$values = Set::extract($result, '{n}.value');
|
||||
|
||||
if ($dir == 'asc') {
|
||||
$dir = SORT_ASC;
|
||||
}
|
||||
if ($dir == 'desc') {
|
||||
$dir = SORT_DESC;
|
||||
}
|
||||
|
||||
array_multisort($values, $dir, $keys, $dir);
|
||||
|
||||
$sorted = array();
|
||||
foreach ($keys as $k) {
|
||||
$sorted[] = $data[$k];
|
||||
}
|
||||
return $sorted;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
Loading…
Reference in a new issue