package.xml000064400000100602117671476410006676 0ustar00 PhD doc.php.net A PHP based Docbook renderer PhD is a PHP based Docbook renderer aimed to replace Docbook-XSL and various other requirements needed to build the PHP.net documentation. Hannes Magnusson bjori bjori@php.net yes Moacir de Oliveira moacir moacir@php.net yes Christian Weiske cweiske cweiske@php.net yes Paul M Jones pmjones pmjones@php.net no Gwynne Raskind gwynne gwynne@php.net no Rudy Nappee loudi loudi@php.net no Richard Quadling rquadling rquadling@php.net yes 2012-06-16 1.1.6 1.1.0 stable stable BSD Style - Fixed indexing of content with markup. (Hannes) - Added support for generate-changelog-for, extension-membership and related phpdoc PI. (Hannes) 5.3.0 1.8.0 PhD_Generic doc.php.net libxml xmlreader dom sqlite3 zlib PhD_PHP doc.php.net PhD_PEAR doc.php.net PhD_IDE doc.php.net posix haru windows 0.1 0.1 snapshot devel 2007-10-01 BSD Style - Initial release 0.1.0 0.1.0 beta devel 2007-10-20 BSD Style - Added example numbering. (Hannes) - Improved support for modifiers in fieldsynopsis. (Hannes) - Remove () from refname when looking for version info, reported by Paul Reinheimer. (Hannes) - Print notes inline with its title, reported by Philip Olson. (Hannes) - Check if we have an open "{" before we print "}". (Hannes) - Escape the version info. (Richard Q.) - Fixed variablelist titles. (Hannes) - Fixed table info titles. (Hannes) - Fixed empty table cells, reported by Mark Wiesemann. (Hannes) - Fixed table title markup, reported by Richard Q. (Hannes) - Fixed non-closing b element for empty <title />s, reported by Joshua Thompson and Philip Olson. (Hannes) - Fixed bug#43013 (Description rather then function name for right arrows on extension pages). (Richard Q.) - Fixed bug#42906 (docs.php.net bold instead of links). (Hannes) - Fixed bug#42860 (cannot render <orgname> element). (Hannes) - Fixed bug#42845 (Copyright page has no TOC). (Hannes) - Language support (for autogenerated texts): * Bulgarian (by Kouber Saparev) * Czech (by Jakub Vrana) * German (by Oliver Albers) * Italian (by Marco Cucinato) * Japanese (by TAKAGI Masahiro) * Polish (by Jaroslaw Glowacki) * Brazilian Portuguese (by Diego Feitosa) * Romanian (by Simion Onea) 0.2.0 0.2.0 beta devel 2007-11-08 BSD Style - Added partial rendering. (Hannes) - Added various verbosity levels. (Hannes) - Added getopt() parsing for few configuration options. (Hannes) - Added support for errorcode, symbol and superscript elements (used by few translations). (Hannes) - Suppressed the contrib element. (Hannes) - Fixed bug#43192 (Chunked HTML output difficult to use without TOC). (Edward Z. Yang) - Fixed bug#43191 (build.php fails to included necessary theme dependencies). (Edward Z. Yang, Richard Q) 0.2.1 0.2.1 beta devel 2007-12-30 BSD Style - Multiple <term>s should be line seperated. (Hannes) - Fixed autogenerated links to methods. (Edward Z.) - Compressed methodnames in classsynopsis. (Edward Z.) - Added HTML headers for the bightml theme. (Hannes) - Removed warnings about missing translation files. (Hannes) 0.2.2 0.2.2 beta devel 2008-01-30 BSD Style - Removed support for phnotify. (Hannes) - Added index chaching. (Edward Z.) - Added option (-l/--list) to list the supported formats/themes.(Hannes) - Added support for linkend in fieldsynopsis varnames. (Hannes) - Added autogenerated "Edited by" text for <editor>. (Hannes) - Added autogenerated "by" text for the first <author> element in <authorgroup>. (Hannes) - Added missing closing "}" for classsynopsis. (Hannes) - Fixed E_NOTICE on empty references. (Hannes) - Fixed weird error message when no arguments are given, reported by Tony. (Hannes) - Fixed typos in the argument descriptions (--help), reported by Tony. (Hannes) - Fixed bug#43972 (PhD doesn't warn on missing partial IDs). (Hannes) - Fixed bug#43904 (PhD doesn't detect <section> without xml:id). (Hannes) - Fixed bug#43489 (Class synopsis return types are not links). (Hannes) - Fixed bug#43440 (Wrong encoding on some parts of the page). (Hannes) - Fixed bug#43428 (Empty TOC). (Hannes) - Fixed bug#43421 (All intra-document hyperlinks broken in the Single HTML file form of manual). (Hannes) - Fixed bug#43416 (Function links do not render as links). (Hannes) 0.2.3 0.2.3 beta beta 2008-03-31 BSD Style - Added initial hCalendar support for <author>. (Hannes) - Added initial eRDF support for <refentry>. (Hannes) - Added support for <footnote> and <footnoteref>. (Gwynne, Hannes) - Added anchor generation for various elements. (Hannes) - Added option (-s/--skip) to skip rendering of chunks. (Hannes) - Added option (-o/--output) to specify output directory (FR#43193). (Richard) - Added support for <sect4> titles . (Gwynne) - Added an 'infdec' role to <literal> in XHTML. (Gwynne) - Fixed couple of typos in PhD info messages. (Richard Q.) - Reformatted package.xml for readability and consistency. (Gwynne) - Merged README.RENDERER into README and updated README with current information. (Gwynne) - Gwynne is a developer of PhD, unfortunately. (Gwynne) - Made 'Example #' text localizeable. (Gwynne) - Added Russion support (for autogenerated texts). (Tony) - Updated translations: - Japanese (Masahiro) - Brazilian Portuguese (Felipe) - German (Mark) 0.2.4 0.2.4 beta beta 2008-05-24 BSD Style - Fixed bug#44906 (Missing space after modifier in properties list). (Hannes) - Fixed bug#44881 (Class constants with $). (Hannes) - Fixed bug#44786 (Remove irrelevant version information). (Hannes) - Fixed bug#44785 (Separating <title> from <note>). (Hannes) - Fixed bug#44776 (Request for change in titles). (Hannes) - Fixed bug#44750 (Request for generic phd logger). (Hannes) - Fixed bug#44690 (Please restore manual main page). (Hannes) - Added French support (for autogenerated texts). (Yannick) - Added Danish support (for autogenerated texts). (Kalle) - Added Swedish support (for autogenerated texts). (Kalle) - Added experimental option (-c/--color) for color in verbose output. (Gwynne) 0.3.0 0.3.0 beta beta 2008-07-24 BSD Style - Added CHM output format. (Rudy) - Added KDevelop (Index & Table of contents) output theme. (Rudy) - Added Man page output format. (Rudy) - Added support for phpdoc:exception. (Hannes) 0.3.1 0.3.1 beta beta 2008-08-23 BSD Style - Added PDF output format. (Rudy) - Added support for phpdoc:classref. (Hannes) - Added support for phpdoc:varentry. (Hannes) - Added support for the phpdoc howto. (Hannes) - Renamed phpdoc:exception to phpdoc:exceptionref. (Hannes) - Fixed bug#45627 (Unix manpages using non-standard folder name). (Rudy) - Fixed bug#45626 (Unix manpages should be gzipped). (Rudy) - Fixed bug#45618 (Bad filenames in man pages). (Rudy) - Fixed unclosed div element on set pages. (Hannes) 0.4.0 0.4.0 beta beta 2008-10-20 BSD Style - Added PEAR XHTML theme. (Rudy, Christian) - Added support for new elements (Christian) * glossentry * glossdef * glosslist * important * paramdef * personblurb * phrase * prompt * releaseinfo * spanspec * qandadiv - Improved <email> support (now creates mailto: links). (Christian) - Chunks without xml:id are no longer chunked. (Christian) - Fixed bug#46252 (Class properties links to a function if theres one with the same name). (Hannes) - Fixed bug#46094 (and then from now on italic). (Hannes) - Fixed bug#45071 (Links to require/include(_once) not rendered). (Hannes) - Fixed a bug where it was only possible to pass one parameter to phd.bat. (Kalle) - Fixed a bug where it wasn't possible to have paths with spaces in when using phd.bat. (Kalle) - Fixed xhtml validation issue for itemizedlist. (Christian) 0.4.1 0.4.1 beta beta 2008-11-08 BSD Style - Fixed bug #46413 Weird examples in Unix manual pages (Rudy) - Added varlistentries to the CHM index. (Rudy) - Language support (for autogenerated texts): * Turkish (by Nilgün Belma Bugüner) - Prevent prev/next errors in combination with chunking elements without ids (Christian) - Support double nested chunking elements without ids (Christian) - Make table captions render properly in peardoc (Christian) - add support for <arg> and <cmdsynopsis> used in peardoc (Christian) - Fix bug #46415: Don't chunk first section on parent site when it has children. (Christian) - Implement request #46411: Allow random chunking depths (Christian) - Implement request #46412: Allow random TOC depths (Christian) - Implement request #46493: Implement new pear api linking tag (Christian) - Make pear chm theme work (Christian) - Make html generated in pear themes nearly 100% valid XHTML (Christian) - Make "Prev" links work correctly on last pages (e.g. last in chapter) (Christian) - Change double quotes to single ones, gives speedup for pear builds (Brett) - Docblock enhancements and Coding Standards fixes (Brett) 0.4.2 0.4.2 beta beta 2008-12-18 BSD Style - Added support for phd:chunk="false" attribute on chunks. (Christian) - Added Turkish support for CHM. (Nilgun) - Added option (-L/--lang language) to use for CHM headers. (Hannes) - Added support for orderedlist numeration. (Hannes) - Added fallback to PHP_Compat getopt() on Windows. (Christian) - Added anchors for tips, warnings, important and notes. (Nilgun) - <interfacename> now automagically links to interfaces. (Hannes) - Automatically use the phpdoc configure.php generated version information file if it exists. (Hannes) - Removed default border for formal tables. (Philip) 0.4.3 0.4.3 beta beta 2009-01-17 BSD Style - Automatically add anchors for refsect roles. (Hannes) - Added description for seealso links. (Hannes) - Fixed a bug where prefaces had unlisted children. (Hannes) - Compressed methodnames in classsynopsis again. (Hannes) - Added Next/Prev and Image Zoom buttons to CHM build (Richard Quadling) - Fixed bug#46941 (FR: Find broken links). (Hannes) - Fixed bug#46931 (wrong order of the META tag in the HEAD element). (Chen Gang) - Fixed bug#46924 (parameter elements force incorrect line breaks). (Hannes) - Fixed bug#46726 (Incorrect HTML output). (Hannes) - Fixed bug#46714 (change deprecated ereg_replace(Since PHP 5.3.0) to preg_replace). (Chen Gang) - Fixed bug#45570 (PhD doesn't use the colspec "align" attribute in xhtml output). (Hannes) - Fixed bug#45318 (table colspec rendering issues). (Hannes) - Fixed bug#44598 (Much space on 'expected output' section). (Hannes) 0.4.4 0.4.4 beta beta 2009-02-16 BSD Style - Add support for <package> in pear theme (Christian) - Replace ereg_replace with preg_replace - Implement request #47201: Allow custom source code highlighter (e.g. Geshi) (Christian) - Fix HTML problems with empty paragraphs in examples and qandaset questions (Christian) - Support <uri> and <screenshot> (Christian) - Copy images automatically using MediaManager (Christian) - Fixed bug#47362: <h1> tag gets omitted in bightml (Christian) - Fixed bug#47196: improve render of initializer tag (Laurent) - Fixed encoding issues in the Polish CHM builds. (Jarosław Głowacki) - Update polish phd translation (Jarosław Głowacki) - Generate syntactically correct php files for pearweb when description or title have a quote in it. (Christian) - Improve object orientated version info support (Hannes) 0.4.5 0.4.5 beta beta 2009-02-19 BSD Style - Fix bug #47408: Same image directory used for each theme (Christian) - Fix bug #47413: pear themes don't work when rendered together at once (Christian) - Change copyright year to 2007-2009 (Christian) - Fix PEAR chm manual title for french (Laurent) - Fix PEAR chm navbar alignment (Laurent) 0.4.6 0.4.6 beta beta 2009-03-07 BSD Style - Added language support with unknownversion into phpdotnet theme. (Philip) - phpbook/phpbook-xsl/version.xml is no longer used (Hannes) - Fix PEAR bug #15967: Wrong ID passed to pearweb manualFooter() (Christian) 0.4.7 0.4.7 beta beta 2009-05-07 BSD Style - Added support for <token> (Christian) - Added support for <simplesect> (Richard Q, Nilgun) - Improved support for <tag> classes (Christian) - Improved support for <variablelist> (Nilgun) - Updated translations: * Danish (Kalle) * Swedish (Kalle) * Turkish (Nilgun) 0.4.8 0.4.8 beta beta 2009-08-27 BSD Style - Add support for external troff highlighter in man pages (Christian). - Add title attribute to anchor tags so address can be seen in CHM files for external links (Richard Q.). - CVS->SVN langs migration (Philip). - Fixed bug#49006 (The manpage format groups function arguments incorrectly). (Moacir) - Fixed bug#49005 (Reference sign in function prototypes in the manpage rendering). (Moacir) 0.9.0 0.9.0 beta beta 2009-09-08 BSD Style - Use namespaces (Moacir) - Use PEAR classname conventions (Christian) - Add support for dbhtml Process Instructions (PI) (Moacir) - Add the --package option (Moacir) - Add the Generic Package (Moacir) - Add the phpdotnet/phd namespace (Christian) - Kill themes and add a concept of "packages" (Moacir) - Rewrite indexer (Hannes, Rudy, Moacir) - Rewrite program flow (Hannes) 0.9.1 0.9.1 beta beta 2009-12-21 BSD Style - Added fallback option to find English files when unable to find translated files (Richard Quadling) - Added VERBOSE_ERRORS, VERBOSE_INFO and VERBOSE_WARNINGS to group verbose levels (Richard Quadling) - Added VERBOSE_MISSING_ATTRIBUTES verbose level (Richard Quadling) - Separated PhD verbose messages into informational and warnings (Richard Quadling) - PhD verbose warning messages are colored magenta (Richard Quadling) - Added MediaManger->findFile() method to return full filename of required image (Richard Quadling) - Added the --css option (Moacir) - Added the --forceindex option (Christian) - Fixed bug #45071 - Links to require/include(_once) not rendered (Moacir) - Fixed bug #47406 - Add support for external css (Moacir) - Fixed bug #48264 - No style for HTML version of php docs (Moacir) - Fixed bug #49547 - default of --color is true, not false (Richard Quadling) - Fixed bug #49675 - Missing links in SeeAlso (Moacir) - Fixed bug #49743 - Problem with functions both procedural and oo (Moacir) - Fixed bug #49839 - Patch to clean up peardoc output (Michael Gauthier) - Fixed --noindex option which did not work properly (Christian) - Fixed --verbose option which did not work properly (Moacir) 1.0.0 1.0.0 stable stable 2010-03-11 BSD Style - Use textual descriptions for VERBOSE_xxx messages (Richard Quadling) - Implemented FR#50668 - add xinclude processing in phd. (Shahar Evron) - Added support for DBTimestamp Processing Instruction. (Moacir) - Added support for edition, inlinemediaobject, exceptionname, firstterm, trademark and edition Docbook5 elements. (Hannes) - Updated translations: (Kalle) - Danish - Swedish - Disabled colored output on Windows. (Kalle) - Fixed bug #45098 - named constants require long opt. (Hannes) - Fixed bug #51070 - Double acronym tags in HTML output. (Moacir) 1.0.1 1.0.0 stable stable 2010-08-10 BSD Style - Now searches the include-path for custom package classes in the \phpdotnet\phd namespace (pmjones) - Added --ext command line option to specify filename extension (pmjones) - Added --saveconfig option to generate a config file to load (Hannes) - Added 'package_dirs' config option to specify package directories to autoload from (Hannes) - Corrected grammar in Danish translation + fixed encoding (Daniel Egeberg) - Allow colored output on Windows, but not by default (Richard Quadling) - Allow <void/> as return type for methodsynopsis tags rather than <type>void</type> (Richard Quadling) - Added support for <sidebar> (Richard Quadling) - Now builds toc/* by default for the PHP package, and added --notoc option to use cached version (Philip) - Changed the VERBOSE_DEFAULT error level to exclude VERBOSE_TOC_WRITING messages (Philip) - Fixed encoding problems with the function iconv() in the CHM format (Moacir) - Fixed the --lang option that was creating an infinite recursion (Moacir) 1.1.0 1.1.0 stable stable 2011-03-07 BSD Style - Added support for package cli options (Moacir) - Do not disable color configuration settings when loading from phd.config.php on Windows when saved setting is enabled (Richard Quadling) - Using saveconfig once no longer saves the config on every call to render (Richard Quadling) - Restoring a saved config now correctly sets the error reporting level to the restored verbosity (Richard Quadling) 1.1.1 1.1.0 stable stable 2011-06-21 BSD Style - Improved the performance of the indexer by ~ 75%. (Hannes) - Added --quit option to quit after processing command line params. Useful when used with --saveconfig to just save the config (Richard Quadling) - Output directory can now be nested (for example /rendering/PHP/en) (Richard Quadling) - New translations: - Spanish (Pablo Bangueses) - Serbian (Nikola Smolenski) - Fixed bug#52664 - "Missing" example#1. (Hannes) - Added --packagedir option to use external packages. (Moacir) - Added Format::getDebugTree() method to allow the current location in the tree to be reportable. (Richard Quadling) 1.1.2 1.1.0 stable stable 2011-06-21 BSD Style - Added phpdoc PI handler to handle manually added version information (bug#51853). (Hannes) - Added the possiblity of adding version information for classes (bug#49927). (Hannes) 1.1.3 1.1.0 stable stable 2012-03-01 BSD Style - Removed redundant align and valign attributes on table-related tags (Alexey Borzov) 1.1.4 1.1.0 stable stable 2012-04-06 BSD Style - Bump version 1.1.5 1.1.0 stable stable 2012-06-07 BSD Style - Show individual package version in --version. (Hannes) - Fixed bug#54217 Warn about nonexisting parameters. (Moacir) - Fixed bug#50725 Generate nav links at top of function index (Peter Cowburn) - Fixed bug#47392 Option to specify filename for bightmls. (Hannes) PhD-1.1.6/phpdotnet/phd/data/langs/fr.xml000064400000002245117671476410013627 0ustar00
Autogenerated text toc Sommaire warning Avertissement note Note caution Attention tip Astuce by par editedby Édité par example Exemple #
PhD-1.1.6/phpdotnet/phd/data/langs/de.xml000064400000002157117671476410013612 0ustar00
Autogenerated text toc Inhaltsverzeichnis warning Warnung note Hinweis caution Achtung tip Tipp by von editedby Herausgegeben von example Beispiel #
PhD-1.1.6/phpdotnet/phd/data/langs/ja.xml000064400000003426117671476410013614 0ustar00
Autogenerated text toc 目次 warning 警告 note 注意 caution 警告 tip ヒント important 重要 by 著者 editedby 編集 example unknownversion バージョン情報なし。おそらく SVN 版にしか存在しないでしょう refname 名前 refsynopsis 書式 mediaobject [表示できません]
PhD-1.1.6/phpdotnet/phd/data/langs/ru.xml000064400000003705117671476410013650 0ustar00
Сгенерированный текст toc Содержание warning Внимание note Замечание caution Предостережение tip Подсказка important Важно by от editedby Под редакцией example Пример # unknownversion Информация о версии неизвестна, возможно, только в SVN refname ИМЯ refsynopsis СОДЕРЖАНИЕ mediaobject [НЕОТОБРАЖАЕМЫЙ МЕДИА-ФАЙЛ]
PhD-1.1.6/phpdotnet/phd/data/langs/sv.xml000064400000003516117671476410013652 0ustar00
Auto-genererad text toc Innehlls Frteckning warning Varsel note Notera caution Varsel tip Tipp important Viktigt by af editedby Redigerat av example Exempel # unknownversion Ingen version information, det kan finnas bara i SVN refname NAMN refsynopsis SYNOPSIS mediaobject [INTE VISNINGSBART MEDIA]
PhD-1.1.6/phpdotnet/phd/data/langs/ro.xml000064400000002136117671476410013637 0ustar00
Autogenerated text toc Cuprins warning Avertizare note Notă caution Precauţie tip Sfat by by editedby Edited By example Example #
PhD-1.1.6/phpdotnet/phd/data/langs/en.xml000064400000004162117671476410013622 0ustar00
Autogenerated text toc Table of Contents warning Warning note Note caution Caution tip Tip important Important by by editedby Edited By example Example # unknownversion No version information available, might only be in SVN refname NAME refsynopsis SYNOPSIS mediaobject [NOT DISPLAYABLE MEDIA] Version Version Function Function Description Description
PhD-1.1.6/phpdotnet/phd/data/langs/tr.xml000064400000003430117671476410013642 0ustar00
Üretilmiş metin toc İçindekiler warning Uyarı note Bilginize caution Dikkat tip İpucu important Önemli by Yazan editedby Düzenleyen example Örnek unknownversion Bir sürüm bilgisi bulunamadı; sadece SVN'de olabilir. refname İSİM refsynopsis SÖZDİZİMİ mediaobject [ORTAM GÖSTERİME UYGUN DEĞİL]
PhD-1.1.6/phpdotnet/phd/data/langs/it.xml000064400000002156117671476410013635 0ustar00
Autogenerated text toc Indice dei contenuti warning Avviso note Nota caution Attenzione tip Suggerimento by by editedby Edited By example Example #
PhD-1.1.6/phpdotnet/phd/data/langs/pl.xml000064400000002175117671476410013635 0ustar00
Autogenerated text toc Spis treści warning Ostrzeżenie note Informacja caution Uwaga tip Wskazówka by Opracowany przez editedby Pod redakcją example Przykład #
PhD-1.1.6/phpdotnet/phd/data/langs/da.xml000064400000003521117671476410013602 0ustar00
Autogenereret tekst toc Indholdsfortegnelse warning Advarsel note Note caution Advarsel tip Tip important Vigtigt by af editedby Redigeret af example Eksempel # unknownversion Ingen versionsoplysninger tilgængelige, findes måske kun i SVN refname NAVN refsynopsis SYNOPSIS mediaobject [MEDIE KAN IKKE VISES]
PhD-1.1.6/phpdotnet/phd/data/langs/bg.xml000064400000002225117671476410013606 0ustar00
Autogenerated text toc Съдържание warning Предупреждение note Забележка caution Внимание tip Съвет by by editedby Edited By example Example #
PhD-1.1.6/phpdotnet/phd/data/langs/pt_BR.xml000064400000003410117671476410014221 0ustar00
Texto autogerado toc Índice warning Aviso note Nota caution Cuidado tip Dica important Importante by por editedby Editado por example Exemplo # unknownversion Não há informação de versão disponível, talvez apenas no SVN refname NOME refsynopsis SINOPSE mediaobject [MÍDIA NÃO DISPONÍVEL]
PhD-1.1.6/phpdotnet/phd/data/langs/cs.xml000064400000002136117671476410013624 0ustar00
Autogenerated text toc Obsah warning Varování note Poznámka caution Výstraha tip Tip by by editedby Edited By example Example #
PhD-1.1.6/phpdotnet/phd/data/langs/es.xml000064400000003473117671476410013633 0ustar00
Autogenerated text toc Tabla de contenidos warning Advertencia note Nota caution Precaución tip Sugerencia important Importante by por editedby Editado por example Ejemplo # unknownversion No hay información de versión disponible, podría estar únicamente en SVN refname NOMBRE refsynopsis SINOPSIS mediaobject [MULTIMEDIA NO DISPONIBLE]
PhD-1.1.6/phpdotnet/phd/data/langs/sr.xml000064400000003653117671476410013650 0ustar00
Autogenerated text toc Садржај warning Упозорење note Напомена caution Опрез tip Савет important Важно by од editedby Уредник example Пример бр.  unknownversion Нема информације о верзији, можда је само у СВН-у refname ИМЕ refsynopsis ПРЕГЛЕД mediaobject [МЕДИЈ СЕ НЕ МОЖЕ ПРИКАЗАТИ]
PhD-1.1.6/phpdotnet/phd/Format/Abstract/Manpage.php000064400000002546117671476410015541 0ustar00highlight(trim($str), $this->role, 'troff'); } public function TEXT($str) { $ret = preg_replace( '/[ \n\t]+/', ' ', $str); // Escape \ ' and NUL byte $ret = addcslashes($ret, "\\'\0"); // No newline if current line begins with ',', ';', ':', '.' if (in_array($ret[0], array(",", ";", ":", "."))) { return $ret; } return $ret; } public function transformFromMap($open, $tag, $name, $attrs, $props) { if ($tag === '') { return $tag; } $isMacro = $tag[0] == "."; if ($open) { if ($isMacro && strpos($tag, "\n") === false) { return "\n" . $tag . "\n"; } return "\n" . $tag; } return ($isMacro ? "" : "\\fP"); } public function createLink($for, &$desc = null, $type = Format::SDESC) { } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Format/Abstract/PDF.php000064400000114351117671476410014600 0ustar00pdfDoc; } public function setPdfDoc($pdfDoc) { $this->pdfDoc = $pdfDoc; } public function UNDEF($open, $name, $attrs, $props) { if ($open) { trigger_error("No mapper found for '{$name}'", E_USER_WARNING); } $this->pdfDoc->setFont(PdfWriter::FONT_NORMAL, 14, array(1, 0, 0)); // Helvetica 14 red $this->pdfDoc->appendText(($open ? "<" : ""); $this->pdfDoc->revertFont(); return ""; } public function CDATA($str) { $this->pdfDoc->appendText(utf8_decode(trim($str))); return ""; } public function transformFromMap($open, $tag, $name, $attrs, $props) { return ""; } public function createLink($for, &$desc = null, $type = Format::SDESC){} public function TEXT($str) {} } class PdfWriter { // Font type constants (for setFont()) const FONT_NORMAL = 0x01; const FONT_ITALIC = 0x02; const FONT_BOLD = 0x03; const FONT_VERBATIM = 0x04; const FONT_VERBATIM_ITALIC = 0x05; const FONT_MANUAL = 0x06; // "Objects" constants (for add()) const PARA = 0x10; const INDENTED_PARA = 0x11; const TITLE = 0x12; const DRAW_LINE = 0x13; const LINE_JUMP = 0x14; const PAGE = 0x15; const TITLE2 = 0x16; const VERBATIM_BLOCK = 0x17; const ADMONITION = 0x18; const ADMONITION_CONTENT = 0x19; const END_ADMONITION = 0x1A; const URL_ANNOTATION = 0x1B; const LINK_ANNOTATION = 0x1C; const ADD_BULLET = 0x1D; const FRAMED_BLOCK = 0x1E; const END_FRAMED_BLOCK = 0x1F; const TITLE3 = 0x20; const TABLE = 0x21; const TABLE_ROW = 0x22; const TABLE_ENTRY = 0x23; const TABLE_END_ENTRY = 0x24; const END_TABLE = 0x25; const TABLE_END_ROW = 0x26; const ADD_NUMBER_ITEM = 0x27; const IMAGE = 0x28; // Page format const VMARGIN = 56.7; // = 1 centimeter const HMARGIN = 56.7; // = 1 centimeter const LINE_SPACING = 2; // nb of points between two lines const INDENT_SPACING = 10; // nb of points for indent const DEFAULT_SHIFT = 20; // default value (points) for shifted paragraph private $SCALE; // nb of points for 1 centimeter private $PAGE_WIDTH; // in points private $PAGE_HEIGHT; // in points private $haruDoc; private $pages = array(); private $currentPage; private $currentPageNumber; private $currentBookName; private $currentFont; private $currentFontSize; private $currentFontColor; private $fonts; private $oldFonts = array(); private $text; private $vOffset = 0; private $hOffset = 0; private $lastPage = array( "vOffset" => 0, "hOffset" => 0, ); private $permanentLeftSpacing = 0; private $permanentRightSpacing = 0; private $appendToBuffer = false; // To append afterwards private $buffer = array( /* array( 'text' => "", 'font' => "", 'size' => "", 'color' => "", )*/ ); private $current = array( "leftSpacing" => 0, "rightSpacing" => 0, "oldVPosition" => 0, "vOffset" => 0, "newVOffset" => 0, "pages" => array(), "row" => array(), "align" => "", "char" => "", "charOffset" => 0, ); // To temporarily store $current(s) private $old = array(); function __construct($pageWidth = 210, $pageHeight = 297) { // Initialization of properties $this->haruDoc = new \HaruDoc; $this->haruDoc->addPageLabel(1, \HaruPage::NUM_STYLE_DECIMAL, 1, "Page "); $this->haruDoc->setPageMode(\HaruDoc::PAGE_MODE_USE_OUTLINE); $this->haruDoc->setPagesConfiguration(2); // Page format $this->SCALE = 72/25.4; $this->PAGE_WIDTH = $pageWidth * $this->SCALE; $this->PAGE_HEIGHT = $pageHeight * $this->SCALE; // Set fonts $this->fonts["Helvetica"] = $this->haruDoc->getFont("Helvetica", "WinAnsiEncoding"); $this->fonts["Helvetica-Bold"] = $this->haruDoc->getFont("Helvetica-Bold", "WinAnsiEncoding"); $this->fonts["Helvetica-Oblique"] = $this->haruDoc->getFont("Helvetica-Oblique", "WinAnsiEncoding"); $this->fonts["Courier"] = $this->haruDoc->getFont("Courier", "WinAnsiEncoding"); $this->fonts["Courier-Oblique"] = $this->haruDoc->getFont("Courier-Oblique", "WinAnsiEncoding"); // Add first page and default font settings $this->currentFont = $this->fonts["Helvetica"]; $this->currentFontSize = 12; $this->currentFontColor = array(0, 0, 0); // Black $this->nextPage(); $this->haruDoc->addPageLabel(1, \HaruPage::NUM_STYLE_DECIMAL, 1, "Page "); } public function getCurrentPage() { return $this->currentPage; } public function setCompressionMode($mode) { $this->haruDoc->setCompressionMode($mode); } // Append text into the current position public function appendText($text) { // if ($this->vOffset > $this->current["charOffset"] + 3*LINE_SPACING + 3*$this->currentFontSize) // $this->vOffset = $this->current["charOffset"] + 3*LINE_SPACING + 3*$this->currentFontSize; if ($this->appendToBuffer) { array_push($this->buffer, array( "text" => $text, "font" => $this->currentFont, "size" => $this->currentFontSize, "color" => $this->currentFontColor )); return; } $this->currentPage->beginText(); do { // Clear the whitespace if it begins the line or if last char is a special char if (strpos($text, " ") === 0 && ($this->hOffset == 0 || in_array($this->current["char"], array("&", "$")))) { $text = substr($text, 1); } // Number of chars allowed in the current line $nbCarac = $this->currentFont->measureText($text, ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->hOffset - $this->permanentLeftSpacing - $this->permanentRightSpacing), $this->currentFontSize, $this->currentPage->getCharSpace(), $this->currentPage->getWordSpace(), true); // If a the text content can't be appended (either there is no whitespaces, // either the is not enough space in the line) if ($nbCarac === 0) { $isEnoughSpaceOnNextLine = $this->currentFont->measureText($text, ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->permanentLeftSpacing - $this->permanentRightSpacing), $this->currentFontSize, $this->currentPage->getCharSpace(), $this->currentPage->getWordSpace(), true); if ($isEnoughSpaceOnNextLine) { $this->vOffset += $this->currentFontSize + self::LINE_SPACING; $this->hOffset = 0; $isLastLine = false; continue; } else { $nbCarac = $this->currentFont->measureText($text, ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->hOffset - $this->permanentLeftSpacing - $this->permanentRightSpacing), $this->currentFontSize, $this->currentPage->getCharSpace(), $this->currentPage->getWordSpace(), false); } } $isLastLine = ($nbCarac == strlen($text)); $textToAppend = substr($text, 0, $nbCarac); $text = substr($text, $nbCarac); // Append text (in a new page if needed) with align if ($this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset) < self::VMARGIN) { $this->currentPage->endText(); $this->current["pages"][] = $this->currentPage; $this->nextPage(); $this->currentPage->beginText(); } if ($this->current["align"] == "center") { $spacing = $this->PAGE_WIDTH - 2*self::HMARGIN - $this->permanentLeftSpacing - $this->permanentRightSpacing - $this->currentPage->getTextWidth($textToAppend); $this->currentPage->textOut(self::HMARGIN + $this->hOffset + $this->permanentLeftSpacing + $spacing/2, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset), $textToAppend); } elseif ($this->current["align"] == "right") { $spacing = $this->PAGE_WIDTH - 2*self::HMARGIN - $this->permanentLeftSpacing - $this->permanentRightSpacing - $this->currentPage->getTextWidth($textToAppend); $this->currentPage->textOut(self::HMARGIN + $this->hOffset + $this->permanentLeftSpacing + $spacing, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset), $textToAppend); } else { // left $this->currentPage->textOut(self::HMARGIN + $this->hOffset + $this->permanentLeftSpacing, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset), $textToAppend); } if ($textToAppend) $this->current["char"] = $textToAppend{strlen($textToAppend)-1}; // Offsets for next line if (!$isLastLine) { $this->vOffset += $this->currentFontSize + self::LINE_SPACING; $this->hOffset = 0; } else { $this->hOffset += $this->currentPage->getTextWidth($textToAppend); } } while(!$isLastLine); // While it remains chars to append $this->currentPage->endText(); $this->current["charOffset"] = $this->vOffset; } // Same function one line at a time public function appendOneLine($text) { if (strpos($text, " ") === 0 && ($this->hOffset == 0 || in_array($this->current["char"], array("&", "$")))) { $text = substr($text, 1); } $this->currentPage->beginText(); $nbCarac = $this->currentFont->measureText($text, ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->hOffset - $this->permanentLeftSpacing - $this->permanentRightSpacing), $this->currentFontSize, $this->currentPage->getCharSpace(), $this->currentPage->getWordSpace(), true); // If a the text content can't be appended (either there is no whitespaces, // either the is not enough space in the line) if ($nbCarac === 0) { $isEnoughSpaceOnNextLine = $this->currentFont->measureText($text, ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->permanentLeftSpacing - $this->permanentRightSpacing), $this->currentFontSize, $this->currentPage->getCharSpace(), $this->currentPage->getWordSpace(), true); if ($isEnoughSpaceOnNextLine) { $this->currentPage->endText(); return $text; } else { $nbCarac = $this->currentFont->measureText($text, ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->hOffset - $this->permanentLeftSpacing - $this->permanentRightSpacing), $this->currentFontSize, $this->currentPage->getCharSpace(), $this->currentPage->getWordSpace(), false); } } $isLastLine = ($nbCarac == strlen($text)); $textToAppend = substr($text, 0, $nbCarac); $text = substr($text, $nbCarac); // Append text (in a new page if needed) if ($this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset) < self::VMARGIN) { $this->currentPage->endText(); $this->current["pages"][] = $this->currentPage; $this->nextPage(); $this->currentPage->beginText(); } $this->currentPage->textOut(self::HMARGIN + $this->hOffset + $this->permanentLeftSpacing, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset), $textToAppend); if ($textToAppend) $this->current["char"] = $textToAppend{strlen($textToAppend)-1}; $this->hOffset += $this->currentPage->getTextWidth($textToAppend); $this->currentPage->endText(); $this->current["charOffset"] = $this->vOffset; return ($isLastLine ? null : $text); } public function setAppendToBuffer($appendToBuffer) { $this->appendToBuffer = $appendToBuffer; } public function appendBufferNow() { foreach($this->buffer as $row) { if ($row["text"] == "\n") { $this->lineJump(); } else { $this->setFont(self::FONT_MANUAL, $row["size"], $row["color"], $row["font"]); $this->appendText($row["text"]); $this->revertFont(); } } $this->buffer = array(); } public function add($type, $option = null) { if ($this->appendToBuffer) return; switch ($type) { case self::INDENTED_PARA: $this->lineJump(); $this->indent(); break; case self::PARA: $this->lineJump(); break; case self::VERBATIM_BLOCK: $this->setFont(self::FONT_VERBATIM, 10, array(0.3, 0.3, 0.3)); $this->lineJump(); break; case self::TITLE: $this->setFont(self::FONT_BOLD, 20); $this->lineJump(); break; case self::TITLE2: $this->setFont(self::FONT_BOLD, 14); $this->lineJump(); break; case self::TITLE3: $this->setFont(self::FONT_BOLD, 12); $this->lineJump(); break; case self::DRAW_LINE: $this->traceLine($option); break; case self::LINE_JUMP: if ($option) $this->lineJump($option); else $this->lineJump(); break; case self::PAGE: $this->nextPage(); break; case self::ADMONITION: $this->beginAdmonition(); break; case self::ADMONITION_CONTENT: $this->admonitionContent(); break; case self::END_ADMONITION: $this->endAdmonition(); break; case self::URL_ANNOTATION: $this->appendUrlAnnotation($option[0], $option[1]); break; case self::LINK_ANNOTATION: return $this->prepareInternalLinkAnnotation($option); break; case self::ADD_BULLET: $this->indent(-self::INDENT_SPACING-$this->currentPage->getTextWidth(chr(149))); $this->appendText(chr(149)); // ANSI Bullet $this->indent(0); break; case self::ADD_NUMBER_ITEM: $this->indent(-self::INDENT_SPACING-$this->currentPage->getTextWidth($option)); $this->appendText($option); $this->indent(0); break; case self::FRAMED_BLOCK: $this->beginFrame(); break; case self::END_FRAMED_BLOCK: $this->endFrame($option); break; case self::TABLE: $this->addTable($option); break; case self::END_TABLE: $this->endTable(); break; case self::TABLE_ROW: $this->newTableRow($option[0], $option[1]); break; case self::TABLE_END_ROW: $this->endTableRow(); break; case self::TABLE_ENTRY: $this->beginTableEntry($option[0], $option[1], $option[2]); break; case self::TABLE_END_ENTRY: $this->endTableEntry(); break; case self::IMAGE: $this->addImage($option); break; default: trigger_error("Unknown object type : {$type}", E_USER_WARNING); break; } } // Switch font on-the-fly public function setFont($type, $size = null, $color = null, $font = null) { if ($this->currentPage == null) return false; $this->oldFonts[] = array($this->currentFont, $this->currentFontSize, $this->currentFontColor); $this->currentFontSize = ($size ? $size : $this->currentFontSize); if ($color && count($color) === 3) { $this->setColor($color[0], $color[1], $color[2]); $this->currentFontColor = $color; } else $this->setColor($this->currentFontColor[0], $this->currentFontColor[1], $this->currentFontColor[2]); switch ($type) { case self::FONT_NORMAL: $this->currentPage->setFontAndSize($this->currentFont = $this->fonts["Helvetica"], $this->currentFontSize); break; case self::FONT_ITALIC: $this->currentPage->setFontAndSize($this->currentFont = $this->fonts["Helvetica-Oblique"], $this->currentFontSize); break; case self::FONT_BOLD: $this->currentPage->setFontAndSize($this->currentFont = $this->fonts["Helvetica-Bold"], $this->currentFontSize); break; case self::FONT_VERBATIM: $this->currentPage->setFontAndSize($this->currentFont = $this->fonts["Courier"], $this->currentFontSize); break; case self::FONT_VERBATIM_ITALIC: $this->currentPage->setFontAndSize($this->currentFont = $this->fonts["Courier-Oblique"], $this->currentFontSize); break; case self::FONT_MANUAL: $this->currentPage->setFontAndSize($this->currentFont = $font, $this->currentFontSize); break; default: trigger_error("Unknown font type : {$type}", E_USER_WARNING); break; } } // Back to the last used font public function revertFont() { $lastFont = array_pop($this->oldFonts); $this->currentFont = $lastFont[0]; $this->currentFontSize = $lastFont[1]; $this->currentFontColor = $lastFont[2]; $this->currentPage->setFontAndSize($lastFont[0], $lastFont[1]); $this->setColor($lastFont[2][0], $lastFont[2][1], $lastFont[2][2]); } // Change font color (1, 1, 1 = white, 0, 0, 0 = black) public function setColor($r, $g, $b) { if ($r < 0 || $r > 1 || $g < 0 || $g > 1 || $b < 0 || $b > 1) return false; $this->currentPage->setRGBStroke($r, $g, $b); $this->currentPage->setRGBFill($r, $g, $b); $this->currentFontColor = array($r, $g, $b); return true; } // Save the current PDF Document to a file public function saveToFile($filename) { $this->haruDoc->save($filename); } public function createOutline($description, $parentOutline = null, $opened = false) { $outline = $this->haruDoc->createOutline($description, $parentOutline); $dest = $this->currentPage->createDestination(); $dest->setXYZ(0, $this->currentPage->getHeight(), 1); $outline->setDestination($dest); $outline->setOpened($opened); return $outline; } public function shift($offset = self::DEFAULT_SHIFT) { $this->permanentLeftSpacing += $offset; } public function unshift($offset = self::DEFAULT_SHIFT) { $this->permanentLeftSpacing -= $offset; } public function vOffset($offset) { $this->vOffset += $offset; } private function indent($offset = self::INDENT_SPACING) { $this->hOffset = $offset; } // Jump to next page (or create a new one if none exists) private function nextPage() { $this->lastPage = array( "vOffset" => $this->vOffset, "hOffset" => $this->hOffset, ); $footerToAppend = false; $this->currentPageNumber++; if (isset($this->pages[$this->currentPageNumber])) { $this->currentPage = $this->pages[$this->currentPageNumber]; $this->vOffset = $this->currentFontSize; $this->hOffset = 0; } else { $this->pages[$this->currentPageNumber] = $this->haruDoc->addPage(); $this->currentPage = $this->pages[$this->currentPageNumber]; $this->currentPage->setTextRenderingMode(\HaruPage::FILL); $this->vOffset = $this->currentFontSize; $this->hOffset = ($this->hOffset ? $this->hOffset : 0); $footerToAppend = true; } if ($this->currentFont && $this->currentFontSize && $this->currentFontColor) { $this->currentPage->setFontAndSize($this->currentFont, $this->currentFontSize); $this->setColor($this->currentFontColor[0], $this->currentFontColor[1], $this->currentFontColor[2]); } if ($footerToAppend && $this->currentPageNumber > 1) { $this->currentPage->beginText(); $this->setFont(self::FONT_NORMAL, 12, array(0,0,0)); $this->currentPage->textOut($this->PAGE_WIDTH - self::HMARGIN - $this->currentPage->getTextWidth($this->currentPageNumber), self::VMARGIN - 30, $this->currentPageNumber); $this->revertFont(); $this->setFont(self::FONT_BOLD, 12, array(0,0,0)); $this->currentPage->textOut(self::HMARGIN, self::VMARGIN - 30, $this->currentBookName); $this->revertFont(); $this->currentPage->endText(); } } public function setCurrentBookName($currentBookName) { $this->currentBookName = $currentBookName; } // Set last page as the current page private function lastPage() { $this->currentPageNumber--; $this->currentPage = $this->pages[$this->currentPageNumber]; $this->vOffset = $this->lastPage["vOffset"]; $this->hOffset = $this->lastPage["hOffset"]; } // Returns true if a next page exists private function isNextPage() { return isset($this->pages[$this->currentPageNumber + 1]); } // Jump a line private function lineJump($nbLines = 1) { $this->vOffset += $nbLines * ($this->currentFontSize + self::LINE_SPACING); $this->hOffset = 0; } // Trace a line from the current position private function traceLine() { $this->lineJump(); $this->currentPage->rectangle(self::HMARGIN + $this->hOffset, $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset, $this->PAGE_WIDTH - 2*$this->hOffset - 2*self::HMARGIN, 1); $this->currentPage->stroke(); } private function beginAdmonition() { // If this admonition is inside another frame array_push($this->old, $this->current); $this->setFont(self::FONT_BOLD, 12); $this->lineJump(); // If no space for admonition title + interleave + admonition first line on this page, then creates a new one if (($this->PAGE_HEIGHT - 2*self::VMARGIN - $this->vOffset) < (3*$this->currentFontSize + 3*self::LINE_SPACING)) $this->nextPage(); $this->current["vOffset"] = $this->vOffset; $this->lineJump(); $this->permanentLeftSpacing += self::INDENT_SPACING; $this->permanentRightSpacing += self::INDENT_SPACING; $this->current["pages"] = array(); } private function admonitionContent() { if ($this->current["pages"]) $this->current["vOffset"] = 0; $this->beginFrame(); $this->revertFont(); $this->currentPage->rectangle(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset, $this->PAGE_WIDTH - 2*self::HMARGIN - ($this->permanentLeftSpacing - self::INDENT_SPACING) - ($this->permanentRightSpacing - self::INDENT_SPACING), $this->vOffset - $this->current["vOffset"]); $this->currentPage->stroke(); } private function endAdmonition() { $this->endFrame(); $this->permanentLeftSpacing -= self::INDENT_SPACING; $this->permanentRightSpacing -= self::INDENT_SPACING; $current = array_pop($this->old); $current["pages"] = array_merge($current["pages"], $this->current["pages"]); $this->current = $current; } private function beginFrame() { $this->lineJump(); $this->current["newVOffset"] = $this->vOffset; $this->current["pages"] = array(); } private function endFrame($dash = null) { $onSinglePage = true; foreach ($this->current["pages"] as $page) { $page->setRGBStroke(0, 0, 0); $page->setLineWidth(1.0); $page->setDash($dash, 0); // left border $page->moveTo(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), self::VMARGIN); $page->lineTo(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->current["newVOffset"]); // right border $page->moveTo($this->PAGE_WIDTH - self::HMARGIN - ($this->permanentRightSpacing - self::INDENT_SPACING), self::VMARGIN); $page->lineTo($this->PAGE_WIDTH - self::HMARGIN - ($this->permanentRightSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->current["newVOffset"]); $page->stroke(); $page->setDash(null, 0); $this->current["newVOffset"] = 0; $onSinglePage = false; } $this->currentPage->setRGBStroke(0, 0, 0); $this->currentPage->setLineWidth(1.0); $this->currentPage->setDash($dash, 0); // left border $this->currentPage->moveTo(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset); $this->currentPage->lineTo(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->current["newVOffset"]); // right border $this->currentPage->moveTo($this->PAGE_WIDTH - self::HMARGIN - ($this->permanentRightSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset); $this->currentPage->lineTo($this->PAGE_WIDTH - self::HMARGIN - ($this->permanentRightSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->current["newVOffset"]); // bottom border $this->currentPage->moveTo(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset); $this->currentPage->lineTo($this->PAGE_WIDTH - self::HMARGIN - ($this->permanentRightSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset); // top border (if frame's on a single page) if ($onSinglePage) { $this->currentPage->moveTo(self::HMARGIN + ($this->permanentLeftSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->current["newVOffset"]); $this->currentPage->lineTo($this->PAGE_WIDTH - self::HMARGIN - ($this->permanentRightSpacing - self::INDENT_SPACING), $this->PAGE_HEIGHT - self::VMARGIN - $this->current["newVOffset"]); } $this->currentPage->stroke(); $this->lineJump(); $this->currentPage->setDash(null, 0); $this->current["oldVPosition"] = 0; } // Append $text with an underlined blue style with a link to $url private function appendUrlAnnotation($text, $url) { $this->appendText(" "); $fromHOffset = $this->hOffset; // If more than one text line to append while ($text = $this->appendOneLine($text)) { // Trace the underline $this->currentPage->setLineWidth(1.0); $this->currentPage->setDash(null, 0); $this->currentPage->moveTo(self::HMARGIN + $this->permanentLeftSpacing + $fromHOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING)); $this->currentPage->lineTo(self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING)); $this->currentPage->stroke(); // Create link $annotationArea = array(self::HMARGIN + $this->permanentLeftSpacing + $fromHOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING), self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset - $this->currentFontSize)); $this->currentPage->createURLAnnotation($annotationArea, $url)->setBorderStyle(0, 0, 0); // Prepare the next line $this->vOffset += $this->currentFontSize + self::LINE_SPACING; $this->hOffset = 0; $fromHOffset = $this->hOffset; } // Trace the underline $this->currentPage->setLineWidth(1.0); $this->currentPage->setDash(null, 0); $this->currentPage->moveTo(self::HMARGIN + $this->permanentLeftSpacing + $fromHOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING)); $this->currentPage->lineTo(self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING)); $this->currentPage->stroke(); // Create link $annotationArea = array(self::HMARGIN + $this->permanentLeftSpacing + $fromHOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING), self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset - $this->currentFontSize)); $this->currentPage->createURLAnnotation($annotationArea, $url)->setBorderStyle(0, 0, 0); } // Append $text with an underlined blue style and prepare an internal link (which will be resolved later) private function prepareInternalLinkAnnotation($text) { $this->appendText(" "); $fromHOffset = $this->hOffset; $linkAreas = array(/* page, left, bottom, right, top */); // If more than one text line to append while ($text = $this->appendOneLine($text)) { // Create link $linkAreas[] = array($this->currentPage, self::HMARGIN + $this->permanentLeftSpacing + $fromHOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING), self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset - $this->currentFontSize)); // Prepare the next line $this->vOffset += $this->currentFontSize + self::LINE_SPACING; $this->hOffset = 0; $fromHOffset = $this->hOffset; } // Prepare link $linkAreas[] = array($this->currentPage, self::HMARGIN + $this->permanentLeftSpacing + $fromHOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset + self::LINE_SPACING), self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - (self::VMARGIN + $this->vOffset - $this->currentFontSize)); return $linkAreas; } public function resolveInternalLink($page, $rectangle, $destPage) { $page->setRGBStroke(0, 0, 1); // blue // Trace the underline $page->setLineWidth(1.0); $page->setDash(array(2), 1); $page->moveTo($rectangle[0], $rectangle[1]); $page->lineTo($rectangle[2], $rectangle[1]); $page->stroke(); // Create link $page->createLinkAnnotation($rectangle, $destPage->createDestination()) ->setBorderStyle(0, 0, 0); $page->setDash(null, 0); } public function addTable($colCount) { // If this table is inside another table or frame array_push($this->old, $this->current); $this->current["leftSpacing"] = $this->permanentLeftSpacing; $this->current["rightSpacing"] = $this->permanentRightSpacing; // First horizontal line $this->currentPage->moveTo(self::HMARGIN + $this->current["leftSpacing"], $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset); $this->currentPage->lineTo($this->PAGE_WIDTH - self::HMARGIN - $this->current["rightSpacing"], $this->PAGE_HEIGHT - self::VMARGIN - $this->vOffset); $this->currentPage->stroke(); } public function endTable() { $this->permanentLeftSpacing = $this->current["leftSpacing"]; $this->permanentRightSpacing = $this->current["rightSpacing"]; $this->lineJump(); $current = array_pop($this->old); $current["pages"] = array_merge($current["pages"], $this->current["pages"]); $this->current = $current; } public function newTableRow($colCount, $valign) { $this->current["vOffset"] = $this->vOffset; $this->current["row"]["cellCount"] = $colCount; $this->current["row"]["activeCell"] = 0; $this->current["row"]["hSize"] = ($this->PAGE_WIDTH - 2*self::HMARGIN - $this->current["leftSpacing"] - $this->current["rightSpacing"]) / $this->current["row"]["cellCount"]; $this->current["row"]["vPosition"] = 0; $this->current["row"]["pages"] = array(); $this->current["row"]["cutPolicy"] = array(1); $this->current["pages"] = array(); } public function beginTableEntry($colspan, $rowspan, $align) { $this->permanentLeftSpacing = ($this->current["row"]["activeCell"]++) * $this->current["row"]["hSize"] + self::LINE_SPACING + $this->current["leftSpacing"]; $this->permanentRightSpacing = $this->PAGE_WIDTH - 2*self::HMARGIN - ($this->current["row"]["activeCell"] + $colspan - 1) * $this->current["row"]["hSize"] - $this->current["leftSpacing"] + self::LINE_SPACING; foreach ($this->current["pages"] as $page) { $this->lastPage(); } $this->current["pages"] = array(); $this->hOffset = 0; $this->vOffset = $this->current["vOffset"] + $this->currentFontSize + self::LINE_SPACING; $this->current["align"] = $align; array_push($this->current["row"]["cutPolicy"], $colspan); } public function endTableEntry() { $this->current["align"] = ""; $newOffset = $this->vOffset + $this->currentFontSize + self::LINE_SPACING; if ($newOffset + $this->PAGE_HEIGHT * count($this->current["pages"]) > $this->current["row"]["vPosition"]) { $this->current["row"]["vPosition"] = $newOffset + $this->PAGE_HEIGHT * count($this->current["pages"]); } if (count($this->current["pages"]) > count($this->current["row"]["pages"])) { $this->current["row"]["pages"] = $this->current["pages"]; } } public function endTableRow() { $vOffset = $this->current["vOffset"]; while($this->isNextPage()) $this->nextPage(); // Vertical lines for ($i = 0, $x = self::HMARGIN + $this->current["leftSpacing"]; $i <= $this->current["row"]["cellCount"]; $i++, $x += $this->current["row"]["hSize"]) { // Don't trace vertical line if colspan if (($cellCount = array_shift($this->current["row"]["cutPolicy"])) > 1) { array_unshift($this->current["row"]["cutPolicy"], $cellCount - 1); continue; } foreach ($this->current["row"]["pages"] as $page) { $page->setRGBStroke(0, 0, 0); $page->moveTo($x, self::VMARGIN); $page->lineTo($x, $this->PAGE_HEIGHT - self::VMARGIN - $this->current["vOffset"]); $page->stroke(); $this->current["vOffset"] = 0; } $this->currentPage->moveTo($x, $this->PAGE_HEIGHT - self::VMARGIN - ($this->current["vOffset"])); $this->currentPage->lineTo($x, $this->PAGE_HEIGHT - self::VMARGIN - ($this->current["row"]["vPosition"] % $this->PAGE_HEIGHT)); $this->currentPage->stroke(); $this->current["vOffset"] = $vOffset; } // Horizontal line $this->currentPage->moveTo(self::HMARGIN + $this->current["leftSpacing"], $this->PAGE_HEIGHT - self::VMARGIN - ($this->current["row"]["vPosition"] % $this->PAGE_HEIGHT)); $this->currentPage->lineTo($this->PAGE_WIDTH - self::HMARGIN - $this->current["rightSpacing"], $this->PAGE_HEIGHT - self::VMARGIN - ($this->current["row"]["vPosition"] % $this->PAGE_HEIGHT)); $this->currentPage->stroke(); // Store position $this->vOffset = $this->current["row"]["vPosition"] % $this->PAGE_HEIGHT; // Store pages $last = array_pop($this->old); $last["pages"] = array_merge($last["pages"], $this->current["row"]["pages"]); array_push($this->old, $last); // Erase current properties $this->current["row"] = array(); } private function endsWith($str, $sub) { return ( substr( $str, strlen( $str ) - strlen( $sub ) ) === $sub ); } private function addImage($url) { $image = null; if ($this->endsWith(strtolower($url), ".png")) { $image = $this->haruDoc->loadPNG($url); } elseif ($this->endsWith(strtolower($url), ".jpg") || $this->endsWith(strtolower($url), ".jpeg")) { $image = $this->haruDoc->loadJPEG($url); } if ($image) { if ($this->PAGE_HEIGHT - $this->vOffset - 2*self::VMARGIN < $image->getHeight()) $this->nextPage(); $this->currentPage->drawImage($image, self::HMARGIN + $this->permanentLeftSpacing + $this->hOffset, $this->PAGE_HEIGHT - self::HMARGIN - $this->vOffset - $image->getHeight(), $image->getWidth(), $image->getHeight()); $this->hOffset = 0; $this->vOffset += $image->getWidth(); } } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Format/Abstract/XHTML.php000064400000007116117671476410015063 0ustar00'; } return ''; } public function TEXT($str) { return htmlspecialchars($str, ENT_QUOTES, "UTF-8"); } public function UNDEF($open, $name, $attrs, $props) { if ($open) { trigger_error("No mapper found for '{$name}'", E_USER_WARNING); } } public function CDATA($str) { switch($this->role) { case '': return '
'
                . htmlspecialchars($str, ENT_QUOTES, "UTF-8")
                . '
'; default: return '
' . $this->highlight(trim($str), $this->role, 'xhtml') . '
'; } } /* Functions from PhDThemeXhtml */ /** * Called after the constructor finished. * This is needed since themes set their outputdir and outputfile * in the constructor. That file/dir is used for mediamanager. * That means we cannot instantiate and complete the manager in our * constructor centrally. * * Each theme needs its own media manager, since the manager contains * the output path. * * @return void */ public function postConstruct() { $this->mediamanager = new MediaManager(Config::xml_root()); $outputdir = $this->getOutputDir(); if (isset($outputdir) && $outputdir) { $this->mediamanager->output_dir = $outputdir; } else { $this->mediamanager->output_dir = Config::output_dir() . '/' . strtolower($this->getFormatName()) . '-data/'; $this->mediamanager->relative_ref_path = basename($this->mediamanager->output_dir) . '/'; } } /* Functions from XHTMLPhDFormat */ /** * Closes a para tag when we are already in a paragraph. * * @return string HTML code * * @see $openPara * @see restorePara() */ public function escapePara() { if (!$this->openPara) { return ''; } if (!isset($this->escapedPara[$this->openPara])) { $this->escapedPara[$this->openPara] = 1; return '

'; } else { ++$this->escapedPara[$this->openPara]; return ''; } } /** * Opens a para tag again when we escaped one before. * * @return string HTML code * * @see $openPara * @see escapePara() */ public function restorePara() { if (!$this->openPara || !isset($this->escapedPara[$this->openPara])) { return ''; } if ($this->escapedPara[$this->openPara] == 1) { unset($this->escapedPara[$this->openPara]); return '

'; } else { --$this->escapedPara[$this->openPara]; return ''; } } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Format/Factory.php000064400000004541117671476410014032 0ustar00pversion; } public final function setPackageVersion($version) { $this->pversion = $version; } public final function getOutputFormats() { return array_keys($this->formats); } public final function registerOutputFormats($formats) { $this->formats = $formats; } public final function getOptionsHandler() { return $this->optionsHandler; } public final function registerOptionsHandler(Options_Interface $optionsHandler) { $this->optionsHandler = $optionsHandler; } protected final function setPackageName($name) { if (!is_string($name)) { throw new \Exception("Package names must be strings.."); } $this->packageName = $name; } public final function getPackageName() { return $this->packageName; } public final function createFormat($format) { if (isset($this->formats[$format]) && $this->formats[$format]) { $classname = __NAMESPACE__ . "\\" . $this->formats[$format]; $obj = new $classname(); if (!($obj instanceof Format)) { throw new \Exception("All Formats must inherit Format"); } return $obj; } trigger_error("This format is not supported by this package", E_USER_ERROR); } public static final function createFactory($package) { static $factories = array(); if (!is_string($package)) { throw new \Exception("Package name must be string.."); } if (!isset($factories[$package])) { $classname = __NAMESPACE__ . "\\Package_" . $package . "_Factory"; $factory = new $classname(); if (!($factory instanceof Format_Factory)) { throw new \Exception("All Factories must inherit Format_Factory"); } $factories[$package] = $factory; } return $factories[$package]; } public final function __toString() { return $this->getPackageName(); } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Options/Handler.php000064400000036646117671476410014216 0ustar00 'f:', // The format to render (xhtml, pdf...) 'noindex' => 'I', // Do not re-index 'forceindex' => 'r', // Force re-indexing under all circumstances 'notoc' => 't', // Do not re-create TOC 'docbook:' => 'd:', // The Docbook XML file to render from (.manual.xml) 'output:' => 'o:', // The output directory 'outputfilename:' => 'F:', // The output filename (only useful for bightml/bigpdf) 'partial:' => 'p:', // The ID to render (optionally ignoring its children) 'skip:' => 's:', // The ID to skip (optionally skipping its children too) 'verbose:' => 'v::', // Adjust the verbosity level 'list' => 'l', // List supported packages/formats 'lang::' => 'L:', // Language hint (used by the CHM) 'color:' => 'c:', // Use color output if possible 'highlighter:' => 'g:', // Class used as source code highlighter 'version' => 'V', // Print out version information 'help' => 'h', // Print out help 'package:' => 'P:', // The package of formats 'css:' => 'C:', // External CSS 'xinclude' => 'x', // Automatically process xinclude directives 'ext:' => 'e:', // The file-format extension to use, including the dot 'saveconfig::' => 'S::', // Save the generated config ? 'quit' => 'Q', // Do not run the render. Use with -S to just save the config. 'memoryindex' => 'M', // Use sqlite in memory rather then file 'packagedir' => 'k:', // Include path for external packages ); } public function option_M($k, $v) { $this->option_memoryindex($k, $v); } public function option_memoryindex($k, $v) { Config::set_memoryindex(true); } public function option_f($k, $v) { if ($k == "f") { return $this->option_format($k, $v); } else { return $this->option_outputfilename($k, $v); } } public function option_format($k, $v) { $formats = array(); foreach((array)$v as $i => $val) { if (!in_array($val, $formats)) { $formats[] = $val; } } Config::set_output_format($formats); } public function option_e($k, $v) { $this->option_ext($k, $v); } public function option_ext($k, $v) { $bool = self::boolval($v); if ($bool === false) { // `--ext=false` means no extension will be used $v = ""; Config::setExt($v); } elseif ($bool === null) { // `--ext=true` means use the default extension, // `--ext=".foo"` means use ".foo" as the extension Config::setExt($v); } } public function option_g($k, $v) { $this->option_highlighter($k, $v); } public function option_highlighter($k, $v) { Config::setHighlighter($v); } public function option_i($k, $v) { $this->option_noindex($k, 'true'); } public function option_noindex($k, $v) { Config::set_no_index(true); } public function option_r($k, $v) { $this->option_forceindex($k, 'true'); } public function option_forceindex($k, $v) { Config::set_force_index(true); } public function option_t($k, $v) { $this->option_notoc($k, 'true'); } public function option_notoc($k, $v) { Config::set_no_toc(true); } public function option_d($k, $v) { $this->option_docbook($k, $v); } public function option_docbook($k, $v) { if (is_array($v)) { trigger_error("Can only parse one file at a time", E_USER_ERROR); } if (!file_exists($v) || is_dir($v) || !is_readable($v)) { trigger_error(sprintf("'%s' is not a readable docbook file", $v), E_USER_ERROR); } Config::set_xml_root(dirname($v)); Config::set_xml_file($v); } public function option_o($k, $v) { $this->option_output($k, $v); } public function option_output($k, $v) { if (is_array($v)) { trigger_error("Only a single output location can be supplied", E_USER_ERROR); } if (!is_dir($v)) { mkdir($v, 0777, true); } if (!is_dir($v) || !is_readable($v)) { trigger_error(sprintf("'%s' is not a valid directory", $v), E_USER_ERROR); } $v = (substr($v, strlen($v) - strlen(DIRECTORY_SEPARATOR)) == DIRECTORY_SEPARATOR) ? $v : ($v . DIRECTORY_SEPARATOR); Config::set_output_dir($v); } public function option_outputfilename($k, $v) { if (is_array($v)) { trigger_error("Only a single output location can be supplied", E_USER_ERROR); } $file = basename($v); Config::set_output_filename($file); } public function option_p($k, $v) { if ($k == "P") { return $this->option_package($k, $v); } $this->option_partial($k, $v); } public function option_partial($k, $v) { $render_ids = Config::render_ids(); foreach((array)$v as $i => $val) { $recursive = true; if (strpos($val, "=") !== false) { list($val, $recursive) = explode("=", $val); if (!is_numeric($recursive) && defined($recursive)) { $recursive = constant($recursive); } $recursive = (bool) $recursive; } $render_ids[$val] = $recursive; } Config::set_render_ids($render_ids); } public function option_package($k, $v) { foreach((array)$v as $package) { if (!in_array($package, Config::getSupportedPackages())) { $supported = implode(', ', Config::getSupportedPackages()); trigger_error("Invalid Package (Tried: '$package' Supported: '$supported')", E_USER_ERROR); } } Config::set_package($v); } public function option_q($k, $v) { $this->option_quit($k, $v); } public function option_quit($k, $v) { Config::set_quit(true); } public function option_s($k, $v) { if ($k == "S") { return $this->option_saveconfig($k, $v); } $this->option_skip($k, $v); } public function option_skip($k, $v) { $skip_ids = Config::skip_ids(); foreach((array)$v as $i => $val) { $recursive = true; if (strpos($val, "=") !== false) { list($val, $recursive) = explode("=", $val); if (!is_numeric($recursive) && defined($recursive)) { $recursive = constant($recursive); } $recursive = (bool) $recursive; } $skip_ids[$val] = $recursive; } Config::set_skip_ids($skip_ids); } public function option_saveconfig($k, $v) { if (is_array($v)) { trigger_error(sprintf("You cannot pass %s more than once", $k), E_USER_ERROR); } // No arguments passed, default to 'true' if (is_bool($v)) { $v = "true"; } $val = self::boolval($v); if (is_bool($val)) { Config::set_saveconfig($v); } else { trigger_error("yes/no || on/off || true/false || 1/0 expected", E_USER_ERROR); } } public function option_v($k, $v) { if ($k[0] === 'V') { $this->option_version($k, $v); return; } $this->option_verbose($k, $v); } public function option_verbose($k, $v) { static $verbose = 0; foreach((array)$v as $i => $val) { foreach(explode("|", $val) as $const) { if (defined($const)) { $verbose |= (int)constant($const); } elseif (is_numeric($const)) { $verbose |= (int)$const; } elseif (empty($const)) { $verbose = max($verbose, 1); $verbose <<= 1; } else { trigger_error("Unknown option passed to --$k, '$const'", E_USER_ERROR); } } } Config::set_verbose($verbose); error_reporting($GLOBALS['olderrrep'] | $verbose); } public function option_l($k, $v) { if ($k == "L") { return $this->option_lang($k, $v); } $this->option_list($k, $v); } public function option_list($k, $v) { $packageList = Config::getSupportedPackages(); echo "Supported packages:\n"; foreach ($packageList as $package) { $formats = Format_Factory::createFactory($package)->getOutputFormats(); echo "\t" . $package . "\n\t\t" . implode("\n\t\t", $formats) . "\n"; } exit(0); } public function option_lang($k, $v) { Config::set_language($v); } public function option_c($k, $v) { if ($k == "C") { return $this->option_css($k, $v); } $this->option_color($k, $v); } public function option_color($k, $v) { if (is_array($v)) { trigger_error(sprintf("You cannot pass %s more than once", $k), E_USER_ERROR); } $val = self::boolval($v); if (is_bool($val)) { Config::setColor_output($val); } else { trigger_error("yes/no || on/off || true/false || 1/0 expected", E_USER_ERROR); } } public function option_css($k, $v) { $styles = array(); foreach((array)$v as $key => $val) { if (!in_array($val, $styles)) { $styles[] = $val; } } Config::set_css($styles); } public function option_k($k, $v) { $this->option_packagedir($k, $v); } public function option_packagedir($k, $v) { $packages = Config::package_dirs(); foreach((array)$v as $key => $val) { if ($path = realpath($val)) { if (!in_array($path, $packages)) { $packages[] = $path; } } else { v('Invalid path: %s', $val, E_USER_WARNING); } } Config::set_package_dirs($packages); } public function option_x($k, $v) { $this->option_xinclude($k, 'true'); } public function option_xinclude($k, $v) { Config::set_process_xincludes(true); } /** * Prints out the current PhD and PHP version. * Exits directly. * * @return void */ public function option_version($k, $v) { $color = Config::phd_info_color(); $output = Config::phd_info_output(); fprintf($output, "%s\n", term_color('PhD Version: ' . Config::VERSION, $color)); $packageList = Config::getSupportedPackages(); foreach ($packageList as $package) { $version = Format_Factory::createFactory($package)->getPackageVersion(); fprintf($output, "\t%s: %s\n", term_color($package, $color), term_color($version, $color)); } fprintf($output, "%s\n", term_color('PHP Version: ' . phpversion(), $color)); fprintf($output, "%s\n", term_color(Config::copyright(), $color)); exit(0); } public function option_h($k, $v) { $this->option_help($k, $v); } public function option_help($k, $v) { echo "PhD version: " .Config::VERSION; echo "\n" . Config::copyright() . "\n -v --verbose Adjusts the verbosity level -f --format The build format to use -P --package The package to use -I --noindex Do not index before rendering but load from cache (default: false) -M --memoryindex Do not save indexing into a file, store it in memory. (default: false) -r --forceindex Force re-indexing under all circumstances (default: false) -t --notoc Do not rewrite TOC before rendering but load from cache (default: false) -d --docbook The Docbook file to render from -x --xinclude Process XML Inclusions (XInclude) (default: false) -p --partial The ID to render, optionally skipping its children chunks (default to true; render children) -s --skip The ID to skip, optionally skipping its children chunks (default to true; skip children) -l --list Print out the supported packages and formats -o --output The output directory (default: .) -F filename --outputfilename filename Filename to use when writing standalone formats (default: -.) -L --lang The language of the source file (used by the CHM theme). (default: en) -c --color Enable color output when output is to a terminal (default: " . (Config::color_output() ? 'true' : 'false') . ") -C --css Link for an external CSS file. -g --highlighter Use custom source code highlighting php class -V --version Print the PhD version information -h --help This help -e --ext The alternative filename extension to use, including the dot. Use 'false' for no extension. -S --saveconfig Save the generated config (default: false). -Q --quit Don't run the build. Use with --saveconfig to just save the config. -k --packagedir Use an external package directory. Most options can be passed multiple times for greater effect. "; exit(0); } /** * Makes a string into a boolean (i.e. on/off, yes/no, ..) * * Returns boolean true/false on success, null on failure * * @param string $val * @return bool */ public static function boolval($val) { if (!is_string($val)) { return null; } switch ($val) { case "on": case "yes": case "true": case "1": return true; break; case "off": case "no": case "false": case "0": return false; break; default: return null; } } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Options/Interface.php000064400000000251117671476410014520 0ustar00defaultHandler = new Options_Handler(); $this->packageHandlers = $this->loadPackageHandlers(); } public static function instance() { static $instance = null; if ($instance == null) { $instance = new self(); } return $instance; } private function loadPackageHandlers() { $packageList = Config::getSupportedPackages(); $list = array(); foreach ($packageList as $package) { if ($handler = Format_Factory::createFactory($package)->getOptionsHandler()) { $list[strtolower($package)] = $handler; } } return $list; } public function handlerForOption($option) { if (method_exists($this->defaultHandler, "option_{$option}")) { return array($this->defaultHandler, "option_{$option}"); } $opt = explode('-', $option); $package = strtolower($opt[0]); if (isset($this->packageHandlers[$package])) { if (method_exists($this->packageHandlers[$package], "option_{$opt[1]}")) { return array($this->packageHandlers[$package], "option_{$opt[1]}"); } } return NULL; } public function getLongOptions() { $defaultOptions = array_keys($this->defaultHandler->optionList()); $packageOptions = array(); foreach ($this->packageHandlers as $package => $handler) { foreach ($handler->optionList() as $opt) { $packageOptions[] = $package . '-' . $opt; } } return array_merge($defaultOptions, $packageOptions); } public function getShortOptions() { return implode('', array_values($this->defaultHandler->optionList())); } /** * Checks if all options passed are valid. * * Fix Bug #54217 - Warn about nonexisting parameters */ private function checkOptions() { $argv = $_SERVER['argv']; $argc = $_SERVER['argc']; $short = str_split(str_replace(':', '', $this->getShortOptions())); $long = array(); foreach ($this->getLongOptions() as $opt) { $long[] = str_replace(':', '', $opt); } for ($i=1; $i < $argc; $i++) { if (substr($argv[$i], 0, 2) == '--') { if (!in_array(substr($argv[$i], 2), $long)) { trigger_error('Invalid long option ' . $argv[$i], E_USER_ERROR); } } elseif (substr($argv[$i], 0, 1) == '-') { if (!in_array(substr($argv[$i], 1), $short)) { trigger_error('Invalid short option ' . $argv[$i], E_USER_ERROR); } } } } public static function getopt() { $self = self::instance(); //validate options $self->checkOptions(); $args = getopt($self->getShortOptions(), $self->getLongOptions()); if ($args === false) { trigger_error("Something happend with getopt(), please report a bug", E_USER_ERROR); } foreach ($args as $k => $v) { $handler = $self->handlerForOption($k); if (is_callable($handler)) { call_user_func($handler, $k, $v); } else { var_dump($k, $v); trigger_error("Hmh, something weird has happend, I don't know this option", E_USER_ERROR); } } } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Reader/Partial.php000064400000011064117671476410013767 0ustar00partial = $render_ids; } else { $this->partial[$render_ids] = 1; } $skip_ids = Config::skip_ids(); if ($skip_ids !== NULL) { if (is_array($skip_ids)) { $this->skip = $skip_ids; } else { $this->skip[$skip_ids] = 1; } } } else { throw new \Exception("Didn't get any IDs to seek"); } $parents = array(); if (file_exists(Config::output_dir() . "index.sqlite")) { $sqlite = new \SQLite3(Config::output_dir() . "index.sqlite"); // Fetch all ancestors of the ids we should render foreach($render_ids as $p => $v) { do { $id = $sqlite->escapeString($p); $row = $sqlite->query("SELECT parent_id FROM ids WHERE docbook_id = '$id'")->fetchArray(SQLITE3_ASSOC); if ($row["parent_id"]) { $parents[] = $p = $row["parent_id"]; continue; } break; } while(1); } } $this->parents = $parents; } public function read() { static $seeked = 0; static $currently_reading = false; static $currently_skipping = false; static $arrayPartial = array(); static $arraySkip = array(); $ignore = false; while($ret = parent::read()) { $id = $this->getAttributeNs("id", self::XMLNS_XML); $currentPartial = end($arrayPartial); $currentSkip = end($arraySkip); if (isset($this->partial[$id])) { if ($currentPartial == $id) { v("%s done", $id, VERBOSE_PARTIAL_READING); unset($this->partial[$id]); --$seeked; $currently_reading = false; array_pop($arrayPartial); } else { v("Starting %s...", $id, VERBOSE_PARTIAL_READING); $currently_reading = $id; ++$seeked; $arrayPartial[] = $id; } return $ret; } elseif (isset($this->skip[$id])) { if ($currentSkip == $id) { v("%s done", $id, VERBOSE_PARTIAL_READING); unset($this->skip[$id]); $currently_skipping = false; $ignore = false; array_pop($arraySkip); } else { v("Skipping %s...", $id, VERBOSE_PARTIAL_READING); $currently_skipping = $id; $ignore = true; $arraySkip[] = $id; } } elseif ($currently_skipping && $this->skip[$currently_skipping]) { if ($currentSkip == $id) { v("Skipping child of %s, %s", $currently_reading, $id, VERBOSE_PARTIAL_CHILD_READING); } else { v("%s done", $id, VERBOSE_PARTIAL_CHILD_READING); } $ignore = true; } elseif ($currently_reading && $this->partial[$currently_reading]) { if ($currentPartial == $id) { v("Rendering child of %s, %s", $currently_reading, $id, VERBOSE_PARTIAL_CHILD_READING); } else { v("%s done", $id, VERBOSE_PARTIAL_CHILD_READING); } return $ret; } elseif (empty($this->partial)) { return false; } else { // If we are used by the indexer then we have no clue about the // parents :) if ($id && $this->parents) { // If this id isn't one of our ancestors we can jump // completely over it if (!in_array($id, $this->parents)) { parent::next(); } } $ignore = true; } } return $ret; } } /* * vim600: sw=4 ts=4 fdm=syntax syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/PI/DBHTMLHandler.php000064400000010434117671476410013751 0ustar00 "", "bgcolor" => "", "cellpadding" => "", "cellspacing" => "", "class" => "", "dir" => "", "filename" => "", "funcsynopsis-style" => "", "img.src.path" => "", "label-width" => "", "linenumbering.everyNth" => "", "linenumbering.separator" => "", "linenumbering.width" => "", "list-presentation" => "", "list-width" => "", "row-height" => "", "start" => "", "stop-chunking" => "", "table-summary" => "", "table-width" => "", "term-presentation" => "", "term-separator" => "", "term-width" => "", "toc" => "", //Attributes for "", "padding" => "", ); public function __construct($format) { parent::__construct($format); } public function parse($target, $data) { $pattern = "/(?[\w]+[\w\-\.]*)[\s]*=[\s]*\"(?[^\"]*)\"/"; preg_match_all($pattern, $data, $matches); for ($i = 0; $i < count($matches["attr"]); $i++) { $attr = trim($matches["attr"][$i]); $value = trim($matches["value"][$i]); $this->setAttribute($attr, $value); } //Hack for stop-chunking if ($data == "stop-chunking") { $this->setAttribute("stop-chunking", true); } //Parse parseDBTimestamp(); $this->setAttribute("padding", ""); $this->setAttribute("format", ""); } } public function setAttribute($attr, $value) { if (isset($this->attrs[$attr])) { $this->attrs[$attr] = $value; } } public function getAttribute($attr) { return isset($this->attrs[$attr]) ? $this->attrs[$attr] : false; } /** * Function to parse dbtimestamp processing instructions * Reference: http://www.sagehill.net/docbookxsl/Datetime.html */ public function parseDBTimestamp() { // Array to parse formats from dbtimestamp to date() $parseArray = array( "a" => "D", // Day abbreviation "A" => "l", // Day name "b" => "M", // Month abbreviation "c" => "c", // ISO date and time "B" => "F", // Month name "d" => "d", // Day in month "H" => "H", // Hour in day "j" => "z", // Day in year "m" => "m", // Month in year "M" => "i", // Minute in hour "S" => "s", // Second in minute "U" => "W", // Week in year "w" => "w", // Day in week "x" => "Y-m-dP", // ISO date "X" => "H:i:sP", // ISO time "Y" => "Y", // Year ); if ($this->getAttribute("padding") == "0") { $parseArray["d"] = "j"; $parseArray["H"] = "G"; $parseArray["m"] = "n"; } $format = $this->getAttribute("format"); if (!$format) { return $this->format->appendData(date('c')); } $dateFormat = ""; $len = strlen($format); for ($i = 0; $i < $len; $i++) { $dateFormat .= isset($parseArray[$format[$i]]) ? $parseArray[$format[$i]] : $format[$i]; } return $this->format->appendData(date($dateFormat)); } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/PI/PHPDOCHandler.php000064400000016054117671476410013760 0ustar00[\w]+[\w\-\.]*)[\s]*=[\s]*\"(?[^\"]*)\"/"; preg_match($pattern, $data, $matches); switch($matches["attr"]) { case "print-version-for": // FIXME: Figureout a way to detect the current language (for unknownversion) if (!$this->format instanceof Index) { return $this->format->autogenVersionInfo($matches["value"], "en"); } return; case "generate-index-for": if ($this->format instanceof Index) { return; } switch($matches["value"]) { case "function": case "refentry": $tmp = $this->format->getRefs(); $ret = ""; $refs = array(); $info = array(); foreach($tmp as $id) { $filename = $this->format->createLink($id, $desc); $refs[$filename] = $desc; $info[$filename] = array($this->format->getLongDescription($id, $islong), $islong); } natcasesort($refs); // Nav bar to jump directly to a character $chars = array_count_values(array_map(function($ref){ return strtolower($ref[0]); }, $refs)); $ret = '

'."\n"; foreach ($chars as $char => $count) { $ret .= ''.$char.''."\n"; } $ret .= "

\n"; // Workaround for 5.3 that doesn't allow func()[index] $current = current($refs); $char = $current[0]; $ret .= "\n\n"; return $ret; break; case "examples": $ret = ""; return $ret; break; default: trigger_error("Don't know how to handle {$matches["value"]} for {$matches["attr"]}", E_USER_WARNING); break; } break; case "extension-membership": if ($this->format instanceof Index) { return $this->format->setMembership($matches["value"]); } return; case "changelog-config-since": $this->_changelogSince = $matches["value"]; break; case "generate-changelog-for-membership": if ($this->format instanceof Index) { return; } $members = explode(" ", $matches["value"]); $changelogs = $this->format->getChangelogsForMembershipOf($members); return $this->generateChangelogMarkup($changelogs); break; case "generate-changelog-for": if ($this->format instanceof Index) { return; } $parents = explode(" ", $matches["value"]); $changelogs = $this->format->getChangelogsForChildrenOf($parents); return $this->generateChangelogMarkup($changelogs); break; default: trigger_error("Don't know how to handle {$matches["attr"]}", E_USER_WARNING); break; } } // usort() callback function used in generate-changelog-for, higest (newest) version first // 1.2.11 comes before 1.2.2, then function name (actually its id.. but close enough :)) protected static function _sortByVersion($a, $b) { $retval = -1 * strnatcasecmp($a["version"], $b["version"]); if ($retval === 0) { return strnatcasecmp($a["docbook_id"], $b["docbook_id"]); } return $retval; } protected function generateChangelogMarkup($changelogs) { usort($changelogs, array(__CLASS__, "_sortByVersion")); $ret = ""; $ret .= ""; $ret .= ""; $ret .= ""; $ret .= ""; $version = ""; foreach($changelogs as $entry) { if (!$this->_changelogSince || strnatcasecmp($entry["version"], $this->_changelogSince) >= 0) { $link = $this->format->createLink($entry["docbook_id"], $desc); if ($version == $entry["version"]) { $v = " "; } else { if ($version) { $ret .= ""; } $ret .= ''; $version = $entry["version"]; $v = $version; } $ret .= sprintf("", $v, $link, $desc, $entry["description"]); } } $this->_changelogSince= null; return $ret . "
" . $this->format->autogen("Version", "en") . "" . $this->format->autogen("Function", "en") . "" . $this->format->autogen("Description", "en") . "
%s%s%s
"; } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Autoloader.php000064400000001714117671476410013271 0ustar00 array(), 'chunk_extra' => array( 'legalnotice' => true, 'phpdoc:exception' => true, ), 'no_index' => false, 'force_index' => false, 'no_toc' => false, 'xml_root' => '.', 'xml_file' => './.manual.xml', 'lang_dir' => './', 'language' => 'en', 'fallback_language' => 'en', 'verbose' => VERBOSE_DEFAULT, 'date_format' => 'H:i:s', 'render_ids' => array( ), 'skip_ids' => array( ), 'color_output' => true, 'output_dir' => './output/', 'output_filename' => '', 'intermediate_output_dir' => '.', 'php_error_output' => STDERR, 'php_error_color' => '01;31', // Red 'user_error_output' => STDERR, 'user_error_color' => '01;33', // Yellow 'phd_info_output' => STDOUT, 'phd_info_color' => '01;32', // Green 'phd_warning_output' => STDOUT, 'phd_warning_color' => '01;35', // Magenta 'highlighter' => 'phpdotnet\\phd\\Highlighter', 'package' => array( 'Generic', ), 'css' => array(), 'process_xincludes' => false, 'ext' => null, 'package_dirs' => array(__INSTALLDIR__), 'saveconfig' => false, 'quit' => false, 'indexcache' => '', 'memoryindex' => '', ); private static $optionArray = null; public static function init(array $a) { // Override any defaults due to operating system constraints // and copy defaults to working optionArray if ($newInit = is_null(self::$optionArray)) { // By default, Windows does not support colors on the console. // ANSICON by Jason Hood (http://adoxa.110mb.com/ansicon/index.html) // can be used to provide colors at the console on Windows. // Color output can still be enabled via the command line parameters --color if('WIN' === strtoupper(substr(PHP_OS, 0, 3))) { self::$optionArrayDefault['color_output'] = false; } self::$optionArray = self::$optionArrayDefault; } // now merge other options self::$optionArray = array_merge(self::$optionArray, (array)$a); if ($newInit) { // Always set saveconfig to false for a new initialization, even after restoring // a save configuration. This allows additional options to be added at the // command line without them being automatically saved. self::$optionArray['saveconfig'] = false; // As well as the quit option. self::$optionArray['quit'] = false; // Set the error reporting level to the restored level. error_reporting($GLOBALS['olderrrep'] | self::$optionArray['verbose']); } } public static function getAllFiltered() { $retval = self::$optionArray; return self::exportable($retval); } public static function exportable($val) { foreach($val as $k => &$opt) { if (is_array($opt)) { $opt = self::exportable($opt); continue; } if (is_resource($opt)) { unset($val[$k]); } } return $val; } /** * Maps static function calls to config option setter/getters. * * To set an option, call "Config::setOptionname($value)". * To retrieve an option, call "Config::optionname()". * * It is also possible, but deprecated, to call * "Config::set_optionname($value)". * * @param string $name Name of called function * @param array $params Array of function parameters * * @return mixed Config value that was requested or set. */ public static function __callStatic($name, $params) { $name = strtolower($name); // FC if this becomes case-sensitive if (strncmp($name, 'set', 3) === 0) { $name = substr($name, 3); if ($name[0] === '_') { $name = substr($name, 1); } if (strlen($name) < 1 || count($params) !== 1) { // assert trigger_error('Misuse of config option setter', E_USER_ERROR); } self::$optionArray[$name] = $params[0]; // no return, intentional } return isset(self::$optionArray[$name]) ? self::$optionArray[$name] : NULL; } public static function getSupportedPackages() { $packageList = array(); foreach(Config::package_dirs() as $dir) { foreach (glob($dir . "/phpdotnet/phd/Package/*", GLOB_ONLYDIR) as $item) { $baseitem = basename($item); if ($baseitem[0] != '.') { $packageList[] = $baseitem; } } } return $packageList; } public static function setColor_output($color_output) { // Disable colored output if the terminal doesn't support colors if ($color_output && function_exists('posix_isatty')) { if (!posix_isatty(Config::phd_info_output())) { Config::setPhd_info_color(false); } if (!posix_isatty(Config::phd_warning_output())) { Config::setPhd_warning_color(false); } if (!posix_isatty(Config::php_error_output())) { Config::setPhd_error_color(false); } if (!posix_isatty(Config::user_error_output())) { Config::setUser_error_color(false); } } self::$optionArray['color_output'] = $color_output; } public static function set_color_output($color_output) { trigger_error('Use setColor_output()', E_USER_DEPRECATED); } public static function copyright() { return sprintf('Copyright(c) 2007-%s The PHP Documentation Group', date('Y')); } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Format.php000064400000046772117671476410012437 0ustar00sqlite = $sqlite; $this->sortIDs(); } } abstract public function transformFromMap($open, $tag, $name, $attrs, $props); abstract public function UNDEF($open, $name, $attrs, $props); abstract public function TEXT($value); abstract public function CDATA($value); /** * Create link to chunk. * * @param string $for Chunk ID * @param string &$desc Description of link, to be filled if neccessary * @param integer $type Format of description, Format::SDESC or * Format::LDESC * * @return string Relative or absolute URI to access $for */ abstract public function createLink( $for, &$desc = null, $type = Format::SDESC ); abstract public function appendData($data); /** * Called by Format::notify() * * Possible events: * - Render::STANDALONE * Always called with true as value from Render::attach() * * * - Render::INIT * Called from Render::execute() when rendering * is being started. Value is always true * * - Render::FINALIZE (from Render::execute()) * Called from Render::execute() when there is * nothing more to read in the XML file. * * - Render::VERBOSE * Called if the user specified the --verbose option * as commandline parameter. Called in render.php * * - Render::CHUNK * Called when a new chunk is opened or closed. * Value is either Render::OPEN or Render::CLOSE * * @param integer $event Event flag (see Render class) * @param mixed $val Additional value flag. Depends * on $event type * * @return void */ abstract public function update($event, $value = null); public final function parsePI($target, $data) { if (isset($this->pihandlers[$target])) { return $this->pihandlers[$target]->parse($target, $data); } } public final function registerPIHandlers($pihandlers) { foreach ($pihandlers as $target => $classname) { $class = __NAMESPACE__ . "\\" . $classname; $this->pihandlers[$target] = new $class($this); } } public function getPIHandler($target) { return $this->pihandlers[$target]; } public function sortIDs() { $this->sqlite->createAggregate("indexes", array($this, "SQLiteIndex"), array($this, "SQLiteFinal"), 9); $this->sqlite->createAggregate("children", array($this, "SQLiteChildren"), array($this, "SQLiteFinal"), 2); $this->sqlite->createAggregate("refname", array($this, "SQLiteRefname"), array($this, "SQLiteFinal"), 2); $this->sqlite->createAggregate("varname", array($this, "SQLiteVarname"), array($this, "SQLiteFinal"), 2); $this->sqlite->createAggregate("classname", array($this, "SQLiteClassname"), array($this, "SQLiteFinal"), 2); $this->sqlite->createAggregate("example", array($this, "SQLiteExample"), array($this, "SQLiteFinal"), 1); $this->sqlite->query('SELECT indexes(docbook_id, filename, parent_id, sdesc, ldesc, element, previous, next, chunk) FROM ids'); $this->sqlite->query('SELECT children(docbook_id, parent_id) FROM ids WHERE chunk != 0'); $this->sqlite->query('SELECT refname(docbook_id, sdesc) FROM ids WHERE element=\'refentry\''); $this->sqlite->query('SELECT varname(docbook_id, sdesc) FROM ids WHERE element=\'phpdoc:varentry\''); $this->sqlite->query('SELECT classname(docbook_id, sdesc) FROM ids WHERE element=\'phpdoc:exceptionref\' OR element=\'phpdoc:classref\''); $this->sqlite->query('SELECT example(docbook_id) FROM ids WHERE element=\'example\' OR element=\'informalexample\''); } public function SQLiteIndex(&$context, $index, $id, $filename, $parent, $sdesc, $ldesc, $element, $previous, $next, $chunk) { $this->indexes[$id] = array( "docbook_id" => $id, "filename" => $filename, "parent_id" => $parent, "sdesc" => $sdesc, "ldesc" => $ldesc, "element" => $element, "previous" => $previous, "next" => $next, "chunk" => $chunk, ); } public function SQLiteChildren(&$context, $index, $id, $parent) { if (!isset($this->children[$parent]) || !is_array($this->children[$parent]) ) { $this->children[$parent] = array(); } $this->children[$parent][] = $id; } public function SQLiteRefname(&$context, $index, $id, $sdesc) { $ref = strtolower(str_replace(array("_", "::", "->"), array("-", "-", "-"), html_entity_decode($sdesc, ENT_QUOTES, 'UTF-8'))); $this->refs[$ref] = $id; } public function SQLiteVarname(&$context, $index, $id, $sdesc) { $this->vars[$sdesc] = $id; } public function SQLiteClassname(&$context, $index, $id, $sdesc) { $this->classes[strtolower($sdesc)] = $id; } public function SQLiteExample(&$context, $index, $id) { $this->examples[] = $id; } public static function SQLiteFinal(&$context) { return $context; } /** * Calls update(). * * @param integer $event Event flag. See Render class for constants * like Render::INIT and Render::CHUNK * @param mixed $val Value; depends on $event flag * * @return void */ final public function notify($event, $val = null) { $this->update($event, $val); } public function setTitle($title) { $this->title = $title; } public function getTitle() { return $this->title; } /** * Set file extension used when chunking and writing * out files. * * @param string $ext File extension without dot * * @return void * * @see getExt() */ public function setExt($ext) { $this->ext = $ext; } /** * Returns file extension without * leading dot. * * @return string File extension. * * @see setExt() */ public function getExt() { return $this->ext; } public function setOutputDir($outputdir) { $this->outputdir = $outputdir; } public function getOutputDir() { return $this->outputdir; } public function setChunked($chunked) { $this->chunked = $chunked; } public function isChunked() { return $this->chunked; } public function setFileStream($stream) { $this->fp = $stream; } public function getFileStream() { return $this->fp; } public function pushFileStream($stream) { $this->fp[] = $stream; } public function popFileStream() { return array_pop($this->fp); } public function addRefname($id, $ref) { $this->refs[$ref] = $id; } public function addClassname($id, $class) { $this->classes[$class] = $id; } public function addVarname($id, $var) { $this->vars[$var] = $id; } public function getChangelogsForChildrenOf($bookids) { $ids = array(); foreach((array)$bookids as $bookid) { $ids[] = "'" . $this->sqlite->escapeString($bookid) . "'"; } $results = $this->sqlite->query("SELECT * FROM changelogs WHERE parent_id IN (" . join(", ", $ids) . ")"); return $this->_returnChangelog($results); } public function getChangelogsForMembershipOf($memberships) { $ids = array(); foreach((array)$memberships as $membership) { $ids[] = "'" . $this->sqlite->escapeString($membership) . "'"; } $results = $this->sqlite->query("SELECT * FROM changelogs WHERE membership IN (" . join(", ", $ids) . ")"); return $this->_returnChangelog($results); } public function _returnChangelog($results) { if (!$results) { return array(); } $changelogs = array(); while ($row = $results->fetchArray()) { $changelogs[] = $row; } return $changelogs; } public function getRefs() { return $this->refs; } public function getExamples() { return $this->examples; } public function getRefnameLink($ref) { return isset($this->refs[$ref]) ? $this->refs[$ref] : null; } public function getClassnameLink($class) { return isset($this->classes[$class]) ? $this->classes[$class] : null; } public function getVarnameLink($var) { return isset($this->vars[$var]) ? $this->vars[$var] : null; } public function getGeneratedExampleID($index) { return $this->examples[$index]; } final public function registerElementMap(array $map) { $this->elementmap = $map; } final public function registerTextMap(array $map) { $this->textmap = $map; } final public function attach($obj, $inf = array()) { if (!($obj instanceof $this) && get_class($obj) != get_class($this)) { throw new InvalidArgumentException(get_class($this) . " themes *MUST* _inherit_ " .get_class($this). ", got " . get_class($obj)); } $obj->notify(Render::STANDALONE, false); return parent::attach($obj, $inf); } final public function getElementMap() { return $this->elementmap; } final public function getTextMap() { return $this->textmap; } final public function registerFormatName($name) { $this->formatname = $name; } public function getFormatName() { return $this->formatname; } /* Buffer where append data instead of the standard stream (see format's appendData()) */ final public function parse($xml) { $parsed = ""; $reader = new Reader(); $render = new Render(); $reader->XML("" . $xml . ""); $this->appendToBuffer = true; $render->attach($this); $render->execute($reader); $this->appendToBuffer = false; $parsed = $this->buffer; $this->buffer = ""; return $parsed; } final public static function autogen($text, $lang) { if ($lang == NULL) { $lang = Config::language(); } if (isset(self::$autogen[$lang])) { if (isset(self::$autogen[$lang][$text])) { return self::$autogen[$lang][$text]; } if ($lang == Config::fallback_language()) { throw new \InvalidArgumentException("Cannot autogenerate text for '$text'"); } return self::autogen($text, Config::fallback_language()); } $filename = Config::lang_dir() . $lang . ".xml"; $r = new \XMLReader; if (!file_exists($filename) || !$r->open($filename)) { if ($lang == Config::fallback_language()) { throw new \Exception("Cannot open $filename"); } return self::autogen($text, Config::fallback_language()); } $autogen = array(); while ($r->read()) { if ($r->nodeType != \XMLReader::ELEMENT) { continue; } if ($r->name == "term") { $r->read(); $k = $r->value; $autogen[$k] = ""; } else if ($r->name == "simpara") { $r->read(); $autogen[$k] = $r->value; } } self::$autogen[$lang] = $autogen; return self::autogen($text, $lang); } /* {{{ TOC helper functions */ /** * Returns the filename for the given id, without the file extension * * @param string $id XML Id * * @return mixed Stringular filename or false if no filename * can be detected. */ final public function getFilename($id) { return isset($this->indexes[$id]['filename']) ? $this->indexes[$id]['filename'] : false; } final public function getPrevious($id) { return $this->indexes[$id]["previous"]; } final public function getNext($id) { return $this->indexes[$id]["next"]; } final public function getParent($id) { return $this->indexes[$id]["parent_id"]; } final public function getLongDescription($id, &$isLDesc = null) { if ($this->indexes[$id]["ldesc"]) { $isLDesc = true; return $this->indexes[$id]["ldesc"]; } else { $isLDesc = false; return $this->indexes[$id]["sdesc"]; } } final public function getShortDescription($id, &$isSDesc = null) { if ($this->indexes[$id]["sdesc"]) { $isSDesc = true; return $this->indexes[$id]["sdesc"]; } else { $isSDesc = false; return $this->indexes[$id]["ldesc"]; } } /** * Returns an array of children IDs of given ID. * * @param string $id XML ID to retrieve children for. * * @return array Array of XML IDs */ final public function getChildren($id) { if (!isset($this->children[$id]) || !is_array($this->children[$id]) || count($this->children[$id]) == 0 ) { return null; } return $this->children[$id]; } /** * Tells you if the given ID is to be chunked or not. * * @param string $id XML ID to get chunk status for * * @return boolean True if it is to be chunked */ final public function isChunkID($id) { return isset($this->indexes[$id]['chunk']) ? $this->indexes[$id]['chunk'] : false; } final public function getRootIndex() { static $root = null; if ($root == null) { $root = $this->sqlite->querySingle('SELECT * FROM ids WHERE parent_id=""', true); } return $root; } /* }}} */ /* {{{ Table helper functions */ public function tgroup($attrs) { if (isset($attrs["cols"])) { $this->TABLE["cols"] = $attrs["cols"]; unset($attrs["cols"]); } $this->TABLE["defaults"] = $attrs; $this->TABLE["colspec"] = array(); } public function colspec(array $attrs) { $colspec = self::getColSpec($attrs); $this->TABLE["colspec"][$colspec["colnum"]] = $colspec; return $colspec; } public function getColspec(array $attrs) { /* defaults */ $defaults["colname"] = count($this->TABLE["colspec"])+1; $defaults["colnum"] = count($this->TABLE["colspec"])+1; return array_merge($defaults, $this->TABLE["defaults"], $attrs); } public function getColCount() { return $this->TABLE["cols"]; } public function initRow() { $this->TABLE["next_colnum"] = 1; } public function getEntryOffset(array $attrs) { $curr = $this->TABLE["next_colnum"]; foreach($this->TABLE["colspec"] as $col => $spec) { if ($spec["colname"] == $attrs["colname"]) { $colnum = $spec["colnum"]; $this->TABLE["next_colnum"] += $colnum-$curr; return $colnum-$curr; } } return -1; } public function colspan(array $attrs) { if (isset($attrs["namest"])) { foreach($this->TABLE["colspec"] as $colnum => $spec) { if ($spec["colname"] == $attrs["namest"]) { $from = $spec["colnum"]; continue; } if ($spec["colname"] == $attrs["nameend"]) { $to = $spec["colnum"]; continue; } } $colspan = $to-$from+1; $this->TABLE["next_colnum"] += $colspan; return $colspan; } $this->TABLE["next_colnum"]++; return 1; } public function rowspan($attrs) { if (isset($attrs["morerows"])) { return $attrs["morerows"]+1; } return 1; } /* }}} */ /** * Highlight (color) the given piece of source code * * @param string $text Text to highlight * @param string $role Source code role to use (php, xml, html, ...) * @param string $format Format to highlight (pdf, xhtml, troff, ...) * * @return string Highlighted code */ public function highlight($text, $role = 'php', $format = 'xhtml') { if (!isset(self::$highlighters[$format])) { $class = Config::highlighter(); self::$highlighters[$format] = $class::factory($format); } return self::$highlighters[$format]->highlight( $text, $role, $format ); } /** * Provide a nested list of IDs from the document root to the CURRENT_ID. * * @param string $name The name of the current element. * @param mixed[] $props Properties relating to the current element. * * @return string A nested list of IDs from the root to the CURRENT_ID. */ public function getDebugTree($name, $props) { /* Build the list of IDs from the CURRENT_ID to the root. */ $ids = array(); $id = $this->CURRENT_ID; while($id != '') { $ids[] = '<' . $this->indexes[$id]['element'] . ' id="' . $id . '">'; $id = $this->indexes[$id]['parent_id']; } /* Reverse the list so that it goes form the root to the CURRENT_ID. */ $ids = array_reverse($ids); /* Build an indented tree view of the ids. */ $tree = ''; $indent = 0; array_walk($ids, function($value, $key) use(&$tree, &$indent) { $tree .= str_repeat(' ', $indent++) . $value . PHP_EOL; }); /* Add the open and closed sibling and the current element. */ $tree .= str_repeat(' ', $indent) . '<' . $props['sibling'] . '>' . PHP_EOL . str_repeat(' ', $indent) . '...' . PHP_EOL . str_repeat(' ', $indent) . '' . PHP_EOL . str_repeat(' ', $indent) . '<' . $name . '>' . PHP_EOL; return $tree; } } /* * vim600: sw=4 ts=4 fdm=syntax syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/functions.php000064400000015234117671476410013204 0ustar00isFile() || $fileinfo->isLink()) { unlink($fileinfo->getPathName()); } elseif (!$fileinfo->isDot() && $fileinfo->isDir()) { removeDir($fileinfo->getPathName()); } } rmdir($path); } /* }}} */ /* {{{ The PhD errorhandler */ function errh($errno, $msg, $file, $line, $ctx = null) { static $err = array( // PHP Triggered Errors E_DEPRECATED => 'E_DEPRECATED ', E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR ', E_STRICT => 'E_STRICT ', E_WARNING => 'E_WARNING ', E_NOTICE => 'E_NOTICE ', // User Triggered Errors E_USER_ERROR => 'E_USER_ERROR ', E_USER_WARNING => 'E_USER_WARNING ', E_USER_NOTICE => 'E_USER_NOTICE ', E_USER_DEPRECATED => 'E_USER_DEPRECATED ', // PhD informationals VERBOSE_INDEXING => 'Indexing ', VERBOSE_FORMAT_RENDERING => 'Rendering Format ', VERBOSE_THEME_RENDERING => 'Rendering Theme ', VERBOSE_RENDER_STYLE => 'Rendering Style ', VERBOSE_PARTIAL_READING => 'Partial Reading ', VERBOSE_PARTIAL_CHILD_READING => 'Partial Child Reading ', VERBOSE_TOC_WRITING => 'Writing TOC ', VERBOSE_CHUNK_WRITING => 'Writing Chunk ', VERBOSE_MESSAGES => 'Heads up ', // PhD warnings VERBOSE_NOVERSION => 'No version information', VERBOSE_BROKEN_LINKS => 'Broken links ', VERBOSE_OLD_LIBXML => 'Old libxml2 ', VERBOSE_MISSING_ATTRIBUTES => 'Missing attributes ', ); static $recursive = false; // Respect the error_reporting setting if (!(error_reporting() & $errno)) { return false; } // Recursive protection if ($recursive) { // Thats bad.. lets print a backtrace right away debug_print_backtrace(); // Fallback to the default errorhandler return false; } $recursive = true; $time = date(Config::date_format()); switch($errno) { case VERBOSE_INDEXING: case VERBOSE_FORMAT_RENDERING: case VERBOSE_THEME_RENDERING: case VERBOSE_RENDER_STYLE: case VERBOSE_PARTIAL_READING: case VERBOSE_PARTIAL_CHILD_READING: case VERBOSE_TOC_WRITING: case VERBOSE_CHUNK_WRITING: case VERBOSE_MESSAGES: $color = Config::phd_info_color(); $output = Config::phd_info_output(); $data = $msg; break; case VERBOSE_NOVERSION: case VERBOSE_BROKEN_LINKS: case VERBOSE_MISSING_ATTRIBUTES: $color = Config::phd_warning_color(); $output = Config::phd_warning_output(); $data = $msg; break; // User triggered errors case E_USER_ERROR: case E_USER_WARNING: case E_USER_NOTICE: $color = Config::user_error_color(); $output = Config::user_error_output(); $data = sprintf("%s:%d\n\t%s", $file, $line, $msg); break; // PHP triggered errors case E_DEPRECATED: case E_RECOVERABLE_ERROR: case E_STRICT: case E_WARNING: case E_NOTICE: $color = Config::php_error_color(); $output = Config::php_error_output(); $data = sprintf("%s:%d\n\t%s", $file, $line, $msg); break; default: $recursive = false; return false; } $timestamp = term_color(sprintf("[%s - %s]", $time, $err[$errno]), $color); fprintf($output, "%s %s\n", $timestamp, $data); // Abort on fatal errors if ($errno & (E_USER_ERROR|E_RECOVERABLE_ERROR)) { exit(1); } $recursive = false; return true; } /* }}} */ set_error_handler(__NAMESPACE__ . '\\errh'); /* }}} */ /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Highlighter.php000064400000004103117671476410013423 0ustar00 * @license http://www.opensource.org/licenses/bsd-license.php BSD Style * @version SVN: $Id$ * @link https://doc.php.net/phd/ */ namespace phpdotnet\phd; /** * Source code highlighting class for phd. * * @category PhD * @package PhD * @author Christian Weiske * @license http://www.opensource.org/licenses/bsd-license.php BSD Style * @link https://doc.php.net/phd/ */ class Highlighter { /** * Create a new highlighter instance for the given format. * * We use a factory so you can return different objects/classes * per format. * * @param string $format Output format (pdf, xhtml, troff, ...) * * @return PhDHighlighter Highlighter object */ public static function factory($format) { return new self(); }//public static function factory(..) /** * Highlight a given piece of source code. * Dead simple version that only works for xhtml+php. Returns text as * it was in all other cases. * * @param string $text Text to highlight * @param string $role Source code role to use (php, xml, html, ...) * @param string $format Output format (pdf, xhtml, troff, ...) * * @return string Highlighted code */ public function highlight($text, $role, $format) { if ($format == 'troff') { return "\n.PP\n.nf\n" . str_replace("\\", "\\\\", trim($text)) . "\n.fi"; } else if ($format != 'xhtml') { return $text; } if ($role == 'php') { return highlight_string($text, 1); } else { return '
'
                . htmlspecialchars($text, ENT_QUOTES, 'UTF-8')
                . "
\n"; } return $retval; }//public function highlight(..) } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Index.php000064400000045335117671476410012250 0ustar00 'format_container_chunk', 'appendix' => 'format_container_chunk', 'bibliography' => array( /* DEFAULT */ false, 'article' => 'format_chunk', 'book' => 'format_chunk', 'part' => 'format_chunk', ), 'book' => 'format_container_chunk', 'chapter' => 'format_container_chunk', 'colophon' => 'format_chunk', 'glossary' => array( /* DEFAULT */ false, 'article' => 'format_chunk', 'book' => 'format_chunk', 'part' => 'format_chunk', ), 'index' => array( /* DEFAULT */ false, 'article' => 'format_chunk', 'book' => 'format_chunk', 'part' => 'format_chunk', ), 'legalnotice' => 'format_legalnotice_chunk', 'part' => 'format_container_chunk', 'phpdoc:exception' => 'format_container_chunk', 'phpdoc:exceptionref' => 'format_container_chunk', 'phpdoc:classref' => 'format_container_chunk', 'phpdoc:varentry' => 'format_varentry_chunk', 'preface' => 'format_chunk', 'refentry' => 'format_chunk', 'reference' => 'format_container_chunk', 'sect1' => 'format_chunk', 'section' => array( /* DEFAULT */ false, 'sect1' => 'format_section_chunk', 'chapter' => 'format_section_chunk', 'appendix' => 'format_section_chunk', 'article' => 'format_section_chunk', 'part' => 'format_section_chunk', 'reference' => 'format_section_chunk', 'refentry' => 'format_section_chunk', 'index' => 'format_section_chunk', 'bibliography' => 'format_section_chunk', 'glossary' => 'format_section_chunk', 'colopone' => 'format_section_chunk', 'book' => 'format_section_chunk', 'set' => 'format_section_chunk', 'setindex' => 'format_section_chunk', 'legalnotice' => 'format_section_chunk', ), 'set' => 'format_container_chunk', 'setindex' => 'format_chunk', 'title' => 'format_ldesc', 'refpurpose' => 'format_ldesc', 'refname' => 'format_sdesc', 'titleabbrev' => 'format_sdesc', 'example' => 'format_example', 'refsect1' => 'format_refsect1', "row" => array( /* DEFAULT */ null, "tbody" => 'format_row', ), 'entry' => array( /* DEFAULT */ null, "row" => array( /* DEFAULT */ null, "tbody" => 'format_entry', ), ), ); private $mytextmap = array( ); private $pihandlers = array( 'dbhtml' => 'PI_DBHTMLHandler', 'phpdoc' => 'PI_PHPDOCHandler', ); private $chunks = array(); private $isChunk = array(); private $previousId = ""; private $inChangelog = false; private $currentChangelog = array(); private $changelog = array(); private $currentMembership = null; private $commit = array(); private $POST_REPLACEMENT_INDEXES = array(); private $POST_REPLACEMENT_VALUES = array(); public function transformFromMap($open, $tag, $name, $attrs, $props) { } public function TEXT($value) { } public function CDATA($value) { } public function createLink($for, &$desc = null, $type = Format::SDESC) { } public function appendData($data) { } /** * Checks if indexing is needed. * * This is determined the following way: * 0. If no index file exists, indexing is required. * 1. If the config option --no-index is supplied, nothing is indexed * 2. If the config option --force-index is supplied, indexing is required * 3. If no option is given, the file modification time of the index and * the manual docbook file are compared. If the index is older than * the docbook file, indexing will be done. * * @return boolean True if indexing is required. */ final static public function requireIndexing() { $indexfile = Config::output_dir() . 'index.sqlite'; if (!file_exists($indexfile)) { return true; } if (Config::no_index()) { return false; } if (Config::force_index()) { return true; } $db = new \SQLite3($indexfile); $indexingCount = $db->query('SELECT COUNT(time) FROM indexing') ->fetchArray(SQLITE3_NUM); if ($indexingCount[0] == 0) { return true; } $indexing = $db->query('SELECT time FROM indexing') ->fetchArray(SQLITE3_ASSOC); $xmlLastModification = filemtime(Config::xml_file()); if ($indexing['time'] > $xmlLastModification) { return false; } return true; } public function update($event, $value = null) { switch($event) { case Render::CHUNK: $this->flags = $value; break; case Render::STANDALONE: if ($value) { $this->registerElementMap(static::getDefaultElementMap()); $this->registerTextMap(static::getDefaultTextMap()); $this->registerPIHandlers($this->pihandlers); } break; case Render::INIT: if ($value) { if (Config::memoryindex()) { $db = new \SQLite3(":memory:"); } else { $db = new \SQLite3(Config::output_dir() . 'index.sqlite'); $db->exec('DROP TABLE IF EXISTS ids'); $db->exec('DROP TABLE IF EXISTS indexing'); $db->exec('DROP TABLE IF EXISTS changelogs'); } $create = <<exec('PRAGMA default_synchronous=OFF'); $db->exec('PRAGMA count_changes=OFF'); $db->exec('PRAGMA cache_size=100000'); $db->exec($create); if (Config::memoryindex()) { Config::set_indexcache($db); } $this->db = $db; $this->chunks = array(); } else { print_r($this->chunks); } break; case Render::FINALIZE: $retval = $this->db->exec("BEGIN TRANSACTION; INSERT INTO indexing (time) VALUES ('" . time() . "'); COMMIT"); $this->commit(); if ($this->db->lastErrorCode()) { trigger_error($this->db->lastErrorMsg(), E_USER_WARNING); } break; } } public function getDefaultElementMap() { return $this->myelementmap; } public function getDefaultTextMap() { return $this->mytextmap; } public function UNDEF($open, $name, $attrs, $props) { if ($open) { if(isset($attrs[Reader::XMLNS_XML]["id"])) { $id = $attrs[Reader::XMLNS_XML]["id"]; $this->storeInfo($name, $id, $this->currentchunk, false); if ($props["empty"]) { $this->appendID(); } } return false; } if(isset($attrs[Reader::XMLNS_XML]["id"])) { $this->appendID(); } return false; } protected function storeInfo($elm, $id, $filename, $isChunk = true) { $this->ids[] = $id; $this->currentid = $id; $this->nfo[$id] = array( "parent" => "", "filename" => $filename, "sdesc" => "", "ldesc" => "", "element" => $elm, "children" => array(), "previous" => $isChunk ? $this->previousId : "", "chunk" => $isChunk, ); // Append "next" to the previously inserted row if ($isChunk) { $this->POST_REPLACEMENT_VALUES[$this->previousId] = $this->db->escapeString($id); $this->previousId = $id; } } public function appendID() { static $idx = -1; $lastChunkId = array_pop($this->ids); $parentid = end($this->ids); $this->currentid = $parentid; $lastChunk = $this->nfo[$lastChunkId]; if (is_array($lastChunk["sdesc"])) { $array = true; $sdesc = array_shift($lastChunk["sdesc"]); } else { $array = false; $sdesc = $lastChunk["sdesc"]; } $this->commit[++$idx] = sprintf( "INSERT INTO ids (docbook_id, filename, parent_id, sdesc, ldesc, element, previous, next, chunk) VALUES('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d);\n", $this->db->escapeString($lastChunkId), $this->db->escapeString($lastChunk["filename"]), $this->db->escapeString($this->currentchunk), $this->db->escapeString($sdesc), $this->db->escapeString($lastChunk["ldesc"]), $this->db->escapeString($lastChunk["element"]), $this->db->escapeString($lastChunk["previous"]), $this->db->escapeString($lastChunk["chunk"] ? "POST-REPLACEMENT" : ""), $this->db->escapeString($lastChunk["chunk"]) ); if ($lastChunk["chunk"]) { $this->POST_REPLACEMENT_INDEXES[] = array("docbook_id" => $lastChunkId, "idx" => $idx); } if ($array === true) { foreach($lastChunk["sdesc"] as $sdesc) { $this->commit[++$idx] = sprintf( "INSERT INTO ids (docbook_id, filename, parent_id, sdesc, ldesc, element, previous, next, chunk) VALUES('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0);\n", $this->db->escapeString($lastChunkId), $this->db->escapeString($lastChunk["filename"]), $this->db->escapeString($this->currentchunk), $this->db->escapeString($sdesc), $this->db->escapeString($lastChunk["ldesc"]), $this->db->escapeString($lastChunk["element"]), $this->db->escapeString($lastChunk["previous"]), $this->db->escapeString($lastChunk["chunk"] ? "POST-REPLACEMENT" : "") ); $this->POST_REPLACEMENT_INDEXES[] = array("docbook_id" => $lastChunkId, "idx" => $idx); } } } public function format_section_chunk($open, $name, $attrs, $props) { if ($open) { if (!isset($attrs[Reader::XMLNS_XML]["id"])) { $this->isSectionChunk[] = false; return $this->UNDEF($open, $name, $attrs, $props); } $this->isSectionChunk[] = true; return $this->format_chunk($open, $name, $attrs, $props); } if (array_pop($this->isSectionChunk)) { return $this->format_chunk($open, $name, $attrs, $props); } return $this->UNDEF($open, $name, $attrs, $props); } public function format_container_chunk($open, $name, $attrs, $props) { if ($open) { if ($name == "book") { $this->currentMembership = null; } return $this->format_chunk($open, $name, $attrs, $props); } return $this->format_chunk($open, $name, $attrs, $props); } public function format_varentry_chunk($open, $name, $attrs, $props) { return $this->format_chunk($open, $name, $attrs, $props); } public function format_chunk($open, $name, $attrs, $props) { if ($props["empty"]) { return false; } $this->processFilename(); if ($open) { if(isset($attrs[Reader::XMLNS_XML]["id"])) { $id = $attrs[Reader::XMLNS_XML]["id"]; } else { $this->isChunk[] = false; return false; } $this->isChunk[] = isset($attrs[Reader::XMLNS_PHD]['chunk']) ? $attrs[Reader::XMLNS_PHD]['chunk'] == "true" : true; if (end($this->isChunk)) { $this->chunks[] = $id; $this->currentchunk = $id; $this->storeInfo($name, $id, $id); } return false; } if (array_pop($this->isChunk)) { $lastchunk = array_pop($this->chunks); $this->currentchunk = end($this->chunks); $this->appendID(); } return false; } public function format_legalnotice_chunk($open, $name, $attrs, $props) { return $this->format_chunk($open, $name, $attrs, $props); } public function format_ldesc($open, $name, $attrs, $props) { if ($open) { if (empty($this->nfo[$this->currentid]["ldesc"])) { /* FIXME: How can I mark that node with "reparse" flag? */ $s = htmlentities(trim(ReaderKeeper::getReader()->readContent()), ENT_COMPAT, "UTF-8"); $this->nfo[$this->currentid]["ldesc"] = $s; } } } public function format_sdesc($open, $name, $attrs, $props) { if ($open) { $s = htmlentities(trim(ReaderKeeper::getReader()->readContent()), ENT_COMPAT, "UTF-8"); if (empty($this->nfo[$this->currentid]["sdesc"])) { /* FIXME: How can I mark that node with "reparse" flag? */ $this->nfo[$this->currentid]["sdesc"] = $s; } else { if (!is_array($this->nfo[$this->currentid]["sdesc"])) { $this->nfo[$this->currentid]["sdesc"] = (array)$this->nfo[$this->currentid]["sdesc"]; } //In the beginning of the array to stay compatible with 0.4 array_unshift($this->nfo[$this->currentid]["sdesc"], $s); } } } public function format_example($open, $name, $attrs, $props) { static $n = 0; if ($open) { ++$n; if(isset($attrs[Reader::XMLNS_XML]["id"])) { $id = $attrs[Reader::XMLNS_XML]["id"]; } else { $id = "example-" . $n; } $this->storeInfo($name, $id, $this->currentchunk, false); return false; } $this->appendID(); return false; } public function format_refsect1($open, $name, $attrs, $props) { if ($open) { if (isset($attrs[Reader::XMLNS_DOCBOOK]['role'])) { if ($attrs[Reader::XMLNS_DOCBOOK]['role'] == "changelog") { $this->inChangelog = true; } } return; } $this->inChangelog = false; } public function format_entry($open, $name, $attrs, $props) { if ($open) { if ($this->inChangelog) { /* FIXME: How can I mark that node with "reparse" flag? */ $this->currentChangelog[] = htmlentities(trim(ReaderKeeper::getReader()->readContent()), ENT_COMPAT, "UTF-8"); } } } public function format_row($open, $name, $attrs, $props) { if ($open) { if ($this->inChangelog) { end($this->ids); prev($this->ids); $this->currentChangelog = array($this->currentMembership, current($this->ids)); } return; } if ($this->inChangelog) { $this->changelog[$this->currentid][] = $this->currentChangelog; } } public function commit() { if (isset($this->commit) && $this->commit) { $search = $this->db->escapeString("POST-REPLACEMENT"); $none = $this->db->escapeString(""); foreach($this->POST_REPLACEMENT_INDEXES as $a) { if (isset($this->POST_REPLACEMENT_VALUES[$a["docbook_id"]])) { $replacement = $this->POST_REPLACEMENT_VALUES[$a["docbook_id"]]; $this->commit[$a["idx"]] = str_replace($search, $replacement, $this->commit[$a["idx"]]); } else { // If there are still post replacement, then they don't have // any 'next' page $this->commit[$a["idx"]] = str_replace($search, $none, $this->commit[$a["idx"]]); } } $this->db->exec('BEGIN TRANSACTION; '.join("", $this->commit).' COMMIT'); $log = ""; foreach($this->changelog as $id => $arr) { foreach($arr as $entry) { $log .= sprintf( "INSERT INTO changelogs (membership, docbook_id, parent_id, version, description) VALUES('%s', '%s', '%s', '%s', '%s');\n", $this->db->escapeString($entry[0]), $this->db->escapeString($id), $this->db->escapeString($entry[1]), $this->db->escapeString($entry[2]), $this->db->escapeString($entry[3]) ); } } $this->db->exec('BEGIN TRANSACTION; ' . $log. ' COMMIT'); $this->log = ""; $this->commit = array(); } } public function processFilename() { static $dbhtml = null; if ($dbhtml == null) { $dbhtml = $this->getPIHandler("dbhtml"); } $filename = $dbhtml->getAttribute("filename"); if ($filename) { $this->nfo[end($this->chunks)]["filename"] = $filename; $dbhtml->setAttribute("filename", false); } } public function setMembership($membership) { $this->currentMembership = $membership; } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/MediaManager.php000064400000011131117671476410013476 0ustar00 */ class MediaManager { /** * Directory where files are put * * @var string */ public $output_dir = null; /** * Path the media files are referenced relative to in html. * Trailing slash required. * * @var string */ public $relative_ref_path = ''; /** * Path the media files are referenced relative to in the xml file. * This is nearly always the directory the xml file is located in. * * @var string */ public $relative_source_path = ''; /** * If the image media directory exists * * @var boolean */ protected $media_dir_exists = false; public function __construct($relative_source_path) { $this->relative_source_path = rtrim($relative_source_path, '/\\') . '/'; }//public function __construct(..) /** * Handles the file: * - Generate proper filename (short version with only one directory) * - Copy file over to this directory * - Return filename relative to output directory * * @param string $filename File name relative to docbook document root * * @return string New file path that should be used in xhtml document */ public function handleFile($filename) { $basename = basename($filename); $newname = md5(substr($filename, 0, -strlen($basename))) . '-' . $basename; //FIXME: make images dynamic according to file type (e.g. video) $newpath = 'images/' . $newname; $this->copyOver($filename, $newpath); return $this->relative_ref_path . $newpath; }//public function handleFile(..) /** * Copies the file referenced with $filename into * $output_dir/$newpath. * * @param string $filename Original filename * @param string $newpath New path relative to output directory * * @return void */ protected function copyOver($filename, $newpath) { $fullpath = $this->output_dir . '/' . $newpath; if ($fullfilename = $this->findFile($filename)) { if (!$this->media_dir_exists) { $dir = dirname($fullpath); if (!file_exists($dir)) { mkdir($dir, 0777, true); } $this->media_dir_exists = true; } if (!copy($fullfilename, $fullpath)) { trigger_error('Image could not be copied to : ' . $fullfilename, E_USER_WARNING); } } else { trigger_error("Image does not exist : $filename", E_USER_WARNING); } }//protected function copyOver(..) /** * Find the exact location of the file referenced with $filename * * If the file cannot be found using the supplied filename, which may be * based upon a specific language, then fallback to the English translation. * * @param string $filename Original filename * @param boolean $allowfallback If the required file cannot be found then fallback to English * * @return string Exact location of the file referenced with $filename or False if file not found. */ public function findFile($filename, $allowfallback = true) { $sourcefilenames = array ( // Original format where @LANG@ was part of phpdoc (ala peardoc). array('', $filename), // Where phpdoc/modules/doc-@LANG@ is used. array('../', $filename), // Where phpdoc/doc-base/trunks and phpdoc/en/trunk are used. array('../../', (substr($filename, 0, strpos($filename, '/', 1)) . '/trunk' . substr($filename, strpos($filename, '/', 1)))), ); $foundfile = false; foreach($sourcefilenames as $pathoffset => $filenameinfo) { // Look for current language specific file. if (file_exists($testingfile = $this->relative_source_path . $filenameinfo[0] . $filenameinfo[1])) { $foundfile = $testingfile; break; } // Fallback to English version. if ($allowfallback && file_exists($testingfile = $this->relative_source_path . $filenameinfo[0] . 'en' . substr($filenameinfo[1], strpos($filenameinfo[1], '/')))) { $foundfile = $testingfile; break; } } return $foundfile; }//protected function findFile(..) }//class MediaManager /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/ObjectStorage.php000064400000001076117671476410013726 0ustar00 $obj->getElementMap(), \XMLReader::TEXT => $obj->getTextMap(), ); } parent::attach($obj, $inf); return $obj; } } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/PIHandler.php000064400000000447117671476410013002 0ustar00format = $format; } public abstract function parse($target, $data); } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/Reader.php000064400000002615117671476410012375 0ustar00isEmptyElement) { return $retval; } if (!$node) { // We need libxml2.6.20 to be able to read the textual content of the node without skipping over the markup too if (\LIBXML_VERSION >= 20620) { return self::readString(); } v("You are using libxml2 v%d, but v20620 or newer is preferred", \LIBXML_VERSION, VERBOSE_OLD_LIBXML); $node = $this->name; } $retval = ""; while (self::readNode($node)) { $retval .= $this->value; } return $retval; } /* }}} */ /* Read $nodeName until END_ELEMENT */ public function readNode($nodeName) { /* {{{ */ return self::read() && !($this->nodeType === self::END_ELEMENT && $this->name == $nodeName); } /* }}} */ } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phpdotnet/phd/ReaderKeeper.php000064400000001506117671476410013527 0ustar00= 0) && isset($tag[$this->STACK[$depth]])) { $tag = $tag[$this->STACK[$depth]]; } else { $tag = $tag[0]; } } while (is_array($tag)); return $tag; } /* }}} */ public function attach($obj, $inf = array()) { /* {{{ */ if (!($obj instanceof Format)) { throw new InvalidArgumentException( 'All formats *MUST* inherit ' . __NAMESPACE__ . '\\Format' ); } $obj->notify(Render::STANDALONE, true); return parent::attach($obj, $inf); } /* }}} */ public function execute(Reader $r) { /* {{{ */ ReaderKeeper::setReader($r); foreach($this as $format) { $format->notify(Render::INIT, true); } $lastdepth = -1; while($r->read()) { $type = $r->nodeType; $data = $retval = $name = $open = false; switch($type) { case \XMLReader::ELEMENT: /* {{{ */ $open = true; /* break intentionally omitted */ case \XMLReader::END_ELEMENT: $name = $r->name; $depth = $r->depth; $attrs = array( Reader::XMLNS_DOCBOOK => array(), Reader::XMLNS_XML => array(), ); if ($r->hasAttributes) { $r->moveToFirstAttribute(); do { $attrs[$r->namespaceURI ?: Reader::XMLNS_DOCBOOK][$r->localName] = $r->value; } while ($r->moveToNextAttribute()); $r->moveToElement(); } $props = array( "empty" => $r->isEmptyElement, "isChunk" => false, "lang" => $r->xmlLang, "ns" => $r->namespaceURI, "sibling" => $lastdepth >= $depth ? $this->STACK[$depth] : "", "depth" => $depth, ); $this->STACK[$depth] = $name; if ($name == "notatag") continue; foreach($this as $format) { $map = $this[$format][\XMLReader::ELEMENT]; if (isset($map[$name]) === false) { $data = $format->UNDEF($open, $name, $attrs, $props); $format->appendData($data); continue; } $tag = $map[$name]; if (is_array($tag)) { $tag = $this->notXPath($tag, $depth); } if ($tag === false) { $data = $format->UNDEF($open, $name, $attrs, $props); $format->appendData($data); continue; } if (strncmp($tag, "format_", 7) !== 0) { $data = $retval = $format->transformFromMap($open, $tag, $name, $attrs, $props); } else { $data = $retval = $format->{$tag}($open, $name, $attrs, $props); } $format->appendData($data); } $lastdepth = $depth; break; /* }}} */ case \XMLReader::TEXT: /* {{{ */ $value = $r->value; $eldepth = $r->depth - 1; $name = $this->STACK[$eldepth]; foreach($this as $format) { $map = $this[$format][\XMLReader::TEXT]; if (isset($map[$name])) { $tag = $map[$name]; if (is_array($tag)) { $tag = $this->notXPath($tag, $eldepth); } if ($tag !== false) { $data = $retval = $format->{$tag}($value, $name); } else { $data = $retval = $format->TEXT($value); } } else { $data = $retval = $format->TEXT($value); } if ($data === false) { $format->appendData($value); } else { $format->appendData($data); } } break; /* }}} */ case \XMLReader::CDATA: /* {{{ */ /* Different formats may want to escape the CDATA sections differently */ $value = $r->value; foreach($this as $format) { $retval = $format->CDATA($value); $format->appendData($retval); } break; /* }}} */ case \XMLReader::WHITESPACE: /* {{{ */ case \XMLReader::SIGNIFICANT_WHITESPACE: /* WS is always WS */ $retval = $r->value; foreach($this as $format) { $format->appendData($retval); } break; /* }}} */ case \XMLReader::PI: $target = $r->name; $data = $r->value; foreach ($this as $format) { $retval = $format->parsePI($target, $data); if ($retval) { $format->appendData($retval); } } break; } } /* Closing time */ foreach($this as $format) { $format->notify(Render::FINALIZE, true); } $r->close(); ReaderKeeper::popReader(); } /* }}} */ } /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/render.php000064400000007261117671476410007674 0ustar00#!@php_bin@ __INSTALLDIR__ . DIRECTORY_SEPARATOR . "phpdotnet" . DIRECTORY_SEPARATOR . "phd" . DIRECTORY_SEPARATOR . "data" . DIRECTORY_SEPARATOR . "langs" . DIRECTORY_SEPARATOR, "phpweb_version_filename" => Config::xml_root() . DIRECTORY_SEPARATOR . 'version.xml', "phpweb_acronym_filename" => Config::xml_root() . DIRECTORY_SEPARATOR . 'entities' . DIRECTORY_SEPARATOR . 'acronyms.xml', )); } if (Config::saveconfig()) { v("Writing the config file", VERBOSE_MESSAGES); file_put_contents("phd.config.php", "attach(new Index); $reader->open(Config::xml_file(), NULL, $readerOpts); $render->execute($reader); $render->detach($format); v("Indexing done", VERBOSE_INDEXING); } else { v("Skipping indexing", VERBOSE_INDEXING); } foreach((array)Config::package() as $package) { $factory = Format_Factory::createFactory($package); // Default to all output formats specified by the package if (count(Config::output_format()) == 0) { Config::set_output_format((array)$factory->getOutputFormats()); } // Register the formats foreach (Config::output_format() as $format) { $render->attach($factory->createFormat($format)); } } // Render formats $reader = make_reader(); $reader->open(Config::xml_file(), NULL, $readerOpts); foreach($render as $format) { $format->notify(Render::VERBOSE, true); } $render->execute($reader); v("Finished rendering", VERBOSE_FORMAT_RENDERING); /* * vim600: sw=4 ts=4 syntax=php et * vim<600: sw=4 ts=4 */ PhD-1.1.6/phd.bat000064400000000155117671476410007142 0ustar00@echo off REM $Id: phd.bat,v 1.4 2009-03-20 12:53:41 bjori Exp $ @"@php_bin@" "@bin_dir@\render.php" %* PhD-1.1.6/LICENSE000064400000001777117671476410006717 0ustar00Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PhD-1.1.6/README000064400000002200117671476410006550 0ustar00PhD - PHP DocBook Copyright(c) 2007-2012 The PHP Documentation Team $Revision$ Installing the PhD renderer: From a PEAR channel: pear install doc.php.net/phd To install the PHP Package: pear install doc.php.net/phd_php To install the PEAR Package: pear install doc.php.net/phd_pear To see all available packages: pear remote-list -c doc.php.net From GIT: Note: Do not install anything from PEAR above. git clone https://git.php.net/repository/phd.git cd phd pear install package.xml package_generic.xml To install the standalone Packages: for i in package_*.xml; do pear install $i; done Requirements: - PHP 5.3 - DOM, libXML2, XMLReader and SQLite3. After installing PhD you can use the `phd` command to render the documentations. To see a list of available packages/formats use the `phd -l` command. By default `phd` use ./output for the rendered files. The `phd` command optionally takes more arguments. For information about those arguments please type `phd -h` - The PHP Documentation team PhD-1.1.6/TODO.RENDERER000064400000001241117671476410007571 0ustar00 TODO: - Learn the alphabet - Sort the elementmaps after purpose and then alphabetically - Sort the methods like the elementmaps - Implement method to generate markup for the default attributes - Implement the remaining elements and attributes of the Docbook format - The abstract formats should be traits - Each Package should define a trait abstracting the general format inspecific customization, f.e. the version info in the PHP package Features: - Auto generate ids for chunks, without requiring xml:id - Create a generic and customizable indexer - Automatically create "lists" (i.e. figures, tables, etc) - The PHP Documentation team .phar/signature.bin000066600000000034117671501060010254 0ustar00_o