1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Gerrit Uitslag <klapinklapin@gmail.com> 5 */ 6 7use dokuwiki\Extension\Event; 8 9/** 10 * Take care of exporting only pages in selection, and not the bookmanager page itself 11 */ 12class action_plugin_bookcreator_export extends DokuWiki_Action_Plugin { 13 14 /** 15 * Registers a callback function for a given event 16 * 17 * @param Doku_Event_Handler $controller 18 */ 19 public function register(Doku_Event_Handler $controller) { 20 $controller->register_hook('ACTION_EXPORT_POSTPROCESS', 'BEFORE', $this, 'replacePageExportBySelection'); 21 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'renameDoExportNSAction'); 22 } 23 24 /** 25 * Handle export request for exporting namespace renamed as normal html/text 26 * export, the 'book_ns' is used to recognize the namespace. This way we can use the default handling of text 27 * and html exports 28 * 29 * @param Event $event 30 */ 31 public function renameDoExportNSAction(Event $event) { 32 $allowedEvents = ['export_htmlns', 'export_textns']; 33 if(in_array($event->data, $allowedEvents)) { 34 $event->data = substr($event->data, 0, -2); 35 } 36 37 //export_xhtml is built-in xhtml export with header 38 if($event->data === 'export_html') { // also act_clean() does this rename 39 $event->data = 'export_xhtml'; 40 } 41 } 42 43 /** 44 * Handle export request for exporting the selection as html or text 45 * 46 * @param Event $event 47 */ 48 public function replacePageExportBySelection(Event $event) { 49 if(!in_array($event->data['mode'], ['text', 'xhtml'])) { 50 //skip other export modes 51 return; 52 } 53 54 global $ID; 55 global $INPUT; 56 try{ 57 if($INPUT->has('selection')) { 58 //export current list from the bookmanager 59 $list = json_decode($INPUT->str('selection', '', true), true); 60 if(!is_array($list) || empty($list)) { 61 throw new Exception($this->getLang('empty')); 62 } 63 } elseif($INPUT->has('savedselection')) { 64 //export a saved selection of the Bookcreator Plugin 65 /** @var action_plugin_bookcreator_handleselection $SelectionHandling */ 66 $SelectionHandling = plugin_load('action', 'bookcreator_handleselection'); 67 $savedselection = $SelectionHandling->loadSavedSelection($INPUT->str('savedselection')); 68 $list = $savedselection['selection']; 69 } elseif($INPUT->has('book_ns')) { 70 //export triggered with export_textns or export_htmlns 71 $list = $this->collectPagesOfNS(); 72 } else { 73 //export is not from bookcreator 74 return; 75 } 76 77 //remove default export version of current page 78 $event->data['output'] = ''; 79 80 $skippedpages = array(); 81 foreach($list as $index => $pageid) { 82 if(auth_quickaclcheck($pageid) < AUTH_READ) { 83 $skippedpages[] = $pageid; 84 unset($list[$index]); 85 } 86 } 87 $list = array_filter($list, 'strlen'); //use of strlen() callback prevents removal of pagename '0' 88 89 //if selection contains forbidden pages throw (overridable) warning 90 if(!$INPUT->bool('book_skipforbiddenpages') && !empty($skippedpages)) { 91 $msg = hsc(join(', ', $skippedpages)); 92 throw new Exception(sprintf($this->getLang('forbidden'), $msg)); 93 } 94 } catch (Exception $e) { 95 http_status(400); 96 print $e->getMessage(); 97 exit(); 98 } 99 100 $keep = $ID; 101 foreach($list as $page) { 102 $ID = $page; 103 $event->data['output'] .= p_cached_output(wikiFN($page), $event->data['mode'], $page); 104 } 105 $ID = $keep; 106 } 107 108 109 /** 110 * @return array list of pages from ns after filtering 111 * @throws Exception 112 */ 113 private function collectPagesOfNS(): array 114 { 115 global $INPUT, $conf; 116 //check input for ns 117 $pdfnamespace = cleanID($INPUT->str('book_ns')); 118 if (!@is_dir(dirname(wikiFN($pdfnamespace . ':dummy')))) { 119 throw new Exception($this->getLang('needns')); 120 } 121 122 //sort order 123 $order = $INPUT->str('book_order', 'natural', true); 124 $sortoptions = array('pagename', 'date', 'natural'); 125 if (!in_array($order, $sortoptions)) { 126 $order = 'natural'; 127 } 128 129 //search depth 130 $depth = $INPUT->int('book_nsdepth', 0); 131 if ($depth < 0) { 132 $depth = 0; 133 } 134 135 //page search 136 $result = array(); 137 $opts = array('depth' => $depth); //recursive all levels 138 $dir = utf8_encodeFN(str_replace(':', '/', $pdfnamespace)); 139 search($result, $conf['datadir'], 'search_allpages', $opts, $dir); 140 141 // exclude ids 142 $excludes = $INPUT->arr('excludes'); 143 if (!empty($excludes)) { 144 $result = array_filter($result, function ($item) use ($excludes) { 145 return !in_array($item['id'], $excludes); 146 }); 147 } 148 // exclude namespaces 149 $excludesns = $INPUT->arr('excludesns'); 150 if (!empty($excludesns)) { 151 $result = array_filter($result, function ($item) use ($excludesns) { 152 foreach ($excludesns as $ns) { 153 if (strpos($item['id'], $ns . ':') === 0) return false; 154 } 155 return true; 156 }); 157 } 158 159 //sorting 160 if (count($result) > 0) { 161 if ($order == 'date') { 162 usort($result, array($this, '_datesort')); 163 } elseif ($order == 'pagename' || $order == 'natural') { 164 usort($result, array($this, '_pagenamesort')); 165 } 166 } 167 168 $list = []; 169 foreach ($result as $item) { 170 $list[] = $item['id']; 171 } 172 173 if ($pdfnamespace !== '') { 174 if (!in_array($pdfnamespace . ':' . $conf['start'], $list, true)) { 175 if (file_exists(wikiFN(rtrim($pdfnamespace, ':')))) { 176 array_unshift($list, rtrim($pdfnamespace, ':')); 177 } 178 } 179 } 180 return $list; 181 } 182} 183