add contents
This commit is contained in:
55
lib/plugins/odt/action/cache.php
Normal file
55
lib/plugins/odt/action/cache.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* ODT Plugin: extends the dependencies of the cache with ODT related files
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Aurelien Bompard <aurelien@bompard.org>
|
||||
* @author Florian Lamml <info@florian-lamml.de>
|
||||
*/
|
||||
// must be run within Dokuwiki
|
||||
if(!defined('DOKU_INC')) die();
|
||||
|
||||
/**
|
||||
* Add the template as a page dependency for the caching system
|
||||
*
|
||||
* @package DokuWiki\Action\Cache
|
||||
*/
|
||||
class action_plugin_odt_cache extends DokuWiki_Action_Plugin {
|
||||
protected $config = null;
|
||||
|
||||
/**
|
||||
* Register the event
|
||||
*
|
||||
* @param Doku_Event_Handler $controller
|
||||
*/
|
||||
public function register(Doku_Event_Handler $controller) {
|
||||
$controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_cache_prepare');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add dependencies to cache
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
*/
|
||||
public function handle_cache_prepare(Doku_Event $event) {
|
||||
// Load config helper if not done yet
|
||||
if ( $this->config == NULL ) {
|
||||
$this->config = plugin_load('helper', 'odt_config');
|
||||
$this->config->load($warning);
|
||||
}
|
||||
|
||||
$cache =& $event->data;
|
||||
// only the ODT rendering mode needs caching tweaks
|
||||
if($cache->mode != "odt") return;
|
||||
|
||||
$template_name = $this->config->getParam('odt_template');
|
||||
if(!$template_name) {
|
||||
return;
|
||||
}
|
||||
$template_path = $this->config->getParam('mediadir') . '/' . $this->config->getParam('tpl_dir') . "/" . $template_name;
|
||||
if(file_exists($template_path)) {
|
||||
$cache->depends['files'][] = $template_path;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
532
lib/plugins/odt/action/export.php
Normal file
532
lib/plugins/odt/action/export.php
Normal file
@@ -0,0 +1,532 @@
|
||||
<?php
|
||||
/**
|
||||
* ODT export Plugin component. Mainly based at dw2pdf export action plugin component.
|
||||
*
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
* @author Luigi Micco <l.micco@tiscali.it>
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @author Gerrit Uitslag <klapinklapin@gmail.com>
|
||||
*/
|
||||
|
||||
// must be run within Dokuwiki
|
||||
if(!defined('DOKU_INC')) die();
|
||||
|
||||
use dokuwiki\Action\Exception\ActionException;
|
||||
use dokuwiki\Action\Exception\ActionAbort;
|
||||
|
||||
/**
|
||||
* Class action_plugin_odt_export
|
||||
*
|
||||
* Collect pages and export these. GUI is available via bookcreator.
|
||||
*
|
||||
* @package DokuWiki\Action\Export
|
||||
*/
|
||||
class action_plugin_odt_export extends DokuWiki_Action_Plugin {
|
||||
protected $config = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $list = array();
|
||||
|
||||
/**
|
||||
* Register the events
|
||||
*
|
||||
* @param Doku_Event_Handler $controller
|
||||
*/
|
||||
public function register(Doku_Event_Handler $controller) {
|
||||
$controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'convert', array());
|
||||
$controller->register_hook('TEMPLATE_PAGETOOLS_DISPLAY', 'BEFORE', $this, 'addbutton_odt', array());
|
||||
$controller->register_hook('TEMPLATE_PAGETOOLS_DISPLAY', 'BEFORE', $this, 'addbutton_pdf', array());
|
||||
$controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addbutton_odt_new', array());
|
||||
$controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addbutton_pdf_new', array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'export odt'-button to pagetools
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
*/
|
||||
public function addbutton_odt(Doku_Event $event) {
|
||||
global $ID, $REV;
|
||||
|
||||
if($this->getConf('showexportbutton') && $event->data['view'] == 'main') {
|
||||
$params = array('do' => 'export_odt');
|
||||
if($REV) {
|
||||
$params['rev'] = $REV;
|
||||
}
|
||||
|
||||
// insert button at position before last (up to top)
|
||||
$event->data['items'] = array_slice($event->data['items'], 0, -1, true) +
|
||||
array('export_odt' =>
|
||||
'<li>'
|
||||
. '<a href="' . wl($ID, $params) . '" class="action export_odt" rel="nofollow" title="' . $this->getLang('export_odt_button') . '">'
|
||||
. '<span>' . $this->getLang('export_odt_button') . '</span>'
|
||||
. '</a>'
|
||||
. '</li>'
|
||||
) +
|
||||
array_slice($event->data['items'], -1, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'export odt=>pdf'-button to pagetools
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
*/
|
||||
public function addbutton_pdf(Doku_Event $event) {
|
||||
global $ID, $REV;
|
||||
|
||||
if($this->getConf('showpdfexportbutton') && $event->data['view'] == 'main') {
|
||||
$params = array('do' => 'export_odt_pdf');
|
||||
if($REV) {
|
||||
$params['rev'] = $REV;
|
||||
}
|
||||
|
||||
// insert button at position before last (up to top)
|
||||
$event->data['items'] = array_slice($event->data['items'], 0, -1, true) +
|
||||
array('export_odt_pdf' =>
|
||||
'<li>'
|
||||
. '<a href="' . wl($ID, $params) . '" class="action export_odt_pdf" rel="nofollow" title="' . $this->getLang('export_odt_pdf_button') . '">'
|
||||
. '<span>' . $this->getLang('export_odt_pdf_button') . '</span>'
|
||||
. '</a>'
|
||||
. '</li>'
|
||||
) +
|
||||
array_slice($event->data['items'], -1, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'export odt' button to page tools, new SVG based mechanism
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
*/
|
||||
public function addbutton_odt_new(Doku_Event $event) {
|
||||
if($event->data['view'] != 'page') return;
|
||||
if($this->getConf('showexportbutton')) {
|
||||
array_splice($event->data['items'], -1, 0, [new \dokuwiki\plugin\odt\MenuItemODT()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'export odt pdf' button to page tools, new SVG based mechanism
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
*/
|
||||
public function addbutton_pdf_new(Doku_Event $event) {
|
||||
if($event->data['view'] != 'page') return;
|
||||
if($this->getConf('showpdfexportbutton')) {
|
||||
array_splice($event->data['items'], -1, 0, [new \dokuwiki\plugin\odt\MenuItemODTPDF()]);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************************
|
||||
* Book export *
|
||||
***********************************************************************************/
|
||||
|
||||
/**
|
||||
* Do article(s) to ODT conversion work
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
* @return bool
|
||||
*/
|
||||
public function convert(Doku_Event $event) {
|
||||
global $ID;
|
||||
$format = NULL;
|
||||
|
||||
$action = act_clean($event->data);
|
||||
|
||||
// Any kind of ODT export?
|
||||
$odt_export = false;
|
||||
if (strncmp($action, 'export_odt', strlen('export_odt')) == 0) {
|
||||
$odt_export = true;
|
||||
}
|
||||
|
||||
// check conversion format
|
||||
if ($odt_export && strpos($action, '_pdf') !== false) {
|
||||
$format = 'pdf';
|
||||
}
|
||||
|
||||
// single page export:
|
||||
// rename action to the actual renderer component
|
||||
if($action == 'export_odt') {
|
||||
$event->data = 'export_odt_page';
|
||||
} else if ($action == 'export_odt_pdf') {
|
||||
$event->data = 'export_odt_pagepdf';
|
||||
}
|
||||
|
||||
if( !is_array($action) && $odt_export ) {
|
||||
// On export to ODT load config helper if not done yet
|
||||
// and stop on errors.
|
||||
if ( $this->config == NULL ) {
|
||||
$this->config = plugin_load('helper', 'odt_config');
|
||||
$this->config->load($warning);
|
||||
|
||||
if (!empty($warning)) {
|
||||
$this->showPageWithErrorMsg($event, NULL, $warning);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->config->setConvertTo($format);
|
||||
}
|
||||
|
||||
// the book export?
|
||||
if(($action != 'export_odtbook') && ($action != 'export_odtns')) return false;
|
||||
|
||||
// check user's rights
|
||||
if(auth_quickaclcheck($ID) < AUTH_READ) return false;
|
||||
|
||||
if($data = $this->collectExportPages($event)) {
|
||||
list($title, $this->list) = $data;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// it's ours, no one else's
|
||||
$event->preventDefault();
|
||||
|
||||
// prepare cache and its dependencies
|
||||
$depends = array();
|
||||
$cache = $this->prepareCache($title, $depends);
|
||||
|
||||
// hard work only when no cache available
|
||||
if(!$this->getConf('usecache') || !$cache->useCache($depends)) {
|
||||
$this->generateODT($cache->cache, $title);
|
||||
}
|
||||
|
||||
// deliver the file
|
||||
$this->sendODTFile($cache->cache, $title);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain list of pages and title, based on url parameters
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function collectExportPages(Doku_Event $event) {
|
||||
global $ID;
|
||||
global $INPUT;
|
||||
|
||||
// Load config helper if not done yet
|
||||
if ( $this->config == NULL ) {
|
||||
$this->config = plugin_load('helper', 'odt_config');
|
||||
$this->config->load($warning);
|
||||
}
|
||||
|
||||
// list of one or multiple pages
|
||||
$list = array();
|
||||
|
||||
$action = $event->data;
|
||||
if($action == 'export_odt') {
|
||||
$list[0] = $ID;
|
||||
$title = $INPUT->str('book_title');
|
||||
if(!$title) {
|
||||
$title = p_get_first_heading($ID);
|
||||
}
|
||||
|
||||
} elseif($action == 'export_odtns') {
|
||||
//check input for title and ns
|
||||
if(!$title = $INPUT->str('book_title')) {
|
||||
$this->showPageWithErrorMsg($event, 'needtitle');
|
||||
return false;
|
||||
}
|
||||
$docnamespace = cleanID($INPUT->str('book_ns'));
|
||||
if(!@is_dir(dirname(wikiFN($docnamespace . ':dummy')))) {
|
||||
$this->showPageWithErrorMsg($event, 'needns');
|
||||
return false;
|
||||
}
|
||||
|
||||
//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(':', '/', $docnamespace));
|
||||
search($result, $this->config->getParam('datadir'), 'search_allpages', $opts, $dir);
|
||||
|
||||
//sorting
|
||||
if(count($result) > 0) {
|
||||
if($order == 'date') {
|
||||
usort($result, array($this, '_datesort'));
|
||||
} elseif($order == 'pagename') {
|
||||
usort($result, array($this, '_pagenamesort'));
|
||||
}
|
||||
}
|
||||
|
||||
foreach($result as $item) {
|
||||
$list[] = $item['id'];
|
||||
}
|
||||
|
||||
} elseif(isset($_COOKIE['list-pagelist']) && !empty($_COOKIE['list-pagelist'])) {
|
||||
// Here is $action == 'export_odtbook'
|
||||
|
||||
/** @deprecated April 2016 replaced by localStorage version of Bookcreator*/
|
||||
|
||||
//is in Bookmanager of bookcreator plugin a title given?
|
||||
if(!$title = $INPUT->str('book_title')) {
|
||||
$this->showPageWithErrorMsg($event, 'needtitle');
|
||||
return false;
|
||||
} else {
|
||||
$list = explode("|", $_COOKIE['list-pagelist']);
|
||||
}
|
||||
|
||||
} elseif($INPUT->has('selection')) {
|
||||
//handle Bookcreator requests based at localStorage
|
||||
// if(!checkSecurityToken()) {
|
||||
// http_status(403);
|
||||
// print $this->getLang('empty');
|
||||
// exit();
|
||||
// }
|
||||
|
||||
$json = new JSON(JSON_LOOSE_TYPE);
|
||||
$list = $json->decode($INPUT->post->str('selection', '', true));
|
||||
if(!is_array($list) || empty($list)) {
|
||||
http_status(400);
|
||||
print $this->getLang('empty');
|
||||
exit();
|
||||
}
|
||||
|
||||
$title = $INPUT->str('pdfbook_title'); //DEPRECATED
|
||||
$title = $INPUT->str('book_title', $title, true);
|
||||
if(empty($title)) {
|
||||
http_status(400);
|
||||
print $this->getLang('needtitle');
|
||||
exit();
|
||||
}
|
||||
|
||||
} else {
|
||||
//show empty bookcreator message
|
||||
$this->showPageWithErrorMsg($event, 'empty');
|
||||
return false;
|
||||
}
|
||||
|
||||
$list = array_map('cleanID', $list);
|
||||
|
||||
$skippedpages = array();
|
||||
foreach($list as $index => $pageid) {
|
||||
if(auth_quickaclcheck($pageid) < AUTH_READ) {
|
||||
$skippedpages[] = $pageid;
|
||||
unset($list[$index]);
|
||||
}
|
||||
}
|
||||
$list = array_filter($list); //removes also pages mentioned '0'
|
||||
|
||||
//if selection contains forbidden pages throw (overridable) warning
|
||||
if(!$INPUT->bool('book_skipforbiddenpages') && !empty($skippedpages)) {
|
||||
$msg = sprintf($this->getLang('forbidden'), hsc(join(', ', $skippedpages)));
|
||||
if($INPUT->has('selection')) {
|
||||
http_status(400);
|
||||
print $msg;
|
||||
exit();
|
||||
} else {
|
||||
$this->showPageWithErrorMsg($event, null, $msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return array($title, $list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set error notification and reload page again
|
||||
*
|
||||
* @param Doku_Event $event
|
||||
* @param string $msglangkey key of translation key
|
||||
*/
|
||||
private function showPageWithErrorMsg(Doku_Event $event, $msglangkey, $translatedMsg=NULL) {
|
||||
if (!empty($msglangkey)) {
|
||||
// Message need to be translated.
|
||||
msg($this->getLang($msglangkey), -1);
|
||||
} else {
|
||||
// Message already has been translated.
|
||||
msg($translatedMsg, -1);
|
||||
}
|
||||
|
||||
$event->data = 'show';
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST'; //clears url
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare cache
|
||||
*
|
||||
* @param string $title
|
||||
* @param array $depends (reference) array with dependencies
|
||||
* @return cache
|
||||
*/
|
||||
protected function prepareCache($title, &$depends) {
|
||||
global $REV;
|
||||
global $INPUT;
|
||||
|
||||
//different caches for varying config settings
|
||||
$template = $this->getConf("odt_template");
|
||||
$template = $INPUT->get->str('odt_template', $template, true);
|
||||
|
||||
|
||||
$cachekey = join(',', $this->list)
|
||||
. $REV
|
||||
. $template
|
||||
. $title;
|
||||
$cache = new cache($cachekey, '.odt');
|
||||
|
||||
$dependencies = array();
|
||||
foreach($this->list as $pageid) {
|
||||
$relations = p_get_metadata($pageid, 'relation');
|
||||
|
||||
if(is_array($relations)) {
|
||||
if(array_key_exists('media', $relations) && is_array($relations['media'])) {
|
||||
foreach($relations['media'] as $mediaid => $exists) {
|
||||
if($exists) {
|
||||
$dependencies[] = mediaFN($mediaid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(array_key_exists('haspart', $relations) && is_array($relations['haspart'])) {
|
||||
foreach($relations['haspart'] as $part_pageid => $exists) {
|
||||
if($exists) {
|
||||
$dependencies[] = wikiFN($part_pageid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dependencies[] = metaFN($pageid, '.meta');
|
||||
}
|
||||
|
||||
$depends['files'] = array_map('wikiFN', $this->list);
|
||||
$depends['files'][] = __FILE__;
|
||||
$depends['files'][] = dirname(__FILE__) . '/../renderer/page.php';
|
||||
$depends['files'][] = dirname(__FILE__) . '/../renderer/book.php';
|
||||
$depends['files'][] = dirname(__FILE__) . '/../plugin.info.txt';
|
||||
$depends['files'] = array_merge(
|
||||
$depends['files'],
|
||||
$dependencies,
|
||||
getConfigFiles('main')
|
||||
);
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a ODT from the articles
|
||||
*
|
||||
* @param string $cachefile
|
||||
* @param string $title
|
||||
*/
|
||||
protected function generateODT($cachefile, $title) {
|
||||
global $ID;
|
||||
global $REV;
|
||||
|
||||
/** @var renderer_plugin_odt_book $odt */
|
||||
$odt = plugin_load('renderer','odt_book');
|
||||
|
||||
// store original pageid
|
||||
$keep = $ID;
|
||||
|
||||
// loop over all pages
|
||||
$xmlcontent = '';
|
||||
foreach($this->list as $page) {
|
||||
$filename = wikiFN($page, $REV);
|
||||
|
||||
if(!file_exists($filename)) {
|
||||
continue;
|
||||
}
|
||||
// set global pageid to the rendered page
|
||||
$ID = $page;
|
||||
$xmlcontent .= p_render('odt_book', p_cached_instructions($filename, false, $page), $info);
|
||||
}
|
||||
|
||||
//restore ID
|
||||
$ID = $keep;
|
||||
|
||||
$odt->doc = $xmlcontent;
|
||||
$odt->setTitle($title);
|
||||
$odt->finalize_ODTfile();
|
||||
|
||||
// write to cache file
|
||||
io_savefile($cachefile, $odt->doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cachefile
|
||||
* @param string $title
|
||||
*/
|
||||
protected function sendODTFile($cachefile, $title) {
|
||||
header('Content-Type: application/vnd.oasis.opendocument.text');
|
||||
header('Cache-Control: must-revalidate, no-transform, post-check=0, pre-check=0');
|
||||
header('Pragma: public');
|
||||
http_conditionalRequest(filemtime($cachefile));
|
||||
|
||||
$filename = rawurlencode(cleanID(strtr($title, ':/;"', ' ')));
|
||||
if($this->getConf('output') == 'file') {
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '.odt";');
|
||||
} else {
|
||||
header('Content-Disposition: inline; filename="' . $filename . '.odt";');
|
||||
}
|
||||
|
||||
//Bookcreator uses jQuery.fileDownload.js, which requires a cookie.
|
||||
header('Set-Cookie: fileDownload=true; path=/');
|
||||
|
||||
//try to send file, and exit if done
|
||||
http_sendfile($cachefile);
|
||||
|
||||
$fp = @fopen($cachefile, "rb");
|
||||
if($fp) {
|
||||
http_rangeRequest($fp, filesize($cachefile), 'application/vnd.oasis.opendocument.text');
|
||||
} else {
|
||||
header("HTTP/1.0 500 Internal Server Error");
|
||||
print "Could not read file - bad permissions?";
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of wiki pages which will be included in the exported document
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExportedPages() {
|
||||
return $this->list;
|
||||
}
|
||||
|
||||
/**
|
||||
* usort callback to sort by file lastmodified time
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
public function _datesort($a, $b) {
|
||||
if($b['rev'] < $a['rev']) return -1;
|
||||
if($b['rev'] > $a['rev']) return 1;
|
||||
return strcmp($b['id'], $a['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* usort callback to sort by page id
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
* @return int
|
||||
*/
|
||||
public function _pagenamesort($a, $b) {
|
||||
if($a['id'] <= $b['id']) return -1;
|
||||
if($a['id'] > $b['id']) return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user