Skip to content

Commit

Permalink
refactor html and text export. Add TEXTNS and HTMLNS syntax
Browse files Browse the repository at this point in the history
Fixes #135
  • Loading branch information
Klap-in committed Jul 15, 2023
1 parent a3e7ee0 commit 4e6be35
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 97 deletions.
160 changes: 152 additions & 8 deletions action/export.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* @author Gerrit Uitslag <klapinklapin@gmail.com>
*/

use dokuwiki\Extension\Event;

/**
* Take care of exporting only pages in selection, and not the bookmanager page itself
*/
Expand All @@ -15,20 +17,162 @@ class action_plugin_bookcreator_export extends DokuWiki_Action_Plugin {
* @param Doku_Event_Handler $controller
*/
public function register(Doku_Event_Handler $controller) {
$controller->register_hook('ACTION_EXPORT_POSTPROCESS', 'BEFORE', $this, '_exportOnlySelectedpages');
$controller->register_hook('ACTION_EXPORT_POSTPROCESS', 'BEFORE', $this, 'replacePageExportBySelection');
$controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'renameDoExportNSAction');
}

/**
* The selected pages for the onscreen rendering are rendered plus the remaining part of the bookmanager page
* (i.e. the wiki text below the bookmanager). That remaining part has to be removed.
* Handle export request for exporting namespace renamed as normal html/text
* export, the 'book_ns' is used to recognize the namespace. This way we can use the default handling of text
* and html exports
*
* @param Doku_Event $event
* @param Event $event
*/
public function renameDoExportNSAction(Event $event) {
// our event?
$allowedEvents = ['export_htmlns', 'export_textns'];
if(!in_array($event->data, $allowedEvents)) return;

$event->data = substr($event->data, 0, -2); // remove ns from name
}

/**
* Handle export request for exporting the selection as html or text
*
* @param Event $event
*/
public function replacePageExportBySelection(Event $event) {
if(!in_array($event->data['mode'], ['text', 'xhtml'])) {
//skip other export modes
return;
}

global $ID;
global $INPUT;
try{
if($INPUT->has('selection')) {
//export current list from the bookmanager
$list = json_decode($INPUT->str('selection', '', true), true);
if(!is_array($list) || empty($list)) {
throw new Exception($this->getLang('empty'));
}
} elseif($INPUT->has('savedselection')) {
//export a saved selection of the Bookcreator Plugin
/** @var action_plugin_bookcreator_handleselection $SelectionHandling */
$SelectionHandling = plugin_load('action', 'bookcreator_handleselection');
$savedselection = $SelectionHandling->loadSavedSelection($INPUT->str('savedselection'));
$list = $savedselection['selection'];
} elseif($INPUT->has('book_ns')) {
//export triggered with export_textns or export_htmlns
$list = $this->collectPagesOfNS();
} else {
//export is not from bookcreator
return;
}

//remove default export version of current page
$event->data['output'] = '';

$skippedpages = array();
foreach($list as $index => $pageid) {
if(auth_quickaclcheck($pageid) < AUTH_READ) {
$skippedpages[] = $pageid;
unset($list[$index]);
}
}
$list = array_filter($list, 'strlen'); //use of strlen() callback prevents removal of pagename '0'

//if selection contains forbidden pages throw (overridable) warning
if(!$INPUT->bool('book_skipforbiddenpages') && !empty($skippedpages)) {
$msg = hsc(join(', ', $skippedpages));
throw new Exception(sprintf($this->getLang('forbidden'), $msg));
}
} catch (Exception $e) {
http_status(400);
print $e->getMessage();
exit();
}

$keep = $ID;
foreach($list as $page) {
$ID = $page;
$event->data['output'] .= p_cached_output(wikiFN($page), $event->data['mode'], $page);
}
$ID = $keep;
}


