diff --git a/plugins/55/dw2pdf/.github/workflows/dokuwiki.yml b/plugins/55/dw2pdf/.github/workflows/dokuwiki.yml new file mode 100644 index 0000000..31b4b08 --- /dev/null +++ b/plugins/55/dw2pdf/.github/workflows/dokuwiki.yml @@ -0,0 +1,11 @@ +name: DokuWiki Default Tasks +on: + push: + pull_request: + schedule: + - cron: '22 12 25 * *' + + +jobs: + all: + uses: dokuwiki/github-action/.github/workflows/all.yml@main diff --git a/plugins/55/dw2pdf/.gitignore b/plugins/55/dw2pdf/.gitignore new file mode 100644 index 0000000..f3916f2 --- /dev/null +++ b/plugins/55/dw2pdf/.gitignore @@ -0,0 +1,12 @@ +composer.phar +vendor/bin/* +vendor/.git +vendor/*/*/.git +vendor/*/*/phpunit.xml* +vendor/*/*/.travis.yml +vendor/*/*/bin/* +vendor/*/*/tests/* +vendor/*/*/test/* +vendor/*/*/doc/* +vendor/*/*/docs/* +vendor/*/*/contrib/* diff --git a/plugins/55/dw2pdf/DokuImageProcessorDecorator.php b/plugins/55/dw2pdf/DokuImageProcessorDecorator.php new file mode 100644 index 0000000..d5aea14 --- /dev/null +++ b/plugins/55/dw2pdf/DokuImageProcessorDecorator.php @@ -0,0 +1,113 @@ + + */ +class DokuPDF extends Mpdf +{ + /** + * DokuPDF constructor. + * + * @param string $pagesize + * @param string $orientation + * @param int $fontsize + * + * @throws MpdfException + * @throws Exception + */ + public function __construct($pagesize = 'A4', $orientation = 'portrait', $fontsize = 11, $docLang = 'en') + { + global $conf; + global $lang; + + if (!defined('_MPDF_TEMP_PATH')) { + define('_MPDF_TEMP_PATH', $conf['tmpdir'] . '/dwpdf/' . random_int(1, 1000) . '/'); + } + io_mkdir_p(_MPDF_TEMP_PATH); + + $format = $pagesize; + if ($orientation == 'landscape') { + $format .= '-L'; + } + + switch ($docLang) { + case 'zh': + case 'zh-tw': + case 'ja': + case 'ko': + $mode = '+aCJK'; + break; + default: + $mode = 'UTF-8-s'; + } + + parent::__construct([ + 'mode' => $mode, + 'format' => $format, + 'default_font_size' => $fontsize, + 'ImageProcessorClass' => DokuImageProcessorDecorator::class, + 'tempDir' => _MPDF_TEMP_PATH, //$conf['tmpdir'] . '/tmp/dwpdf' + 'SHYlang' => $docLang, + ]); + + $this->autoScriptToLang = true; + $this->baseScript = 1; + $this->autoVietnamese = true; + $this->autoArabic = true; + $this->autoLangToFont = true; + + $this->ignore_invalid_utf8 = true; + $this->tabSpaces = 4; + + // assumed that global language can be used, maybe Bookcreator needs more nuances? + $this->SetDirectionality($lang['direction']); + } + + /** + * Cleanup temp dir + */ + public function __destruct() + { + io_rmdir(_MPDF_TEMP_PATH, true); + } + + /** + * Decode all paths, since DokuWiki uses XHTML compliant URLs + * + * @param string $path + * @param string $basepath + */ + public function GetFullPath(&$path, $basepath = '') + { + $path = htmlspecialchars_decode($path); + parent::GetFullPath($path, $basepath); + } +} diff --git a/plugins/55/dw2pdf/MenuItem.php b/plugins/55/dw2pdf/MenuItem.php new file mode 100644 index 0000000..735e8ed --- /dev/null +++ b/plugins/55/dw2pdf/MenuItem.php @@ -0,0 +1,47 @@ +params['at'] = $DATE_AT; + } elseif ($REV) { + $this->params['rev'] = $REV; + } + } + + /** + * Get label from plugin language file + * + * @return string + */ + public function getLabel() + { + $hlp = plugin_load('action', 'dw2pdf'); + return $hlp->getLang('export_pdf_button'); + } +} diff --git a/plugins/55/dw2pdf/README b/plugins/55/dw2pdf/README new file mode 100644 index 0000000..40ae8af --- /dev/null +++ b/plugins/55/dw2pdf/README @@ -0,0 +1,40 @@ +dw2pdf Plugin for DokuWiki + +Export DokuWiki pages to PDF + +All documentation for this plugin can be found at +http://www.dokuwiki.org/plugin:dw2pdf + +If you install this plugin manually, make sure it is installed in +lib/plugins/dw2pdf/ - if the folder is called different it +will not work! + +Please refer to http://www.dokuwiki.org/plugins for additional info +on how to install plugins in DokuWiki. + +---- + +Notes on updating the mpdf library. The library is installed by composer +but results are checked into the plugin repository. Similar to what we do +in DokuWiki core. Because mpdf has some dependencies that are already +satisfied in DokuWiki core, they do not need to be installed by the plugin +again. To do so we declare them as replaced in the composer.json. The +.gitignore is used to skip checking in unneeded library files like examples +etc. + +Updating should be done via composer update --no-dev --prefer-dist + +---- +Copyright (C) Andreas Gohr , + Luigi Micco + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +See the COPYING file in your DokuWiki folder for details diff --git a/plugins/55/dw2pdf/_test/ActionPagenameSortTest.php b/plugins/55/dw2pdf/_test/ActionPagenameSortTest.php new file mode 100644 index 0000000..f7188d6 --- /dev/null +++ b/plugins/55/dw2pdf/_test/ActionPagenameSortTest.php @@ -0,0 +1,104 @@ +assertLessThan(0, $action->cbPagenameSort(['id' => 'bar'], ['id' => 'bar:start'])); + $this->assertGreaterThan(0, $action->cbPagenameSort(['id' => 'bar:bar'], ['id' => 'bar:start'])); + } + + /** + * @return array + * @see testPageNameSort + */ + public function providerPageNameSort() + { + return [ + [ + 'start pages sorted', + [ + 'bar', + 'bar:start', + 'bar:alpha', + 'bar:bar', + ], + ], + [ + 'pages and subspaces mixed', + [ + 'alpha', + 'beta:foo', + 'gamma', + ], + ], + [ + 'full test', + [ + 'start', + '01_page', + '10_page', + 'bar', + 'bar:start', + 'bar:1_page', + 'bar:2_page', + 'bar:10_page', + 'bar:22_page', + 'bar:aa_page', + 'bar:aa_page:detail1', + 'bar:zz_page', + 'foo', + 'foo:start', + 'foo:01_page', + 'foo:10_page', + 'foo:foo', + 'foo:zz_page', + 'ns', + 'ns:01_page', + 'ns:10_page', + 'ns:ns', + 'ns:zz_page', + 'zz_page', + ], + ], + ]; + } + + /** + * @dataProvider providerPageNameSort + * @param string $comment + * @param array $expected + */ + public function testPagenameSort($comment, $expected) + { + // prepare the array as expected in the sort function + $prepared = []; + foreach ($expected as $line) { + $prepared[] = ['id' => $line]; + } + + // the input is random + $input = $prepared; + shuffle($input); + + // run sort + $action = new \action_plugin_dw2pdf(); + usort($input, [$action, 'cbPagenameSort']); + + $this->assertSame($prepared, $input); + } +} + diff --git a/plugins/55/dw2pdf/_test/DokuImageProcessorTest.php b/plugins/55/dw2pdf/_test/DokuImageProcessorTest.php new file mode 100644 index 0000000..556cadf --- /dev/null +++ b/plugins/55/dw2pdf/_test/DokuImageProcessorTest.php @@ -0,0 +1,73 @@ +assertEquals($expected_file, $actual_file, '$file ' . $msg); + $this->assertEquals($expected_orig_srcpath, $actual_orig_srcpath, '$orig_srcpath ' . $msg); + } + +} diff --git a/plugins/55/dw2pdf/_test/GeneralTest.php b/plugins/55/dw2pdf/_test/GeneralTest.php new file mode 100644 index 0000000..8c6d5b0 --- /dev/null +++ b/plugins/55/dw2pdf/_test/GeneralTest.php @@ -0,0 +1,86 @@ +assertFileExists($file); + + $info = confToHash($file); + + $this->assertArrayHasKey('base', $info); + $this->assertArrayHasKey('author', $info); + $this->assertArrayHasKey('email', $info); + $this->assertArrayHasKey('date', $info); + $this->assertArrayHasKey('name', $info); + $this->assertArrayHasKey('desc', $info); + $this->assertArrayHasKey('url', $info); + + $this->assertEquals('dw2pdf', $info['base']); + $this->assertRegExp('/^https?:\/\//', $info['url']); + $this->assertTrue(mail_isvalid($info['email'])); + $this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']); + $this->assertTrue(false !== strtotime($info['date'])); + } + + /** + * Test to ensure that every conf['...'] entry in conf/default.php has a corresponding meta['...'] entry in + * conf/metadata.php. + */ + public function testPluginConf(): void + { + $conf_file = __DIR__ . '/../conf/default.php'; + $meta_file = __DIR__ . '/../conf/metadata.php'; + + if (!file_exists($conf_file) && !file_exists($meta_file)) { + self::markTestSkipped('No config files exist -> skipping test'); + } + + if (file_exists($conf_file)) { + include($conf_file); + } + if (file_exists($meta_file)) { + include($meta_file); + } + + $this->assertEquals( + gettype($conf), + gettype($meta), + 'Both ' . DOKU_PLUGIN . 'dw2pdf/conf/default.php and ' . DOKU_PLUGIN . 'dw2pdf/conf/metadata.php have to exist and contain the same keys.' + ); + + if ($conf !== null && $meta !== null) { + foreach ($conf as $key => $value) { + $this->assertArrayHasKey( + $key, + $meta, + 'Key $meta[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'dw2pdf/conf/metadata.php' + ); + } + + foreach ($meta as $key => $value) { + $this->assertArrayHasKey( + $key, + $conf, + 'Key $conf[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'dw2pdf/conf/default.php' + ); + } + } + + } +} diff --git a/plugins/55/dw2pdf/_test/RendererTest.php b/plugins/55/dw2pdf/_test/RendererTest.php new file mode 100644 index 0000000..4c5ebd0 --- /dev/null +++ b/plugins/55/dw2pdf/_test/RendererTest.php @@ -0,0 +1,43 @@ + $level) { + $actualbookmarklevel = $this->callInaccessibleMethod($Renderer, 'calculateBookmarklevel', [$level]); + $this->assertEquals($expectedbookmarklevels[$i], $actualbookmarklevel, "index:$i, lvl:$level"); + } + } +} diff --git a/plugins/55/dw2pdf/_test/SyntaxExportLinkTest.php b/plugins/55/dw2pdf/_test/SyntaxExportLinkTest.php new file mode 100644 index 0000000..d0a6a2b --- /dev/null +++ b/plugins/55/dw2pdf/_test/SyntaxExportLinkTest.php @@ -0,0 +1,46 @@ +.:|Foo~~'); + $expected_parser_response = array( + 'plugin', + array( + 'dw2pdf_exportlink', + array( + 'link' => '?do=export_pdfns&book_ns=foo:bar&book_title=Foo', + 'title' => 'Export namespace "foo:bar:" to file Foo.pdf', + 5, + 1, + ), + 5, + '~~PDFNS>.:|Foo~~', + ), + 1, + ); + $this->assertEquals($expected_parser_response, $parser_response[2]); + $renderer_response = p_render('xhtml', $parser_response, $info); + $expected_renderer_response = 'doku.php?id=foo:bar:start&do=export_pdfns&book_ns=foo:bar&book_title=Foo" class="wikilink2" title="foo:bar:start" rel="nofollow" data-wiki-id="foo:bar:start">Export namespace "foo:bar:" to file Foo.pdf'; + $trimmed_renderer_response = substr($renderer_response, strpos($renderer_response, 'doku.php'), -5); + $trimmed_renderer_response = trim($trimmed_renderer_response); + $this->assertEquals($expected_renderer_response, $trimmed_renderer_response); + } +} + diff --git a/plugins/55/dw2pdf/action.php b/plugins/55/dw2pdf/action.php new file mode 100644 index 0000000..1b66573 --- /dev/null +++ b/plugins/55/dw2pdf/action.php @@ -0,0 +1,1122 @@ + + * @author Andreas Gohr + */ +class action_plugin_dw2pdf extends ActionPlugin +{ + /** + * Settings for current export, collected from url param, plugin config, global config + * + * @var array + */ + protected $exportConfig; + /** @var string template name, to use templates from dw2pdf/tpl/