1<?php 2namespace dokuwiki\plugin\struct\types; 3use dokuwiki\plugin\struct\meta\QueryBuilder; 4 5/** 6 * Class Page 7 * 8 * Represents a single page in the wiki. Will be linked in output. 9 * 10 * @package dokuwiki\plugin\struct\types 11 */ 12class Page extends AbstractMultiBaseType { 13 14 protected $config = array( 15 'usetitles' => false, 16 'autocomplete' => array( 17 'mininput' => 2, 18 'maxresult' => 5, 19 'namespace' => '', 20 'postfix' => '', 21 ), 22 ); 23 24 /** 25 * Output the stored data 26 * 27 * @param string $value the value stored in the database - JSON when titles are used 28 * @param \Doku_Renderer $R the renderer currently used to render the data 29 * @param string $mode The mode the output is rendered in (eg. XHTML) 30 * @return bool true if $mode could be satisfied 31 */ 32 public function renderValue($value, \Doku_Renderer $R, $mode) { 33 if($this->config['usetitles']) { 34 list($id, $title) = json_decode($value); 35 } else { 36 $id = $value; 37 $title = null; 38 } 39 40 if(!$id) return true; 41 42 $R->internallink(":$id", $title); 43 return true; 44 } 45 46 /** 47 * Cleans the link 48 * 49 * @param string $value 50 * @return string 51 */ 52 public function validate($value) { 53 return cleanID($value); 54 } 55 56 /** 57 * Autocompletion support for pages 58 * 59 * @return array 60 */ 61 public function handleAjax() { 62 global $INPUT; 63 64 // check minimum length 65 $lookup = trim($INPUT->str('search')); 66 if(utf8_strlen($lookup) < $this->config['autocomplete']['mininput']) return array(); 67 68 // results wanted? 69 $max = $this->config['autocomplete']['maxresult']; 70 if($max <= 0) return array(); 71 72 // lookup with namespace and postfix applied 73 $namespace = $this->config['autocomplete']['namespace']; 74 if($namespace) { 75 // namespace may be relative, resolve in current context 76 $namespace .= ':foo'; // resolve expects pageID 77 resolve_pageid($INPUT->str('ns'), $namespace, $exists); 78 $namespace = getNS($namespace); 79 } 80 $postfix = $this->config['postfix']; 81 if($namespace) $lookup .= ' @' . $namespace; 82 83 $data = ft_pageLookup($lookup, true, $this->config['usetitles']); 84 if(!count($data)) return array(); 85 86 // this basically duplicates what we do in ajax_qsearch() 87 $result = array(); 88 $counter = 0; 89 foreach($data as $id => $title) { 90 if($this->config['usetitles']) { 91 $name = $title; 92 } else { 93 $ns = getNS($id); 94 if($ns) { 95 $name = noNS($id) . ' (' . $ns . ')'; 96 } else { 97 $name = $id; 98 } 99 } 100 101 // check suffix 102 if($postfix && !substr($id, -1 * strlen($postfix)) == $postfix) { 103 continue; // page does not end in postfix, don't suggest it 104 } 105 106 $result[] = array( 107 'label' => $name, 108 'value' => $id 109 ); 110 111 $counter++; 112 if($counter > $max) break; 113 } 114 115 return $result; 116 } 117 118 /** 119 * When using titles, we need ot join the titles table 120 * 121 * @param QueryBuilder $QB 122 * @param string $tablealias 123 * @param string $colname 124 * @param string $alias 125 */ 126 public function select(QueryBuilder $QB, $tablealias, $colname, $alias) { 127 if(!$this->config['usetitles']) { 128 parent::select($QB, $tablealias, $colname, $alias); 129 return; 130 } 131 $rightalias = $QB->generateTableAlias(); 132 $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.$colname = $rightalias.pid"); 133 $QB->addSelectStatement("JSON($tablealias.$colname, $rightalias.title)", $alias); 134 } 135 136 /** 137 * Return the pageid only 138 * 139 * @param string $value 140 * @return string 141 */ 142 public function rawValue($value) { 143 if($this->config['usetitles']) { 144 list($value) = json_decode($value); 145 } 146 return $value; 147 } 148 149 /** 150 * When using titles, we need to compare against the title table, too 151 * 152 * @param QueryBuilder $QB 153 * @param string $tablealias 154 * @param string $colname 155 * @param string $comp 156 * @param string $value 157 * @param string $op 158 */ 159 public function filter(QueryBuilder $QB, $tablealias, $colname, $comp, $value, $op) { 160 if(!$this->config['usetitles']) { 161 parent::filter($QB, $tablealias, $colname, $comp, $value, $op); 162 return; 163 } 164 165 $rightalias = $QB->generateTableAlias(); 166 $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.$colname = $rightalias.pid"); 167 168 // compare against page and title 169 $sub = $QB->filters()->where($op); 170 $pl = $QB->addValue($value); 171 $sub->whereOr("$tablealias.$colname $comp $pl"); 172 $pl = $QB->addValue($value); 173 $sub->whereOr("$rightalias.title $comp $pl"); 174 } 175 176} 177