/**
* @return array list of pages from ns after filtering
* @throws Exception
*/
public function _exportOnlySelectedpages(Doku_Event $event) {
private function collectPagesOfNS(): array
{
global $INPUT, $conf;
//check input for ns
$pdfnamespace = cleanID($INPUT->str('book_ns'));
if (!@is_dir(dirname(wikiFN($pdfnamespace . ':dummy')))) {
throw new Exception($this->getLang('needns'));
}

//sort order
$order = $INPUT->str('book_order', 'natural', true);
$sortoptions = array('pagename', 'date', 'natural');
if (!in_array($order, $sortoptions)) {
$order = 'natural';
}

//search depth
$depth = $INPUT->int('book_nsdepth', 0);
if ($depth < 0) {
$depth = 0;
}

//page search
$result = array();
$opts = array('depth' => $depth); //recursive all levels
$dir = utf8_encodeFN(str_replace(':', '/', $pdfnamespace));
search($result, $conf['datadir'], 'search_allpages', $opts, $dir);

// exclude ids
$excludes = $INPUT->arr('excludes');
if (!empty($excludes)) {
$result = array_filter($result, function ($item) use ($excludes) {
return !in_array($item['id'], $excludes);
});
}
// exclude namespaces
$excludesns = $INPUT->arr('excludesns');
if (!empty($excludesns)) {
$result = array_filter($result, function ($item) use ($excludesns) {
foreach ($excludesns as $ns) {
if (strpos($item['id'], $ns . ':') === 0) return false;
}
return true;
});
}

//sorting
if (count($result) > 0) {
if ($order == 'date') {
usort($result, array($this, '_datesort'));
} elseif ($order == 'pagename' || $order == 'natural') {
usort($result, array($this, '_pagenamesort'));
}
}

$pos = strrpos($event->data['output'],'<!-- END EXPORTED PAGES -->');
if($pos === false) return;
$list = [];
foreach ($result as $item) {
$list[] = $item['id'];
}

$event->data['output'] = substr($event->data['output'], 0, $pos);
if ($pdfnamespace !== '') {
if (!in_array($pdfnamespace . ':' . $conf['start'], $list, true)) {
if (file_exists(wikiFN(rtrim($pdfnamespace, ':')))) {
array_unshift($list, rtrim($pdfnamespace, ':'));
}
}
}
return $list;
}
}
3 changes: 3 additions & 0 deletions lang/en/lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
$lang['selectiondontexist'] = "Selection doesn't exist at page '%s'";
$lang['selectionforbidden'] = "You have no access to selection at page '%s'";
$lang['exportselection'] = "Export the saved selection '%s' as %s";
$lang['export_htmlns'] = 'Export namespace "%s:" to screen as html';
$lang['export_textns'] = 'Export namespace "%s:" to screen as text';


