From 4bf498f406e389452a664cb23fbfea77ba014835 Mon Sep 17 00:00:00 2001 From: "Raymond J. Kolbe" Date: Sun, 7 Oct 2012 17:10:06 -0400 Subject: [PATCH 1/2] Started adding cli functionality. Moved config loader callback into its own file. --- bin/dompdf | 4 + bin/dompdf.php | 26 +++ config/module.config.php | 29 +++ .../Controller/CommandLineController.php | 61 +++++ .../Font/Exception/InvalidFontFile.php | 9 + src/DOMPDFModule/Font/FontFamilyInstaller.php | 212 ++++++++++++++++++ src/DOMPDFModule/Module.php | 84 ++----- src/DOMPDFModule/Module/ConfigListener.php | 73 ++++++ 8 files changed, 430 insertions(+), 68 deletions(-) create mode 100755 bin/dompdf create mode 100644 bin/dompdf.php create mode 100644 src/DOMPDFModule/Controller/CommandLineController.php create mode 100644 src/DOMPDFModule/Font/Exception/InvalidFontFile.php create mode 100644 src/DOMPDFModule/Font/FontFamilyInstaller.php create mode 100644 src/DOMPDFModule/Module/ConfigListener.php diff --git a/bin/dompdf b/bin/dompdf new file mode 100755 index 0000000..ed040bc --- /dev/null +++ b/bin/dompdf @@ -0,0 +1,4 @@ +#!/usr/bin/env php +run(); diff --git a/config/module.config.php b/config/module.config.php index a0a046c..a5f027d 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -275,4 +275,33 @@ 'ViewPdfStrategy' => 'DOMPDFModule\Mvc\Service\ViewPdfStrategyFactory', ) ), + 'controllers' => array( + 'invokables' => array( + 'DOMPDFModule\Controller\CommandLineController' => 'DOMPDFModule\Controller\CommandLineController' + ) + ), + 'console' => array( + 'router' => array( + 'routes' => array( + 'install-system-fonts' => array( + 'options' => array( + 'route' => 'install system_fonts', + 'defaults' => array( + 'controller' => 'DOMPDFModule\Controller\CommandLineController', + 'action' => 'install-system-fonts' + ) + ) + ), + 'install-fonts' => array( + 'options' => array( + 'route' => 'install font_family [] [] []', + 'defaults' => array( + 'controller' => 'DOMPDFModule\Controller\CommandLineController', + 'action' => 'install-font-family' + ) + ) + ) + ) + ) + ) ); \ No newline at end of file diff --git a/src/DOMPDFModule/Controller/CommandLineController.php b/src/DOMPDFModule/Controller/CommandLineController.php new file mode 100644 index 0000000..a5c322f --- /dev/null +++ b/src/DOMPDFModule/Controller/CommandLineController.php @@ -0,0 +1,61 @@ +plugin('params'); + $fontFamily = $params->fromRoute('name', false); + $normalFontPath = $params->fromRoute('file', false); + + $installer = new FontFamilyInstaller($fontFamily, $normalFontPath); + + if ($bold = $params->fromRoute('bold_file', false)) { + $installer->queueFont($bold, FontFamilyInstaller::FONT_TYPE_BOLD); + } + + if ($italic = $params->fromRoute('italic_file', false)) { + $installer->queueFont($italic, FontFamilyInstaller::FONT_TYPE_ITALIC); + } + + if ($boldItalic = $params->fromRoute('bold_italic_file', false)) { + $installer->queueFont($boldItalic, FontFamilyInstaller::FONT_TYPE_BOLD_ITALIC); + } + + $installer->install(); + } + + public function installSystemFontsAction() + { + $fonts = FontMetrics::get_system_fonts(); + + foreach ($fonts as $family => $files) { + + if (!isset($files['normal'])) { + continue; + } + + $installer = new FontFamilyInstaller($family, $files["normal"]); + + if (isset($files["bold"])) { + $installer->queueFont($files['bold'], FontFamilyInstaller::FONT_TYPE_BOLD); + } + + if (isset($files["italic"])) { + $installer->queueFont($files['italic'], FontFamilyInstaller::FONT_TYPE_ITALIC); + } + + if (isset($files["bold_italic"])) { + $installer->queueFont($files['bold_italic'], FontFamilyInstaller::FONT_TYPE_BOLD_ITALIC); + } + + $installer->install(); + } + } +} \ No newline at end of file diff --git a/src/DOMPDFModule/Font/Exception/InvalidFontFile.php b/src/DOMPDFModule/Font/Exception/InvalidFontFile.php new file mode 100644 index 0000000..64e0c3e --- /dev/null +++ b/src/DOMPDFModule/Font/Exception/InvalidFontFile.php @@ -0,0 +1,9 @@ + array('-Bold', '_Bold', 'b', 'B', 'bd', 'BD'), + 'italic' => array('-Oblique', '_Italic', 'i', 'I'), + 'bold_italic' => array('-BoldOblique', '_Bold_Italic', 'bi', 'BI', 'ib', 'IB'), + ); + + public function __construct($family, $normalFontPath) + { + $this->family = $family; + $this->queueFont($normalFontPath); + } + + /** + * + * @todo Rename to setInstallDirectory + * + * @param type $path + * @return \DOMPDFModule\Font\FontFamilyInstaller + * @throws \RuntimeException + */ + public function setFontDirectory($path) + { + $this->fontDirectory = new FileInfo($path); + if (!$this->fontDirectory->isDir()) { + throw new \RuntimeException('Font directory is not a directory at all.'); + } + + if (!$this->fontDirectory->isWritable()) { + throw new \RuntimeException('Font directory is not writable.'); + } + + return $this; + } + + /** + * + * @todo Rename to getInstallDirectory + * + * @return type + */ + public function getFontDirectory() + { + if (!isset($this->fontDirectory)) { + $this->setFontDirectory(DOMPDF_FONT_DIR); + } + return $this->fontDirectory; + } + + /** + * + * @todo Potentially rename to queueFontForInstallation + * + * @param type $path + * @param type $type + * @return \DOMPDFModule\Font\FontFamilyInstaller + * @throws Exception\InvalidFontFile + */ + public function queueFont($path, $type = self::FONT_TYPE_NORMAL) + { + $font = new FileInfo($path); + if (!$font->isReadable()) { + throw new Exception\InvalidFontFile(sprintf( + "'%s' is not readable.", + $path + )); + } + + if (!in_array($font->getExtension(), static::$validExtensions)) { + throw new Exception\InvalidFontFile(sprintf( + "Invalid font extension '%s' provided. Only ttf and otf are supported", + $font->getExtension() + )); + } + + switch ($type) { + case static::FONT_TYPE_NORMAL; + if (isset($this->normalFontPath)) { + throw new Exception\InvalidFontFile( + "Normal font can not be queued after installer instantiation." + ); + } + $this->normalFontPath = $font; + break; + case static::FONT_TYPE_BOLD; + $this->boldFontPath = $font; + break; + case static::FONT_TYPE_ITALIC; + $this->italicFontPath = $font; + break; + case static::FONT_TYPE_BOLD_ITALIC; + $this->boldItalicFontPath = $font; + break; + default : + throw new Exception\InvalidFontFile("Invalid type specified."); + } + + return $this; + } + + public function install() + { + if (!$this->boldFontPath) { + $this->boldFontPath = $this->findAdditionalFont(static::FONT_TYPE_BOLD); + } + + if (!$this->italicFontPath) { + $this->italicFontPath = $this->findAdditionalFont(static::FONT_TYPE_ITALIC); + } + + if (!$this->boldItalicFontPath) { + $this->boldItalicFontPath = $this->findAdditionalFont(static::FONT_TYPE_BOLD_ITALIC); + } + + $fonts = array( + 'normal' => $this->normalFontPath, + 'bold' => $this->boldFontPath, + 'italic' => $this->italicFontPath, + 'bold_italic' => $this->boldItalicFontPath + ); + + FontMetrics::init(); + + $fontMap = array(); + + foreach ($fonts as $type => $info) { + $destination = new FileInfo($this->getFontDirectory()->getRealPath() . DIRECTORY_SEPARATOR . $info->getBasename()); + + if (null == $info) { + /** + * Font not found, default to using the 'normal' font as an additional font. + */ + $fontMap[$type] = $destination->getPath() . + DIRECTORY_SEPARATOR . + $destination->getBasename('.' . $destination->getExtension()); + continue; + } + + if (!copy($info->getRealPath(), $destination->getPath() . DIRECTORY_SEPARATOR .$destination->getBasename())) { + throw new \RuntimeException(sprintf( + "Unable to copy '%s' to '%s'", + $info->getRealPath(), + $destination->getPath() . DIRECTORY_SEPARATOR . $destination->getBasename() + )); + } + + //echo "Generating Adobe Font Metrics for $entry_name...\n"; + $entry = $destination->getPath() . + DIRECTORY_SEPARATOR . + $destination->getBasename('.' . $destination->getExtension()); + + $font = FontLib::load($destination->getPath() .'/'.$destination->getBasename()); + $font->saveAdobeFontMetrics($entry . '.ufm'); + + $fontMap[$type] = $entry; + } + + FontMetrics::set_font_family($this->family, $fontMap); + FontMetrics::save_font_families(); + } + + protected function findAdditionalFont($type) + { + foreach (static::$additionalFontPatterns[$type] as $pattern) { + $path = $this->normalFontPath->getPath() . + DIRECTORY_SEPARATOR . + $this->normalFontPath->getBasename('.' . $this->normalFontPath->getExtension()) . + $pattern . + '.' . $this->normalFontPath->getExtension(); + + $font = new FileInfo($path); + + if (!$font->isReadable()) { + continue; + } + + return $font; + } + return null; + } +} diff --git a/src/DOMPDFModule/Module.php b/src/DOMPDFModule/Module.php index 3851e46..619e773 100644 --- a/src/DOMPDFModule/Module.php +++ b/src/DOMPDFModule/Module.php @@ -20,45 +20,16 @@ namespace DOMPDFModule; use Zend\ModuleManager\ModuleManager; -use Zend\ModuleManager\ModuleEvent; +use Zend\ModuleManager\Feature\ConsoleUsageProviderInterface; +use Zend\Console\Adapter\AdapterInterface as Console; -class Module +/** + * @todo On Composer post-install, copy dompdf_font_family_cache.dist.php + * to font directory as a non-dist file. Define __DOMPDF_FONT_CACHE_FILE + * to point to this new file. + */ +class Module implements ConsoleUsageProviderInterface { - /** - * An array of keys that map DOMPDF define keys to DOMPDFModule config's - * keys. - * - * @var array - */ - private static $configCompatMapping = array( - 'font_directory' => 'DOMPDF_FONT_DIR', - 'font_cache_directory' => 'DOMPDF_FONT_CACHE', - 'temporary_directory' => 'DOMPDF_TEMP_DIR', - 'chroot' => 'DOMPDF_CHROOT', - 'unicode_enabled' => 'DOMPDF_UNICODE_ENABLED', - 'enable_fontsubsetting' => 'DOMPDF_ENABLE_FONTSUBSETTING', - 'pdf_backend' => 'DOMPDF_PDF_BACKEND', - 'default_media_type' => 'DOMPDF_DEFAULT_MEDIA_TYPE', - 'default_paper_size' => 'DOMPDF_DEFAULT_PAPER_SIZE', - 'default_font' => 'DOMPDF_DEFAULT_FONT', - 'dpi' => 'DOMPDF_DPI', - 'enable_php' => 'DOMPDF_ENABLE_PHP', - 'enable_javascript' => 'DOMPDF_ENABLE_JAVASCRIPT', - 'enable_remote' => 'DOMPDF_ENABLE_REMOTE', - 'log_output_file' => 'DOMPDF_LOG_OUTPUT_FILE', - 'font_height_ratio' => 'DOMPDF_FONT_HEIGHT_RATIO', - 'enable_css_float' => 'DOMPDF_ENABLE_CSS_FLOAT', - 'enable_html5parser' => 'DOMPDF_ENABLE_HTML5PARSER', - 'debug_png' => 'DEBUGPNG', - 'debug_keep_temp' => 'DEBUGKEEPTEMP', - 'debug_css' => 'DEBUGCSS', - 'debug_layout' => 'DEBUG_LAYOUT', - 'debug_layout_links' => 'DEBUG_LAYOUT_LINES', - 'debug_layout_blocks' => 'DEBUG_LAYOUT_BLOCKS', - 'debug_layout_inline' => 'DEBUG_LAYOUT_INLINE', - 'debug_layout_padding_box' => 'DEBUG_LAYOUT_PADDINGBOX' - ); - /** * @param ModuleManager $moduleManager * @return void @@ -66,37 +37,7 @@ class Module public function init(ModuleManager $moduleManager) { $eventManager = $moduleManager->getEventManager(); - $eventManager->attach('loadModules.post', array($this, 'loadConfiguration')); - } - - /** - * Event callback called after modules are loaded, responsible - * for loading DOMPDF config. - * - * @param ModuleEvent $e - * @return void - */ - public function loadConfiguration(ModuleEvent $event) - { - define("DOMPDF_DIR", __DIR__ . '/../../vendor/dompdf'); - define("DOMPDF_INC_DIR", DOMPDF_DIR . "/include"); - define("DOMPDF_LIB_DIR", DOMPDF_DIR . "/lib"); - - $config = $event->getConfigListener()->getMergedConfig(); - foreach ($config['dompdf_module'] as $key => $value) { - if (! array_key_exists($key, self::$configCompatMapping)) { - continue; - } - - define(self::$configCompatMapping[$key], $value); - } - - define("DOMPDF_AUTOLOAD_PREPEND", false); - - require_once DOMPDF_INC_DIR . '/functions.inc.php'; - require_once DOMPDF_LIB_DIR . '/html5lib/Parser.php'; - require_once DOMPDF_INC_DIR . '/autoload.inc.php'; - require_once __DIR__ . '/../../config/module.compat.php'; + $eventManager->attach('loadModules.post', array(new Module\ConfigListener(), 'loadConfig')); } /** @@ -117,4 +58,11 @@ public function getAutoloaderConfig() ), ); } + + public function getConsoleUsage(Console $console) + { + return array( + 'Sample DOMPDF usage message' + ); + } } diff --git a/src/DOMPDFModule/Module/ConfigListener.php b/src/DOMPDFModule/Module/ConfigListener.php new file mode 100644 index 0000000..2fd4239 --- /dev/null +++ b/src/DOMPDFModule/Module/ConfigListener.php @@ -0,0 +1,73 @@ + 'DOMPDF_FONT_DIR', + 'font_cache_directory' => 'DOMPDF_FONT_CACHE', + 'temporary_directory' => 'DOMPDF_TEMP_DIR', + 'chroot' => 'DOMPDF_CHROOT', + 'unicode_enabled' => 'DOMPDF_UNICODE_ENABLED', + 'enable_fontsubsetting' => 'DOMPDF_ENABLE_FONTSUBSETTING', + 'pdf_backend' => 'DOMPDF_PDF_BACKEND', + 'default_media_type' => 'DOMPDF_DEFAULT_MEDIA_TYPE', + 'default_paper_size' => 'DOMPDF_DEFAULT_PAPER_SIZE', + 'default_font' => 'DOMPDF_DEFAULT_FONT', + 'dpi' => 'DOMPDF_DPI', + 'enable_php' => 'DOMPDF_ENABLE_PHP', + 'enable_javascript' => 'DOMPDF_ENABLE_JAVASCRIPT', + 'enable_remote' => 'DOMPDF_ENABLE_REMOTE', + 'log_output_file' => 'DOMPDF_LOG_OUTPUT_FILE', + 'font_height_ratio' => 'DOMPDF_FONT_HEIGHT_RATIO', + 'enable_css_float' => 'DOMPDF_ENABLE_CSS_FLOAT', + 'enable_html5parser' => 'DOMPDF_ENABLE_HTML5PARSER', + 'debug_png' => 'DEBUGPNG', + 'debug_keep_temp' => 'DEBUGKEEPTEMP', + 'debug_css' => 'DEBUGCSS', + 'debug_layout' => 'DEBUG_LAYOUT', + 'debug_layout_links' => 'DEBUG_LAYOUT_LINES', + 'debug_layout_blocks' => 'DEBUG_LAYOUT_BLOCKS', + 'debug_layout_inline' => 'DEBUG_LAYOUT_INLINE', + 'debug_layout_padding_box' => 'DEBUG_LAYOUT_PADDINGBOX' + ); + + /** + * Event callback called after modules are loaded, responsible + * for loading DOMPDF config. + * + * @param ModuleEvent $e + * @return void + */ + public function loadConfig(ModuleEvent $event) + { + define("DOMPDF_DIR", __DIR__ . '/../../../vendor/dompdf'); + define("DOMPDF_INC_DIR", DOMPDF_DIR . "/include"); + define("DOMPDF_LIB_DIR", DOMPDF_DIR . "/lib"); + + $config = $event->getConfigListener()->getMergedConfig(); + foreach ($config['dompdf_module'] as $key => $value) { + if (! array_key_exists($key, self::$configCompatMapping)) { + continue; + } + + define(self::$configCompatMapping[$key], $value); + } + + define("DOMPDF_AUTOLOAD_PREPEND", false); + + require_once DOMPDF_INC_DIR . '/functions.inc.php'; + require_once DOMPDF_LIB_DIR . '/html5lib/Parser.php'; + require_once DOMPDF_INC_DIR . '/autoload.inc.php'; + require_once __DIR__ . '/../../../config/module.compat.php'; + } +} \ No newline at end of file From 1a9f36ea111254a652ba9fd277fd494b6f9c8dfe Mon Sep 17 00:00:00 2001 From: "Raymond J. Kolbe" Date: Wed, 10 Oct 2012 21:08:12 -0400 Subject: [PATCH 2/2] Started to refactor module. --- config/module.config.php | 6 +++--- ...ommandLineController.php => ConsoleController.php} | 2 +- src/DOMPDFModule/Font/FontFamilyInstaller.php | 11 ++++------- src/DOMPDFModule/Module.php | 9 ++++++++- 4 files changed, 16 insertions(+), 12 deletions(-) rename src/DOMPDFModule/Controller/{CommandLineController.php => ConsoleController.php} (97%) diff --git a/config/module.config.php b/config/module.config.php index 2da9671..9238295 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -287,7 +287,7 @@ ), 'controllers' => array( 'invokables' => array( - 'DOMPDFModule\Controller\CommandLineController' => 'DOMPDFModule\Controller\CommandLineController' + 'DOMPDFConsole' => 'DOMPDFModule\Controller\ConsoleController' ) ), 'console' => array( @@ -297,7 +297,7 @@ 'options' => array( 'route' => 'install system_fonts', 'defaults' => array( - 'controller' => 'DOMPDFModule\Controller\CommandLineController', + 'controller' => 'DOMPDFConsole', 'action' => 'install-system-fonts' ) ) @@ -306,7 +306,7 @@ 'options' => array( 'route' => 'install font_family [] [] []', 'defaults' => array( - 'controller' => 'DOMPDFModule\Controller\CommandLineController', + 'controller' => 'DOMPDFConsole', 'action' => 'install-font-family' ) ) diff --git a/src/DOMPDFModule/Controller/CommandLineController.php b/src/DOMPDFModule/Controller/ConsoleController.php similarity index 97% rename from src/DOMPDFModule/Controller/CommandLineController.php rename to src/DOMPDFModule/Controller/ConsoleController.php index c277937..e2d47ce 100644 --- a/src/DOMPDFModule/Controller/CommandLineController.php +++ b/src/DOMPDFModule/Controller/ConsoleController.php @@ -6,7 +6,7 @@ use DOMPDFModule\Font\FontFamilyInstaller; use Font_Metrics as FontMetrics; -class CommandLineController extends Controller +class ConsoleController extends Controller { public function installFontFamilyAction() { diff --git a/src/DOMPDFModule/Font/FontFamilyInstaller.php b/src/DOMPDFModule/Font/FontFamilyInstaller.php index 0061564..7af56b1 100644 --- a/src/DOMPDFModule/Font/FontFamilyInstaller.php +++ b/src/DOMPDFModule/Font/FontFamilyInstaller.php @@ -11,9 +11,6 @@ * proper automatic font additions of bold, italic, bold italic. * * @see http://v1.jontangerine.com/silo/typography/naming/ for naming scheme. - * - * @todo Rename class to TypefaceInstaller since Typeface is what we are installing, - * and "Fonts" are the individual files (e.g. bold, italic, etc). */ class FontFamilyInstaller { @@ -155,18 +152,18 @@ public function install() $fontMap = array(); foreach ($fonts as $type => $info) { - $destination = new FileInfo($this->getFontDirectory()->getRealPath() . DIRECTORY_SEPARATOR . $info->getBasename()); - if (null == $info) { /** * Font not found, default to using the 'normal' font as an additional font. */ - $fontMap[$type] = $destination->getPath() . + $fontMap[$type] = $this->getFontDirectory()->getRealPath() . DIRECTORY_SEPARATOR . - $destination->getBasename('.' . $destination->getExtension()); + $fonts['normal']->getBasename('.' . $destination->getExtension()); continue; } + $destination = new FileInfo($this->getFontDirectory()->getRealPath() . DIRECTORY_SEPARATOR . $info->getBasename()); + if (!copy($info->getRealPath(), $destination->getPath() . DIRECTORY_SEPARATOR .$destination->getBasename())) { throw new \RuntimeException(sprintf( "Unable to copy '%s' to '%s'", diff --git a/src/DOMPDFModule/Module.php b/src/DOMPDFModule/Module.php index 3c6909f..8a2413e 100644 --- a/src/DOMPDFModule/Module.php +++ b/src/DOMPDFModule/Module.php @@ -51,7 +51,14 @@ public function getAutoloaderConfig() public function getConsoleUsage(Console $console) { return array( - 'Sample DOMPDF usage message' + 'install system_fonts' => 'Installs system-installed fonts to DOMPDF font directory.', + 'install font_family [] [] []' => 'Installs font(s) to DOMPDF font directory', + + array('' , 'Font family name'), + array('' , 'Path to .otf or .ttf regular font file'), + array('' , 'Path to .otf or .ttf bold font file'), + array('' , 'Path to .otf or .ttf italic font file'), + array('' , 'Path to .otf or .ttf bold italic font file') ); } }