-
Notifications
You must be signed in to change notification settings - Fork 0
/
Neighbors.php
58 lines (50 loc) · 1.67 KB
/
Neighbors.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
/**
* Copyright 2014 David Persson. All rights reserved.
* Copyright 2016 Atelier Disko. All rights reserved.
*
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
namespace base_core\extensions\data\behavior;
use Exception;
use li3_behaviors\data\model\Behavior;
use lithium\data\Entity;
class Neighbors extends \li3_behaviors\data\model\Behavior {
// Retrieves the next and previous record, surrounding the current one.
//
// An order and direction should be given in query, use DESC direction for
// date fields, so that next is newer and prev is older.
//
// FIXME This is a naive implemetation. Better:
// http://stackoverflow.com/questions/12293115/how-to-select-rows-surrounding-a-row-not-by-id
public function neighbors($model, Behavior $behavior, Entity $entity, array $query = array()) {
$next = $prev = null;
// Do not rely on 'indexed' => false feature as we may get a regular collection as
// a result. In general this should not be the case, but `Aggregated` behavior does.
$results = array_values($model::find('all', [
'fields' => ['id']
] + $query)->to('array', ['indexed' => false]));
foreach ($results as $key => $result) {
if ($result['id'] != $entity->id) {
continue;
}
if (isset($results[$key + 1])) {
$prev = $results[$key + 1]['id'];
}
if (isset($results[$key - 1])) {
$next = $results[$key - 1]['id'];
}
break;
}
return [
'prev' => $prev ? $model::find('first', [
'conditions' => ['id' => $prev]
] + $query) : false,
'next' => $next ? $model::find('first', [
'conditions' => ['id' => $next]
] + $query) : false
];
}
}
?>