public function build() { echo sprintf("\nBuilding easybook %s package\n%s\n", $this->version, str_repeat('=', 80)); // add book script $this->addFile(new \SplFileInfo($this->rootDir . '/book')); // add autoloaders $this->addFile(new \SplFileInfo($this->rootDir . '/vendor/autoload.php')); $this->addFile(new \SplFileInfo($this->rootDir . '/vendor/composer/ClassLoader.php')); $this->addFile(new \SplFileInfo($this->rootDir . '/vendor/composer/autoload_classmap.php')); $this->addFile(new \SplFileInfo($this->rootDir . '/vendor/composer/autoload_namespaces.php')); // add resources $finder = new Finder(); $finder->files()->ignoreVCS(true)->notName('.DS_Store')->in($this->rootDir . '/app/Resources'); foreach ($finder as $file) { $this->addFile($file); } // add sample books $finder = new Finder(); $finder->files()->ignoreVCS(true)->notName('.DS_Store')->exclude('Output')->exclude('Resources')->in(array($this->rootDir . '/doc/easybook-doc-en', $this->rootDir . '/doc/easybook-doc-es')); foreach ($finder as $file) { $this->addFile($file); } // add core classes $finder = new Finder(); $finder->files()->ignoreVCS(true)->name('*.php')->notName('.DS_Store')->exclude('Tests')->notName('Builder.php')->in($this->rootDir . '/src'); foreach ($finder as $file) { $this->addFile($file); } // add vendors $finder = new Finder(); $finder->files()->ignoreVCS(true)->notName('.DS_Store')->notName('README*')->notName('CHANGELOG')->notName('AUTHORS')->notName('create_pear_package.php')->notName('composer.json')->notName('installed.json')->notName('package.xml.tpl')->notName('phpunit.xml.dist')->exclude(array('docs', 'tests', 'twig/bin', 'twig/doc', 'twig/ext', 'twig/test'))->in($this->rootDir . '/vendor'); foreach ($finder as $file) { $this->addFile($file); } // add license and Readme $this->addFile(new \SplFileInfo($this->rootDir . '/LICENSE.md')); $this->addFile(new \SplFileInfo($this->rootDir . '/README.md')); // compress all files into a single ZIP file Toolkit::zip($this->packageDir, './' . $this->zipFile); // delete temp directory $this->filesystem->remove($this->packageDir); echo sprintf("\n %d files added\n\n %s (%.2f MB) package built successfully\n\n", $this->fileCount, $this->zipFile, filesize($this->zipFile) / (1024 * 1024)); }
public function build($zipFile = null) { $this->zipFile = $zipFile ?: sprintf('%s/easybook-%s.zip', $this->rootDir, $this->version); if (file_exists($this->zipFile)) { unlink($this->zipFile); } // add package files $this->addBookScript(); $this->addAutoloaders(); $this->addResources(); $this->addSampleBooks(); $this->addCommandHelp(); $this->addCoreClasses(); $this->addVendors(); $this->addLicenseAndReadme(); // compress all files into a single ZIP file Toolkit::zip($this->packageDir, $this->zipFile); // delete temp directory $this->filesystem->remove($this->packageDir); echo sprintf("\n %d files added\n\n %s (%.2f MB) package built successfully\n\n", $this->fileCount, $this->zipFile, filesize($this->zipFile) / (1024 * 1024)); }
public function assembleBook() { // set the edition id needed for ebook generation $this->app->edition('id', $this->app['publishing.id']); // variables needed to hold the list of images and fonts of the book $bookImages = array(); $bookFonts = array(); // prepare the temp directory used to build the book $bookTempDir = $this->app['app.dir.cache'] . '/' . $this->app['publishing.book.slug'] . '-' . $this->app['publishing.edition']; $this->app->get('filesystem')->mkdir(array($bookTempDir, $bookTempDir . '/book', $bookTempDir . '/book/META-INF', $bookTempDir . '/book/OEBPS', $bookTempDir . '/book/OEBPS/css', $bookTempDir . '/book/OEBPS/images', $bookTempDir . '/book/OEBPS/fonts')); // generate easybook CSS file if ($this->app->edition('include_styles')) { $this->app->renderThemeTemplate('style.css.twig', array('resources_dir' => '..'), $bookTempDir . '/book/OEBPS/css/easybook.css'); // copy book fonts and prepare font data for ebook manifest $this->app->get('filesystem')->copy($this->app['app.dir.resources'] . '/Fonts/Inconsolata/Inconsolata.ttf', $bookTempDir . '/book/OEBPS/fonts/Inconsolata.ttf'); $bookFonts[] = array('id' => 'font-1', 'filePath' => 'fonts/Inconsolata.ttf', 'mediaType' => 'application/octet-stream'); } // generate custom CSS file $customCss = $this->app->getCustomTemplate('style.css'); if (file_exists($customCss)) { $this->app->get('filesystem')->copy($customCss, $bookTempDir . '/book/OEBPS/css/styles.css', true); } // each book element will generate an HTML page // use automatic slugs (chapter-1, chapter-2, ...) instead of // semantic slugs (lorem-ipsum, dolor-sit-amet, ...) $this->app->set('publishing.slugs', array()); $items = array(); foreach ($this->app['publishing.items'] as $item) { $pageName = array_key_exists('number', $item['config']) ? $item['config']['element'] . ' ' . $item['config']['number'] : $item['config']['element']; $slug = $this->app->get('slugger')->slugify(trim($pageName)); $item['slug'] = $slug; // TODO: document this new item property $item['fileName'] = $slug . '.html'; $items[] = $item; } // update `publishing items` with the new slug value $this->app->set('publishing.items', $items); // generate one HTML page for every book item $items = array(); foreach ($this->app['publishing.items'] as $item) { $this->app->renderThemeTemplate('chunk.twig', array('item' => $item, 'has_custom_css' => file_exists($customCss)), $bookTempDir . '/book/OEBPS/' . $item['fileName']); } // copy book images and prepare image data for ebook manifest if (file_exists($imagesDir = $this->app['publishing.dir.contents'] . '/images')) { $images = $this->app->get('finder')->files()->in($imagesDir); $i = 1; foreach ($images as $image) { $this->app->get('filesystem')->copy($image->getPathName(), $bookTempDir . '/book/OEBPS/images/' . $image->getFileName()); $bookImages[] = array('id' => 'figure-' . $i++, 'filePath' => 'images/' . $image->getFileName(), 'mediaType' => 'image/' . pathinfo($image->getFilename(), PATHINFO_EXTENSION)); } } // look for cover images $cover = null; if (null != ($image = $this->app->getCustomCoverImage())) { list($width, $height, $type) = getimagesize($image); $cover = array('height' => $height, 'width' => $width, 'filePath' => 'images/' . basename($image), 'mediaType' => image_type_to_mime_type($type)); // copy the cover image $this->app->get('filesystem')->copy($image, $bookTempDir . '/book/OEBPS/images/' . basename($image)); } // generate book cover $this->app->renderThemeTemplate('cover.twig', array('cover' => $cover), $bookTempDir . '/book/OEBPS/titlepage.html'); // generate OPF file $this->app->renderThemeTemplate('content.opf.twig', array('cover' => $cover, 'has_custom_css' => file_exists($customCss), 'fonts' => $bookFonts, 'images' => $bookImages), $bookTempDir . '/book/OEBPS/content.opf'); // generate NCX file $this->app->renderThemeTemplate('toc.ncx.twig', array(), $bookTempDir . '/book/OEBPS/toc.ncx'); // generate container.xml and mimetype files $this->app->renderThemeTemplate('container.xml.twig', array(), $bookTempDir . '/book/META-INF/container.xml'); $this->app->renderThemeTemplate('mimetype.twig', array(), $bookTempDir . '/book/mimetype'); // compress book contents as ZIP file and rename to .epub // TODO: the name of the book file (book.epub) must be configurable Toolkit::zip($bookTempDir . '/book', $bookTempDir . '/book.zip'); $this->app->get('filesystem')->copy($bookTempDir . '/book.zip', $this->app['publishing.dir.output'] . '/book.epub', true); // remove temp directory used to build the book $this->app->get('filesystem')->remove($bookTempDir); }
/** * It generates the compressed file required for the ePub book. * To compress the contents, it uses the 'Zip' PHP extension. * * @param string $directory Book contents directory * @param string $zip_file The path of the generated ZIP file */ private function zipBookContentsWithPhpExtension($directory, $zip_file) { Toolkit::zip($directory, $zip_file); }
private function zipBookContents($directory, $zip_file) { if (extension_loaded('zip')) { return Toolkit::zip($directory, $zip_file); } // After several hours trying to create ZIP files with lots of PHP // tools and libraries (Archive_Zip, Pclzip, zetacomponents/archive, ...) // I can't produce a proper ZIP file for ebook readers. // Therefore, if ZIP extension isn't enabled, the ePub ZIP file is // generated by executing 'zip' command // check if 'zip' command exists $process = new Process('zip'); $process->run(); if (!$process->isSuccessful()) { throw new \RuntimeException("[ERROR] You must enable the ZIP extension in PHP \n" . " or your system should be able to execute 'zip' console command."); } // To generate the ePub file, you must execute the following commands: // $ cd /path/to/ebook/contents // $ zip -X0 book.zip mimetype // $ zip -rX9 book.zip * -x mimetype $command = sprintf('cd %s && zip -X0 %s mimetype && zip -rX9 %s * -x mimetype', $directory, $zip_file, $zip_file); $process = new Process($command); $process->run(); if (!$process->isSuccessful()) { throw new \RuntimeException("[ERROR] 'zip' command execution wasn't successful.\n\n" . "Executed command:\n" . " {$command}\n\n" . "Result:\n" . $process->getErrorOutput()); } }