From: gggeek Date: Wed, 21 Dec 2022 15:22:19 +0000 (+0000) Subject: bring back old doc-building toolchain based on sh/php scripts instead of pakefile... X-Git-Tag: 4.9.4~54 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=99a5fe55cb77da1182945b6a8be9a1872ee5afc5;p=plcapi.git bring back old doc-building toolchain based on sh/php scripts instead of pakefile, as it is more in line with modern practices or running CD in containers --- diff --git a/.gitignore b/.gitignore index 6b586b47..9eb7cb7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ /.scannerwork /.idea -/build/* +/doc/api +/doc/build/.phpdoc +/doc/build/composer.lock +/doc/build/vendor +/doc/manual/phpxmlrpc_manual.html +/doc/manual/phpxmlrpc_manual.pdf /vendor/* /.phpunit.result.cache /composer.lock diff --git a/doc/build/composer.json b/doc/build/composer.json index 2f062f4f..5532b34f 100644 --- a/doc/build/composer.json +++ b/doc/build/composer.json @@ -2,6 +2,7 @@ "name": "phpxmlrpc/phpxmlrpc-doc-toolchain", "require": { "php": "^5.3.0 || ^7.0 || ^8.0", + "ext-dom": "*", "ext-xsl": "*", "indeyets/pake": "^1.99", "docbook/docbook-xsl": "^1.79", diff --git a/doc/build/convert.php b/doc/build/convert.php new file mode 100644 index 00000000..75b085c1 --- /dev/null +++ b/doc/build/convert.php @@ -0,0 +1,88 @@ +load($doc); +$xsl = new DOMDocument; +$xsl->load($xss); + +// Configure the transformer +$processor = new XSLTProcessor; +if (version_compare(PHP_VERSION, '5.4', "<")) { + if (defined('XSL_SECPREF_WRITE_FILE')) { + ini_set("xsl.security_prefs", XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE); + } +} else { + // the php online docs only mention setSecurityPrefs, but somehow some installs have setSecurityPreferences... + if (method_exists('XSLTProcessor', 'setSecurityPrefs')) { + $processor->setSecurityPrefs(XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE); + } else { + $processor->setSecurityPreferences(XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE); + } +} +if (is_dir($target)) +{ + if (!$processor->setParameter('', 'base.dir', $target)) { + error("KO setting param base.dir"); + } +} + +// attach the xsl rules +$processor->importStyleSheet($xsl); + +$out = $processor->transformToXML($xml); + +if (!is_dir($target)) { + if (!file_put_contents($target, $out)) { + error("KO saving output to '{$target}'"); + } +} + +info("OK"); + +// *** functions *** + +function info($msg) +{ + echo "$msg\n"; +} + +function error($msg, $errcode=1) +{ + fwrite(STDERR, "$msg\n"); + exit($errcode); +} diff --git a/doc/build/custom.fo.xsl b/doc/build/custom.fo.xsl new file mode 100644 index 00000000..074bc9fa --- /dev/null +++ b/doc/build/custom.fo.xsl @@ -0,0 +1,102 @@ + + + + + + + + + + +1 +no +ansi +0 +1 +php +A4 +1 + + + 80% + + + + + + + + + + + + + + + + + + + + + + + + + + + ( void ) + + + ( ) + + + + + + ( ... ) + + + + + + + ( + + + + + + + + + + + , + + + ) + + + + + + + + + + + + = + + + + + diff --git a/doc/build/generate.sh b/doc/build/generate.sh new file mode 100755 index 00000000..87c6712e --- /dev/null +++ b/doc/build/generate.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -e + +cd "$(dirname -- "$(dirname -- "${BASH_SOURCE[0]}")")" + +# API docs + +php ./build/vendor/bin/phpdoc run --cache-folder './build/.phpdoc' -d "$(realpath ../src/)" -t './api' --title PHP-XMLRPC --defaultpackagename PHPXMLRPC + +# User Manual + +# HTML (single file) from asciidoc +asciidoctor -d book -o './manual/phpxmlrpc_manual.html' './manual/phpxmlrpc_manual.adoc' + +# PDF file from asciidoc via docbook and apache fop +asciidoctor -d book -b docbook -o './build/phpxmlrpc_manual.xml' './manual/phpxmlrpc_manual.adoc' +php ./build/convert.php './build/phpxmlrpc_manual.xml' './build/custom.fo.xsl' './manual/phpxmlrpc_manual.fo.xml' +fop ./manual/phpxmlrpc_manual.fo.xml ./manual/phpxmlrpc_manual.pdf +rm ./build/phpxmlrpc_manual.xml ./manual/phpxmlrpc_manual.fo.xml diff --git a/doc/build/setup_tools.sh b/doc/build/setup_tools.sh index 6a6bb4ab..c4aa14ad 100644 --- a/doc/build/setup_tools.sh +++ b/doc/build/setup_tools.sh @@ -7,22 +7,16 @@ set -e sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ asciidoctor fop git unzip zip -PHPPKG=$(dpkg --list | grep php | grep cli | awk '{print $2}') +PHPPKG=$(dpkg --list | grep php | grep cli | grep -v -F '(default)' | awk '{print $2}') sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${PHPPKG/cli/xsl}" -cd "$(dirname -- $(dirname -- $(dirname -- ${BASH_SOURCE[0]})))" -if [ ! -d build/tools ]; then - mkdir build/tools -fi -if [ -L "$(pwd)/build/tools/composer.json" ]; then - rm "$(pwd)/build/tools/composer.json" -fi -ln -s $(pwd)/doc/build/composer.json $(pwd)/build/tools/composer.json -cd build/tools -# in case we are switching between php versions, aleways reinstall every tool with the corect version... +cd "$(dirname -- "${BASH_SOURCE[0]}")" +# in case we are switching between php versions, always reinstall every tool with the correct version... if [ -f composer.lock ]; then rm composer.lock fi composer install --no-dev +#sudo chown -R "$(id -u):$(id -g)" vendor + # required as of phpdoc 3.1.2 sed -r -i -e "s|resource: '%kernel\\.project_dir%/vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Php'|resource: '%kernel.project_dir%/../reflection/src/phpDocumentor/Reflection/Php'|g" ./vendor/phpdocumentor/phpdocumentor/config/reflection.yaml diff --git a/pakefile.php b/pakefile.php deleted file mode 100644 index 9d2513bf..00000000 --- a/pakefile.php +++ /dev/null @@ -1,427 +0,0 @@ - 'asciidoctor', - 'fop' => 'fop', - 'php' => 'php', - 'zip' => 'zip', - ); - protected static $options = array( - 'repo' => 'https://github.com/gggeek/phpxmlrpc', - 'branch' => 'master', - 'workspace' => null - ); - - public static function libVersion() - { - if (self::$libVersion == null) - throw new \Exception('Missing library version argument'); - return self::$libVersion; - } - - /// @todo allow this to be set via an option - public static function buildDir() - { - return self::$buildDir; - } - - public static function workspaceDir() - { - return self::option('workspace') != '' ? self::option('workspace') : self::buildDir().'/workspace'; - } - - public static function toolsDir() - { - return self::buildDir().'/tools'; - } - - // most likely things will break if this one is moved outside the BuildDir - public static function distDir() - { - return self::buildDir().'/xmlrpc-'.self::libVersion(); - } - - // these will be generated in BuildDir - public static function distFiles() - { - return array( - 'xmlrpc-'.self::libVersion().'.tar.gz', - 'xmlrpc-'.self::libVersion().'.zip', - ); - } - - public static function getOpts($args=array(), $cliOpts=array()) - { - if (count($args) > 0) - // throw new \Exception('Missing library version argument'); - self::$libVersion = $args[0]; - - foreach (self::$tools as $name => $binary) { - if (isset($cliOpts[$name])) { - self::$tools[$name] = $cliOpts[$name]; - } - } - - foreach (self::$options as $name => $value) { - if (isset($cliOpts[$name])) { - self::$options[$name] = $cliOpts[$name]; - } - } - - //pake_echo('---'.self::$libVersion.'---'); - } - - /** - * @param string $name - * @return string - */ - public static function tool($name) - { - return self::$tools[$name]; - } - - /** - * @param string $name - * @return string - */ - public static function option($name) - { - return self::$options[$name]; - } - - /** - * @param string $inFile - * @param string $xssFile - * @param string $outFileOrDir - * @throws \Exception - */ - public static function applyXslt($inFile, $xssFile, $outFileOrDir) - { - if (!file_exists($inFile)) { - throw new \Exception("File $inFile cannot be found"); - } - if (!file_exists($xssFile)) { - throw new \Exception("File $xssFile cannot be found"); - } - - $docbookFoXslPath = realpath(Builder::buildDir().'/tools/vendor/docbook/docbook-xsl/fo/docbook.xsl'); - $docbookChunkXslPath = realpath(Builder::buildDir().'/tools/vendor/docbook/docbook-xsl/xhtml/chunk.xsl'); - file_put_contents( - $xssFile, - str_replace( - array('%fo-docbook.xsl%', '%docbook-chunk.xsl%'), - array($docbookFoXslPath, $docbookChunkXslPath), - file_get_contents($xssFile) - ) - ); - - // Load the XML source - $xml = new \DOMDocument(); - $xml->load($inFile); - $xsl = new \DOMDocument(); - $xsl->load($xssFile); - - // Configure the transformer - $processor = new \XSLTProcessor(); - if (version_compare(PHP_VERSION, '5.4', "<")) { - if (defined('XSL_SECPREF_WRITE_FILE')) { - ini_set("xsl.security_prefs", XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE); - } - } else { - // the php online docs only mention setSecurityPrefs, but somehow some installs have setSecurityPreferences... - if (method_exists('XSLTProcessor', 'setSecurityPrefs')) { - $processor->setSecurityPrefs(XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE); - } else { - $processor->setSecurityPreferences(XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE); - } - } - $processor->importStyleSheet($xsl); // attach the xsl rules - - if (is_dir($outFileOrDir)) { - if (!$processor->setParameter('', 'base.dir', realpath($outFileOrDir))) { - echo "setting param base.dir KO\n"; - } - } - - $out = $processor->transformToXML($xml); - - if (!is_dir($outFileOrDir)) { - file_put_contents($outFileOrDir, $out); - } - } - - public static function highlightPhpInHtml($content) - { - $startTag = '
';
-        $endTag = '
'; - - //$content = file_get_contents($inFile); - $last = 0; - $out = ''; - while (($start = strpos($content, $startTag, $last)) !== false) { - $end = strpos($content, $endTag, $start); - $code = substr($content, $start + strlen($startTag), $end - $start - strlen($startTag)); - if ($code[strlen($code) - 1] == "\n") { - $code = substr($code, 0, -1); - } - - $code = str_replace(array('>', '<'), array('>', '<'), $code); - $code = highlight_string('<?php 
', '', $code); - - $out = $out . substr($content, $last, $start + strlen($startTag) - $last) . $code . $endTag; - $last = $end + strlen($endTag); - } - $out .= substr($content, $last, strlen($content)); - - return $out; - } -} - -} - -namespace { - -use PhpXmlRpc\Builder; - -function run_default($task=null, $args=array(), $cliOpts=array()) -{ - echo "Syntax: pake {\$pake-options} \$task \$lib-version [\$git-tag] {\$task-options}\n"; - echo "\n"; - echo " Run 'pake help' to list all pake options\n"; - echo " Run 'pake -T' to list available tasks\n"; - echo " Run 'pake -P' to list all available tasks (including hidden ones) and their dependencies\n"; - echo "\n"; - echo " Task options:\n"; - echo " --repo=REPO URL of the source repository to clone. Defaults to the official github repo.\n"; - echo " --branch=BRANCH The git branch to build from. Defaults to 'master'\n"; - echo " --workspace=DIR The dir where to check out source code. Defaults to build/workspace\n"; - echo " --asciidoctor=ASCIIDOCTOR Location of the asciidoctor command-line tool\n"; - echo " --fop=FOP Location of the apache fop command-line tool\n"; - echo " --php=PHP Location of the php command-line interpreter\n"; - echo " --zip=ZIP Location of the zip tool\n"; -} - -function run_getopts($task=null, $args=array(), $cliOpts=array()) -{ - Builder::getOpts($args, $cliOpts); -} - -/** - * Downloads source code in the build workspace directory, optionally checking out the given branch/tag - * @todo allow using current installation / dir as source, bypassing git clone in workspace - at least for doc generation - */ -function run_init($task=null, $args=array(), $cliOpts=array()) -{ - // download the current version into the workspace - $targetDir = Builder::workspaceDir(); - - // check if workspace exists and is not already set to the correct repo - if (is_dir($targetDir) && pakeGit::isRepository($targetDir)) { - $repo = new pakeGit($targetDir); - $remotes = $repo->remotes(); - if (trim($remotes['origin']['fetch']) != Builder::option('repo')) { - throw new Exception("Directory '$targetDir' exists and is not linked to correct git repo"); - } - - /// @todo we should just fetch if we are checking out a tag, but pull if we are checking out a branch. - /// Also, we should only pull after having checked out the correct branch... - $repo->pull(); - } else { - pake_mkdirs(dirname($targetDir)); - $repo = pakeGit::clone_repository(Builder::option('repo'), Builder::workspaceDir()); - } - - $repo->checkout(Builder::option('branch')); -} - -/** - * Runs all the build steps. - * - * (does nothing by itself, as all the steps are managed via task dependencies) - */ -function run_build($task=null, $args=array(), $cliOpts=array()) -{ -} - -function run_clean_doc() -{ - pake_remove_dir(Builder::workspaceDir().'/doc/api'); - $finder = pakeFinder::type('file')->name('*.html'); - pake_remove($finder, Builder::workspaceDir().'/doc/manual'); - $finder = pakeFinder::type('file')->name('*.xml'); - pake_remove($finder, Builder::workspaceDir().'/doc/manual'); -} - -/** - * Generates documentation in all formats - */ -function run_doc($task=null, $args=array(), $cliOpts=array()) -{ - // in - $srcDir = Builder::workspaceDir(); - // out - $docDir = Builder::workspaceDir().'/doc'; - - // API docs - - // from phpdoc comments using phpdocumentor - $cmd = Builder::tool('php'); - pake_sh("$cmd " . Builder::toolsDir(). "/vendor/bin/phpdoc run --cache-folder ".Builder::buildDir()."/.phpdoc -d ".$srcDir.'/src'." -t ".$docDir.'/api --title PHP-XMLRPC --defaultpackagename PHPXMLRPC'); - - // from phpdoc comments using Sami - deprecated on 2021/12, as Sami is abandonware - /*$samiConfig = <<files() - ->exclude('debugger') - ->exclude('demo') - ->exclude('doc') - ->exclude('tests') - ->in('./build/workspace'); - return new Sami\Sami(\$iterator, array( - 'title' => 'PHP-XMLRPC', - 'build_dir' => 'build/workspace/doc/api', - 'cache_dir' => 'build/cache', - )); -EOT; - file_put_contents('build/sami_config.php', $samiConfig); - $cmd = Builder::tool('php'); - pake_sh("$cmd " . Builder::toolsDir(). "/vendor/bin/sami.php update -vvv build/sami_config.php");*/ - - // User Manual - - // html (single file) from asciidoc - $cmd = Builder::tool('asciidoctor'); - pake_sh("$cmd -d book -o $docDir/manual/phpxmlrpc_manual.html $srcDir/doc/manual/phpxmlrpc_manual.adoc"); - - // then docbook from asciidoc - /// @todo create phpxmlrpc_manual.xml with the good version number - /// @todo create phpxmlrpc_manual.xml with the date set to the one of last commit (or today?) - pake_sh("$cmd -d book -b docbook -o $docDir/manual/phpxmlrpc_manual.xml $srcDir/doc/manual/phpxmlrpc_manual.adoc"); - - # Other tools for docbook... - # - # jade cmd yet to be rebuilt, starting from xml file and putting output in ./out dir, e.g. - # jade -t xml -d custom.dsl xmlrpc_php.xml - # - # convertdoc command for xmlmind xxe editor - # convertdoc docb.toHTML xmlrpc_php.xml -u out - # - # saxon + xerces xml parser + saxon extensions + xslthl: adds a little syntax highlighting - # (bold and italics only, no color) for php source examples... - # java \ - # -classpath c:\programmi\saxon\saxon.jar\;c:\programmi\saxon\xslthl.jar\;c:\programmi\xerces\xercesImpl.jar\;C:\htdocs\xmlrpc_cvs\docbook-xsl\extensions\saxon65.jar \ - # -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl \ - # -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl \ - # -Dxslthl.config=file:///c:/htdocs/xmlrpc_cvs/docbook-xsl/highlighting/xslthl-config.xml \ - # com.icl.saxon.StyleSheet -o xmlrpc_php.fo.xml xmlrpc_php.xml custom.fo.xsl use.extensions=1 - - // HTML (multiple files) from docbook - discontinued, as we use the nicer-looking html gotten from asciidoc - /*Builder::applyXslt($docDir.'/manual/phpxmlrpc_manual.xml', $docDir.'/build/custom.xsl', $docDir.'/manual'); - // post process html files to highlight php code samples - foreach(pakeFinder::type('file')->name('*.html')->in($docDir.'/manual') as $file) - { - file_put_contents($file, Builder::highlightPhpInHtml(file_get_contents($file))); - }*/ - - // PDF file from docbook - - // convert to fo and then to pdf using apache fop - Builder::applyXslt($docDir.'/manual/phpxmlrpc_manual.xml', $docDir.'/build/custom.fo.xsl', $docDir.'/manual/phpxmlrpc_manual.fo.xml'); - $cmd = Builder::tool('fop'); - pake_sh("$cmd $docDir/manual/phpxmlrpc_manual.fo.xml $docDir/manual/phpxmlrpc_manual.pdf"); - - // cleanup - unlink($docDir.'/manual/phpxmlrpc_manual.xml'); - unlink($docDir.'/manual/phpxmlrpc_manual.fo.xml'); -} - -function run_clean_dist() -{ - pake_remove_dir(Builder::distDir()); - $finder = pakeFinder::type('file')->name(Builder::distFiles()); - pake_remove($finder, Builder::buildDir()); -} - -/** - * Creates the tarballs for a release - */ -function run_dist($task=null, $args=array(), $cliOpts=array()) -{ - // copy workspace dir into dist dir, without git - pake_mkdirs(Builder::distDir()); - $finder = pakeFinder::type('any')->ignore_version_control(); - /// @todo make sure we don't recurse - avoid 'build' dir - pake_mirror($finder, realpath(Builder::workspaceDir()), realpath(Builder::distDir())); - - // @todo remove unwanted files from dist dir - files and dirs from .gitattributes - - // also: do we still need to run dos2unix? - - // create tarballs - $cwd = getcwd(); - chdir(dirname(Builder::distDir())); - foreach(Builder::distFiles() as $distFile) { - // php can not really create good zip files via phar: they are not compressed! - if (substr($distFile, -4) == '.zip') { - $cmd = Builder::tool('zip'); - $extra = '-9 -r'; - pake_sh("$cmd $distFile $extra ".basename(Builder::distDir())); - } - else { - $finder = pakeFinder::type('any')->pattern(basename(Builder::distDir()).'/**'); - // see https://bugs.php.net/bug.php?id=58852 - $pharFile = str_replace(Builder::libVersion(), '_LIBVERSION_', $distFile); - pakeArchive::createArchive($finder, '.', $pharFile); - rename($pharFile, $distFile); - } - } - chdir($cwd); -} - -function run_clean_workspace($task=null, $args=array(), $cliOpts=array()) -{ - if (realpath(__DIR__) === realpath(Builder::workspaceDir())) { - throw new \Exception("Can not remove workspace dir, as it is where pakefile is located!"); - } - pake_remove_dir(Builder::workspaceDir()); -} - -/** - * Cleans up the whole build directory - * @todo 'make clean' usually just removes the results of the build, distclean removes all but sources - */ -function run_clean($task=null, $args=array(), $cliOpts=array()) -{ - pake_remove_dir(Builder::buildDir()); -} - -// helper task: display help text -pake_task( 'default' ); -// internal task: parse cli options -pake_task('getopts'); -pake_task('init', 'getopts'); -pake_task('doc', 'getopts', 'init', 'clean-doc'); -pake_task('build', 'getopts', 'init', 'doc'); -pake_task('dist', 'getopts', 'init', 'build', 'clean-dist'); -pake_task('clean-doc', 'getopts'); -pake_task('clean-dist', 'getopts'); -pake_task('clean-workspace', 'getopts'); -pake_task('clean', 'getopts'); - -}