1<?php 2/** 3 * Plugin nspages : Displays nicely a list of the pages of a namespace 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 */ 7 8if(!defined('DOKU_INC')) die(); 9require_once 'printer.php'; 10require_once 'rendererXhtmlHelper.php'; 11 12use dokuwiki\Utf8\PhpString; 13 14class nspages_printerNice extends nspages_printer { 15 private $nbCols; 16 private $anchorName; 17 18 function __construct($plugin, $mode, $renderer, $nbCols, $anchorName, $data){ 19 parent::__construct($plugin, $mode, $renderer, $data); 20 if ( $this->mode !== 'xhtml' ){ 21 throw Exception('nspages_printerNice can only work in xhtml mode'); 22 } 23 $this->nbCols = $this->_computeActualNbCols($nbCols); 24 $this->anchorName = $anchorName; 25 } 26 27 private function _computeActualNbCols($nbCols){ 28 $nbCols = (int) $nbCols; 29 if(!isset($nbCols) || is_null($nbCols) || $nbCols < 1) { 30 $nbCols = 3; 31 } 32 return $nbCols; 33 } 34 35 function _print($tab, $type) { 36 $nbItemsPrinted = 0; 37 38 $nbItemPerColumns = $this->_computeNbItemPerColumns(sizeof($tab)); 39 $actualNbCols = count($nbItemPerColumns); 40 $helper = new rendererXhtmlHelper($this->renderer, $actualNbCols, $this->plugin, $this->anchorName); 41 42 $helper->openColumn(); 43 $firstCharOfLastAddedPage = $this->_firstChar($tab[0]); 44 45 $helper->printHeaderChar($firstCharOfLastAddedPage); 46 $helper->openListOfItems(); 47 48 $idxCol = 0; 49 foreach($tab as $item) { 50 //change to the next column if necessary 51 if($nbItemsPrinted == $nbItemPerColumns[$idxCol]) { 52 $idxCol++; 53 $helper->closeListOfItems(); 54 $helper->closeColumn(); 55 $helper->openColumn(); 56 57 $newLetter = $this->_firstChar($item); 58 if($newLetter != $firstCharOfLastAddedPage) { 59 $firstCharOfLastAddedPage = $newLetter; 60 $helper->printHeaderChar($firstCharOfLastAddedPage); 61 } else { 62 $helper->printHeaderChar($firstCharOfLastAddedPage, true); 63 } 64 $helper->openListOfItems(); 65 } 66 67 $newLetter = $this->_firstChar($item); 68 if($newLetter != $firstCharOfLastAddedPage) { 69 $firstCharOfLastAddedPage = $newLetter; 70 $helper->closeListOfItems(); 71 $helper->printHeaderChar($firstCharOfLastAddedPage); 72 $helper->openListOfItems(); 73 } 74 75 $this->_printElement($item); 76 $nbItemsPrinted++; 77 } 78 $helper->closeListOfItems(); 79 $helper->closeColumn(); 80 } 81 82 private function _firstChar($item) { 83 $return_char = PhpString::strtoupper(PhpString::substr($item['sort'], 0, 1)); 84 $uniord_char = $this->_uniord($return_char); 85 86 // korean support. See #111 for more context 87 if ($uniord_char > 44031 && $uniord_char < 55204) { 88 $return_char = ['ㄱ','ㄱ','ㄴ','ㄷ','ㄷ','ㄹ','ㅁ','ㅂ','ㅂ','ㅅ','ㅅ','ㅇ','ㅈ','ㅈ','ㅊ','ㅋ','ㅌ','ㅍ','ㅎ'][($uniord_char-44032)/588]; 89 } 90 91 return $return_char; 92 } 93 94 /** 95 * This code is from: 96 * https://stackoverflow.com/questions/9361303/ 97 */ 98 private function _uniord($c) { 99 if (ord($c[0]) >=0 && ord($c[0]) <= 127) 100 return ord($c[0]); 101 if (ord($c[0]) >= 192 && ord($c[0]) <= 223) 102 return (ord($c[0])-192)*64 + (ord($c[1])-128); 103 if (ord($c[0]) >= 224 && ord($c[0]) <= 239) 104 return (ord($c[0])-224)*4096 + (ord($c[1])-128)*64 + (ord($c[2])-128); 105 if (ord($c[0]) >= 240 && ord($c[0]) <= 247) 106 return (ord($c[0])-240)*262144 + (ord($c[1])-128)*4096 + (ord($c[2])-128)*64 + (ord($c[3])-128); 107 if (ord($c[0]) >= 248 && ord($c[0]) <= 251) 108 return (ord($c[0])-248)*16777216 + (ord($c[1])-128)*262144 + (ord($c[2])-128)*4096 + (ord($c[3])-128)*64 + (ord($c[4])-128); 109 if (ord($c[0]) >= 252 && ord($c[0]) <= 253) 110 return (ord($c[0])-252)*1073741824 + (ord($c[1])-128)*16777216 + (ord($c[2])-128)*262144 + (ord($c[3])-128)*4096 + (ord($c[4])-128)*64 + (ord($c[5])-128); 111 if (ord($c[0]) >= 254 && ord($c[0]) <= 255) 112 return false; 113 return false; 114 } 115 116 /** 117 * Compute the number of element to display per column 118 * When $nbItems / $nbCols isn't an int, we make sure, for aesthetic reasons, 119 * that the first are the ones which have the more items 120 * Moreover, if we don't have enought items to display, we may choose to display less than the number of columns wanted 121 * 122 * @param int $nbItems The total number of items to display 123 * @return an array which contains $nbCols int. 124 */ 125 private function _computeNbItemPerColumns($nbItems) { 126 $result = array(); 127 128 if($nbItems < $this->nbCols) { 129 for($idx = 0; $idx < $nbItems; $idx++) { 130 $result[] = $idx + 1; 131 } 132 return $result; 133 } 134 135 $collength = $nbItems / $this->nbCols; 136 $nbItemPerCol = array(); 137 for($idx = 0; $idx < $this->nbCols; $idx++) { 138 $nbItemPerCol[] = ceil(($idx + 1) * $collength) - ceil($idx * $collength); 139 } 140 rsort($nbItemPerCol); 141 142 $result[] = $nbItemPerCol[0]; 143 for($idx = 1; $idx < $this->nbCols; $idx++) { 144 $result[] = end($result) + $nbItemPerCol[$idx]; 145 } 146 147 return $result; 148 } 149} 150