1<?php 2 3namespace dokuwiki\TreeBuilder; 4 5use dokuwiki\TreeBuilder\Node\AbstractNode; 6use dokuwiki\TreeBuilder\Node\WikiNamespace; 7use dokuwiki\Utf8\Sort; 8 9/** 10 * Class that provides comparators for sorting the tree nodes 11 */ 12class TreeSort 13{ 14 public const SORT_BY_ID = [self::class, 'sortById']; 15 public const SORT_BY_TITLE = [self::class, 'sortByTitle']; 16 public const SORT_BY_NS_FIRST_THEN_ID = [self::class, 'sortByNsFirstThenId']; 17 public const SORT_BY_NS_FIRST_THEN_TITLE = [self::class, 'sortByNsFirstThenTitle']; 18 19 /** 20 * Comparator to sort by ID 21 * 22 * @param AbstractNode $a 23 * @param AbstractNode $b 24 * @return int 25 */ 26 public static function sortById(AbstractNode $a, AbstractNode $b): int 27 { 28 // we need to compare the ID segment by segment 29 $pathA = explode(':', $a->getId()); 30 $pathB = explode(':', $b->getId()); 31 $min = min(count($pathA), count($pathB)); 32 33 for ($i = 0; $i < $min; $i++) { 34 if ($pathA[$i] !== $pathB[$i]) { 35 return $pathA[$i] <=> $pathB[$i]; 36 } 37 } 38 return count($pathA) <=> count($pathB); 39 } 40 41 42 /** 43 * Comparator to sort namespace first, then by ID 44 * 45 * @param AbstractNode $a 46 * @param AbstractNode $b 47 * @return int 48 */ 49 public static function sortByNsFirstThenId(AbstractNode $a, AbstractNode $b): int 50 { 51 $res = self::sortByNsFirst($a, $b); 52 if ($res === 0) $res = self::sortById($a, $b); 53 return $res; 54 } 55 56 /** 57 * Comparator to sort by title (using natural sort) 58 * 59 * @param AbstractNode $a 60 * @param AbstractNode $b 61 * @return int 62 */ 63 public static function sortByTitle(AbstractNode $a, AbstractNode $b): int 64 { 65 return Sort::strcmp($a->getTitle(), $b->getTitle()); 66 } 67 68 /** 69 * Comparator to sort namespace first, then by title 70 * 71 * @param AbstractNode $a 72 * @param AbstractNode $b 73 * @return int 74 */ 75 public static function sortByNsFirstThenTitle(AbstractNode $a, AbstractNode $b): int 76 { 77 $res = self::sortByNsFirst($a, $b); 78 if ($res === 0) $res = self::sortByTitle($a, $b); 79 return $res; 80 } 81 82 /** 83 * Comparator to sort by namespace first 84 * 85 * @param AbstractNode $a 86 * @param AbstractNode $b 87 * @return int 88 */ 89 protected static function sortByNsFirst(AbstractNode $a, AbstractNode $b): int 90 { 91 $isAaNs = ($a instanceof WikiNamespace); 92 $isBaNs = ($b instanceof WikiNamespace); 93 94 if ($isAaNs !== $isBaNs) { 95 if ($isAaNs) { 96 return -1; 97 } elseif ($isBaNs) { 98 return 1; 99 } 100 } 101 return 0; 102 } 103} 104