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 e147054..9238295 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -285,4 +285,33 @@ 'ViewPdfStrategy' => __NAMESPACE__ . '\Mvc\Service\ViewPdfStrategyFactory', ) ), + 'controllers' => array( + 'invokables' => array( + 'DOMPDFConsole' => 'DOMPDFModule\Controller\ConsoleController' + ) + ), + 'console' => array( + 'router' => array( + 'routes' => array( + 'install-system-fonts' => array( + 'options' => array( + 'route' => 'install system_fonts', + 'defaults' => array( + 'controller' => 'DOMPDFConsole', + 'action' => 'install-system-fonts' + ) + ) + ), + 'install-fonts' => array( + 'options' => array( + 'route' => 'install font_family [] [] []', + 'defaults' => array( + 'controller' => 'DOMPDFConsole', + 'action' => 'install-font-family' + ) + ) + ) + ) + ) + ) ); \ No newline at end of file diff --git a/src/DOMPDFModule/Controller/ConsoleController.php b/src/DOMPDFModule/Controller/ConsoleController.php new file mode 100644 index 0000000..e2d47ce --- /dev/null +++ b/src/DOMPDFModule/Controller/ConsoleController.php @@ -0,0 +1,60 @@ +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) { + if (null == $info) { + /** + * Font not found, default to using the 'normal' font as an additional font. + */ + $fontMap[$type] = $this->getFontDirectory()->getRealPath() . + DIRECTORY_SEPARATOR . + $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'", + $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 7d0e6ad..8a2413e 100644 --- a/src/DOMPDFModule/Module.php +++ b/src/DOMPDFModule/Module.php @@ -19,7 +19,15 @@ namespace DOMPDFModule; -class Module +use Zend\ModuleManager\Feature\ConsoleUsageProviderInterface; +use Zend\Console\Adapter\AdapterInterface as Console; + +/** + * @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 { /** * @return array @@ -34,9 +42,23 @@ public function getAutoloaderConfig() return array( 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array( - __NAMESPACE__ => __DIR__ , + __NAMESPACE__ => __DIR__ ), ), ); } + + public function getConsoleUsage(Console $console) + { + return array( + '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') + ); + } }