1<?php 2 3use dokuwiki\File\PageResolver; 4 5/** 6 * DokuWiki Plugin tplinc (Helper Component) 7 * 8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 9 * @author Andreas Gohr <dokuwiki@cosmocode.de> 10 */ 11class helper_plugin_tplinc extends DokuWiki_Plugin 12{ 13 14 protected $file = DOKU_CONF . 'tplinc.conf'; 15 16 /** 17 * Load the current assignments into an array 18 * 19 * @return array 20 */ 21 public function loadAssignments() 22 { 23 $assignments = array(); 24 if (!file_exists($this->file)) return $assignments; 25 26 $data = file($this->file); 27 foreach ($data as $line) { 28 //ignore comments (except escaped ones) 29 $line = preg_replace('/(?<![&\\\\])#.*$/', '', $line); 30 $line = str_replace('\\#', '#', $line); 31 $line = trim($line); 32 if (empty($line)) continue; 33 $assignments[] = array_map('trim', explode("\t", $line, 4)); 34 } 35 36 return $assignments; 37 } 38 39 /** 40 * The same as loadAssignments but uses caching 41 * 42 * @return array 43 */ 44 public function getAssignments() 45 { 46 static $assignements = null; 47 if ($assignements === null) $assignements = $this->loadAssignments(); 48 return $assignements; 49 } 50 51 /** 52 * Save new assignment data 53 * 54 * @param array $data as returned by loadAssignment 55 * @return bool 56 */ 57 public function saveAssignments($data) 58 { 59 $content = ''; 60 61 foreach ($data as $row) { 62 $row = array_map('trim', $row); 63 if ($row[0] === '' || $row[1] === '') continue; 64 if (count($row) < 4) $row[3] = 0; 65 66 $content .= join("\t", $row) . "\n"; 67 } 68 69 return io_saveFile($this->file, $content); 70 } 71 72 /** 73 * Get a list of pages that should be included at the given $location 74 * 75 * @param string $location 76 * @param null|string $id the ID to check against, null for global $ID 77 * @return array list of pages to include 78 */ 79 public function getIncludes($location, $id = null) 80 { 81 global $ID; 82 if ($id === null) $id = $ID; 83 $id = cleanID($id); 84 $ns = getNS($id); 85 $pns = ":$ns:"; 86 87 $assignments = $this->getAssignments(); 88 $pages = array(); 89 90 foreach ($assignments as $row) { 91 list($pattern, $page, $loc, $skipacl) = $row; 92 if ($loc != $location) continue; 93 $page = $this->matchPagePattern($pattern, $id, $page, $pns); 94 if ($page === false) continue; 95 $page = (new PageResolver($ns))->resolveId($page); 96 if (!page_exists($page)) continue; 97 if (!$skipacl && auth_quickaclcheck($page) < AUTH_READ) continue; 98 $pages[] = $page; 99 } 100 101 return array_unique($pages); 102 } 103 104 /** 105 * Render the include pagesfor the given $location 106 * 107 * @param $location 108 * @param null|string $id the ID to check against, null for global $ID 109 * @return string the rendered XHTML 110 */ 111 public function renderIncludes($location, $id = null) 112 { 113 $pages = $this->getIncludes($location, $id); 114 $content = ''; 115 foreach ($pages as $page) { 116 $content .= p_wiki_xhtml($page, '', false); 117 } 118 return $content; 119 } 120 121 /** 122 * Get the locations supported by the template 123 * 124 * The template needs to implement the apropriate event hook 125 * 126 * @return array 127 */ 128 public function getLocations() 129 { 130 $data = array('' => $this->getLang('unknown')); 131 $event = new Doku_Event('PLUGIN_TPLINC_LOCATIONS_SET', $data); 132 $event->advise_before(false); 133 asort($data); 134 $event->advise_after(); 135 136 return $data; 137 } 138 139 /** 140 * Check if the given pattern matches the given page id 141 * 142 * @param string $pattern the pattern to check against 143 * @param string $id the cleaned pageid to check 144 * @param string $page the page to include on success - may contain regexp placeholders 145 * @param string|null $pns optimization, the colon wrapped namespace of the page, set null for automatic 146 * @return string|bool the page as matched (with placeholders replaced) or false if the pattern does not match 147 */ 148 protected function matchPagePattern($pattern, $id, $page, $pns = null) 149 { 150 if (trim($pattern, ':') == '**') return $page; // match all 151 152 // regex patterns 153 if ($pattern[0] == '/') { 154 if (preg_match($pattern, ":$id", $matches)) { 155 $len = count($matches); 156 for ($i = $len - 1; $i >= 0; $i--) { 157 $page = str_replace('$' . $i, $matches[$i], $page); 158 } 159 return $page; 160 } 161 return false; 162 } 163 164 if (is_null($pns)) { 165 $pns = ':' . getNS($id) . ':'; 166 } 167 168 $ans = ':' . cleanID($pattern) . ':'; 169 if (substr($pattern, -2) == '**') { 170 // upper namespaces match 171 if (strpos($pns, $ans) === 0) { 172 return $page; 173 } 174 } else { 175 if (substr($pattern, -1) == '*') { 176 // namespaces match exact 177 if ($ans == $pns) { 178 return $page; 179 } 180 } else { 181 // exact match 182 if (cleanID($pattern) == $id) { 183 return $page; 184 } 185 } 186 } 187 188 return false; 189 } 190 191} 192