Open Journal Systems  3.3.0
Sort.php
1 <?php
2 /*
3  * citeproc-php
4  *
5  * @link http://github.com/seboettg/citeproc-php for the source repository
6  * @copyright Copyright (c) 2016 Sebastian Böttger.
7  * @license https://opensource.org/licenses/MIT
8  */
9 
11 
18 use SimpleXMLElement;
19 
34 class Sort
35 {
41  private $sortingKeys;
42 
46  public function __construct(SimpleXMLElement $node)
47  {
48  $this->sortingKeys = new ArrayList();
50  foreach ($node->children() as $child) {
51  if ("key" === $child->getName()) {
52  $this->sortingKeys->append(new Key($child));
53  }
54  }
55  }
56 
67  public function sort(&$data)
68  {
69  if (is_array($data)) {
70  $data = new DataList($data);
71  }
72  $dataToSort = $data->toArray();
73  try {
74  $data->replace($this->performSort(0, $dataToSort));
75  } catch (CiteProcException $e) {
76  //nothing to do, because $data is passed by referenced
77  }
78  }
79 
91  private function performSort($keyNumber, $dataToSort)
92  {
93  if (count($dataToSort) < 2) {
94  return $dataToSort;
95  }
96 
98  $key = $this->sortingKeys->get($keyNumber);
99  $variable = $key->getVariable();
100  $groupedItems = [];
101 
102  if ($key->isDateVariable()) {
103  if (DateHelper::hasDateRanges($dataToSort, $variable, "all")) {
104  $newKey = clone $key;
105  $newKey->setRangePart(2);
106  $key->setRangePart(1);
107  $this->sortingKeys->append($newKey);
108  }
109  }
110 
111  //grouping by value
112  foreach ($dataToSort as $citationNumber => $dataItem) {
113  if ($key->isNameVariable()) {
114  $sortKey = Variables::nameHash($dataItem, $variable);
115  } elseif ($key->isNumberVariable()) {
116  $sortKey = $dataItem->{$variable};
117  } elseif ($key->isDateVariable()) {
118  $sortKey = DateHelper::getSortKeyDate($dataItem, $key);
119  } elseif ($key->isMacro()) {
120  $sortKey = mb_strtolower(strip_tags(CiteProc::getContext()->getMacro(
121  $key->getMacro()
122  )->render($dataItem, $citationNumber)));
123  } elseif ($variable === "citation-number") {
124  $sortKey = $citationNumber + 1;
125  } else {
126  $sortKey = mb_strtolower(strip_tags($dataItem->{$variable}));
127  }
128  $groupedItems[$sortKey][] = $dataItem;
129  }
130 
131  if ($this->sortingKeys->count() > ++$keyNumber) {
132  foreach ($groupedItems as $group => &$array) {
133  if (count($array) > 1) {
134  $array = $this->performSort($keyNumber, $array);
135  }
136  }
137  }
138 
139  //sorting by array keys
140  if ($key->getSort() === "ascending") {
141  ksort($groupedItems); //ascending
142  } else {
143  krsort($groupedItems); //reverse
144  }
145 
146  //the flattened array is the result
147  $sortedDataGroups = array_values($groupedItems);
148  return $this->flatten($sortedDataGroups);
149  }
150 
151  public function flatten($array)
152  {
153  $returnArray = [];
154  array_walk_recursive($array, function ($a) use (&$returnArray) {
155  $returnArray[] = $a;
156  });
157  return $returnArray;
158  }
159 
163  public function getSortingKeys()
164  {
165  return $this->sortingKeys;
166  }
167 }
Seboettg\CiteProc\Util\DateHelper
Definition: DateHelper.php:26
Seboettg\Collection\flatten
flatten()
Definition: ArrayListTrait.php:306
Seboettg\CiteProc\CiteProc
Definition: CiteProc.php:32
Seboettg\CiteProc\Util\Variables\nameHash
static nameHash(stdClass $data, $variable)
Definition: Variables.php:164
Seboettg\Collection\count
count()
Definition: ArrayListTrait.php:253
Seboettg\CiteProc\Exception\CiteProcException
Definition: CiteProcException.php:20
Seboettg\CiteProc\Util\Variables
Definition: Variables.php:25
Seboettg\CiteProc\Data\DataList
Definition: DataList.php:22
Seboettg\CiteProc\Style\Sort\Sort\getSortingKeys
getSortingKeys()
Definition: Sort.php:166
Seboettg\CiteProc\CiteProc\getContext
static getContext()
Definition: CiteProc.php:45
Seboettg\CiteProc\Style\Sort\Sort\flatten
flatten($array)
Definition: Sort.php:154
Seboettg\CiteProc\Style\Sort\Key
Definition: Key.php:30
Seboettg\CiteProc\Util\DateHelper\hasDateRanges
static hasDateRanges($items, $variable, $match="all")
Definition: DateHelper.php:104
Seboettg\CiteProc\Style\Sort\Sort\__construct
__construct(SimpleXMLElement $node)
Definition: Sort.php:49
Seboettg\Collection\ArrayList
Definition: ArrayList.php:20
Seboettg\CiteProc\Style\Sort\Sort\sort
sort(&$data)
Definition: Sort.php:70
Seboettg\CiteProc\Style\Sort\Sort
Definition: Sort.php:34
Seboettg\CiteProc\Style\Sort
Definition: Key.php:10
Seboettg\CiteProc\Util\DateHelper\getSortKeyDate
static getSortKeyDate($dataItem, $key)
Definition: DateHelper.php:75