$lang['titlepreparedownload'] = "Preparing Download...";
$lang['preparingdownload'] = "We are preparing your download, please wait...";
Expand Down
2 changes: 2 additions & 0 deletions lang/nl/lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
$lang['selectiondontexist'] = 'Selectie bestaat niet op pagina \'%s\'';
$lang['selectionforbidden'] = 'U hebt geen toegang tot de selectie op pagina \'%s\'';
$lang['exportselection'] = 'Exporteer de opgeslagen selectie \'%s\' als %s';
$lang['export_htmlns'] = 'Exporteer namespace "%s:" naar het scherm als html';
$lang['export_textns'] = 'Exporteer namespace "%s:" naar het scherm als tekst';
$lang['titlepreparedownload'] = 'Download Voorbereiden...';
$lang['preparingdownload'] = 'We zijn uw download aan het voorbereiden, even geduld alstublieft...';
$lang['titleerrordownload'] = 'Fout';
Expand Down
108 changes: 19 additions & 89 deletions syntax/bookmanager.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function getSort() {
* @param int $state The lexer state for the match
* @param int $pos The character position of the matched text
* @param Doku_Handler $handler The Doku_Handler object
* @return bool|array Return an array with all data you want to use in render, false don't add an instruction
* @return array Return an array with all data you want to use in render, false don't add an instruction
*/
function handle($match, $state, $pos, Doku_Handler $handler) {

Expand Down Expand Up @@ -113,10 +113,6 @@ function render($format, Doku_Renderer $renderer, $data) {
list($type, $num, $order) = $data;

if($type == "bookmanager") {
if($format == 'text' && $INPUT->str('do') == 'export_text') {
$format = 'xhtml';
}

if($format == 'xhtml') {
/** @var Doku_Renderer_xhtml $renderer */
$renderer->info['cache'] = false;
Expand All @@ -126,35 +122,33 @@ function render($format, Doku_Renderer $renderer, $data) {

//intervents the normal export_* handling
$do = $INPUT->str('do');
$allowed_onscreen_exports = array(
$ignore_onscreen_exports = [
'export_html',
'export_text'
);
if(in_array($do, $allowed_onscreen_exports)) {
//export as xhtml or text
$this->exportOnScreen($renderer);

} else {
//show the bookmanager
$this->showBookManager($renderer, $usercansave);

// Displays the list of saved selections
$this->renderSelectionslist($renderer, $bookmanager = true, $ID, $order);
$renderer->doc .= "<br />";
'export_htmlns'
];
if(in_array($do, $ignore_onscreen_exports)) {
//export as xhtml or text, is handled in action component 'export'
return false;
}

//show the bookmanager
$this->showBookManager($renderer, $usercansave);

// Displays the list of saved selections
$this->renderSelectionslist($renderer, true, $ID, $order);
$renderer->doc .= "<br />";
}
return false;

} else {
// type == archive

if($format == 'xhtml') {
/** @var Doku_Renderer_xhtml $renderer */
// generates the list of saved selections
$this->renderSelectionslist($renderer, $bookmanager = false, $this->getConf('book_page'), $order, $num);
$this->renderSelectionslist($renderer, false, $this->getConf('book_page'), $order, $num);
}
return false;
}
return false;
}

/**
Expand Down Expand Up @@ -191,77 +185,12 @@ public function renderSelectionslist($renderer, $bookmanager, $bmpage, $order, $
}
}



/**
* Handle export request for exporting the selection as html or text
*
* @param Doku_renderer_xhtml $renderer
*/
private function exportOnScreen($renderer) {
global $ID;
global $INPUT;
try{
$list = array();
if($INPUT->has('selection')) {
//export current list from the bookmanager
$list = json_decode($INPUT->str('selection', '', true), true);
if(!is_array($list) || empty($list)) {
throw new Exception($this->getLang('empty'));
}
} elseif($INPUT->has('savedselection')) {
//export a saved selection of the Bookcreator Plugin
/** @var action_plugin_bookcreator_handleselection $SelectionHandling */
$SelectionHandling = plugin_load('action', 'bookcreator_handleselection');
$savedselection = $SelectionHandling->loadSavedSelection($INPUT->str('savedselection'));
$list = $savedselection['selection'];
}

//remove first part of bookmanager page
$renderer->doc = '';

$render_mode = 'xhtml';
if($INPUT->str('do') == 'export_text') {
$render_mode = 'text';
}

$skippedpages = array();
foreach($list as $index => $pageid) {
if(auth_quickaclcheck($pageid) < AUTH_READ) {
$skippedpages[] = $pageid;
unset($list[$index]);
}
}
$list = array_filter($list, 'strlen'); //use of strlen() callback prevents removal of pagename '0'

//if selection contains forbidden pages throw (overridable) warning
if(!$INPUT->bool('book_skipforbiddenpages') && !empty($skippedpages)) {
$msg = hsc(join(', ', $skippedpages));
throw new Exception(sprintf($this->getLang('forbidden'), $msg));
}
} catch (Exception $e) {
http_status(400);
print $e->getMessage();
exit();
}
$keep = $ID;
foreach($list as $page) {
$ID = $page;
$renderer->doc .= p_cached_output(wikiFN($page), $render_mode, $page);
}

//add mark for removing everything after these rendered pages, see action component 'export'
$renderer->doc .= '<!-- END EXPORTED PAGES -->';
$ID = $keep;
}

/**
* Displays the Bookmanager - Let organize selections and export them
* Only visible when a selection is loaded from the save selections or from cookie FIXME
*
* @param Doku_renderer_xhtml $renderer
* @param bool $usercansave User has permissions to save the selection
* @return bool false: empty cookie, true: selection found and bookmanager is rendered
*/
private function showBookManager($renderer, $usercansave) {
global $ID;
Expand Down Expand Up @@ -305,7 +234,9 @@ private function showBookManager($renderer, $usercansave) {
$renderer->doc .= "</div>";
$renderer->doc .= "<div class='bookcreator__actions'>";
// PDF Export
$values = array('export_html'=> $this->getLang('exportprint'));
$values = [
'export_html'=> $this->getLang('exportprint')
];
$selected = 'export_html';
if(file_exists(DOKU_PLUGIN."text/renderer.php") && !plugin_isdisabled("text")) {
$values['export_text'] = $this->getLang('exporttext');
Expand Down Expand Up @@ -375,7 +306,6 @@ private function showBookManager($renderer, $usercansave) {
. " <div class='downloadresponse'>{$this->getLang('faileddownload')}</div>"
. '</div>';

return true;
}

/**
Expand Down
Loading

0 comments on commit 4e6be35

Please sign in to comment.