function download_open_export_file( $filename ) { $filepath = \PressBooks\Export\Export::getExportFolder() . $filename; if ( ! is_readable( $filepath ) ) { // Cannot read file wp_die( __( 'File not found', 'pressbooks-textbook' ) . ": $filename", '', array( 'response' => 404 ) ); } // Force download set_time_limit( 0 ); header( 'Content-Description: File Transfer' ); header( 'Content-Type: ' . \Pressbooks\Export\Export::mimeType( $filepath ) ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Transfer-Encoding: binary' ); header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' ); header( 'Pragma: public' ); header( 'Content-Length: ' . filesize( $filepath ) ); @ob_clean(); flush(); while ( @ob_end_flush() ); // Fix out-of-memory problem readfile( $filepath ); exit; }
/** * Truncate the exports directory, delete old files. * * @param int $max */ function truncate_exports($max) { $max = absint($max); $dir = \PressBooks\Export\Export::getExportFolder(); $files = group_exports(); $i = 1; foreach ($files as $date => $exports) { if ($i > $max) { foreach ($exports as $export) { $export = realpath($dir . $export); unlink($export); } } ++$i; } }
/** * Scan the export directory, return latest of each file type * * @return array */ function latest_exports() { $suffix = array('._3.epub', '.epub', '.pdf', '.mobi', '.hpub', '.icml', '.html', '.xml'); $dir = \PressBooks\Export\Export::getExportFolder(); $files = array(); // group by extension, sort by date newest first foreach (\PressBooks\Utility\scandir_by_date($dir) as $file) { $ext = strstr($file, '.'); $files[$ext][] = $file; } // get only one of the latest of each type $latest = array(); foreach ($suffix as $value) { if (array_key_exists($value, $files)) { $latest[$value] = $files[$value][0]; } } // @TODO filter these results against user prefs return $latest; }
/** * Scan the export directory, return latest of each file type * * @return array */ function latest_exports() { $suffix = array( '._3.epub', '.epub', '.pdf', '.mobi', '.hpub', '.icml', '.html', '.xml', '._vanilla.xml', '._oss.pdf', ); $dir = \PressBooks\Export\Export::getExportFolder(); $files = array(); // group by extension, sort by date newest first foreach ( \PressBooks\Utility\scandir_by_date( $dir ) as $file ) { // only interested in the part of filename starting with the timestamp preg_match( '/-\d{10,11}(.*)/', $file, $matches ); // grab the first captured parenthisized subpattern $ext = $matches[1]; $files[$ext][] = $file; } // get only one of the latest of each type $latest = array(); foreach ( $suffix as $value ) { if ( array_key_exists( $value, $files ) ) { $latest[$value] = $files[$value][0]; } } // @TODO filter these results against user prefs return $latest; }
/** * Uses $this->manifest to generate itself. * * @param array $book_contents * @param array $metadata */ protected function createToc($book_contents, $metadata) { $vars = array('post_title' => '', 'stylesheet' => $this->stylesheet, 'post_content' => '', 'isbn' => @$metadata['pb_ebook_isbn']); $options = get_option('pressbooks_theme_options_global'); // Start by inserting self into correct manifest position $array_pos = $this->positionOfToc(); $file_id = 'table-of-contents'; $filename = "{$file_id}.{$this->filext}"; $vars['post_title'] = __('Table Of Contents', 'pressbooks'); $this->manifest = array_slice($this->manifest, 0, $array_pos + 1, true) + array($file_id => array('ID' => -1, 'post_title' => $vars['post_title'], 'filename' => $filename)) + array_slice($this->manifest, $array_pos + 1, count($this->manifest) - 1, true); // HTML $li_count = 0; $i = 1; $html = '<div id="toc"><h1>' . __('Contents', 'pressbooks') . '</h1><ul>'; foreach ($this->manifest as $k => $v) { // We only care about front-matter, part, chapter, back-matter // Skip the rest $subtitle = ''; $author = ''; $license = ''; $title = Sanitize\strip_br($v['post_title']); if (preg_match('/^front-matter-/', $k)) { $class = 'front-matter '; $class .= \PressBooks\Taxonomy\front_matter_type($v['ID']); $subtitle = trim(get_post_meta($v['ID'], 'pb_subtitle', true)); $author = trim(get_post_meta($v['ID'], 'pb_section_author', true)); $license = $options['copyright_license'] ? get_post_meta($v['ID'], 'pb_section_license', true) : ''; } elseif (preg_match('/^part-/', $k)) { $class = 'part'; if (get_post_meta($v['ID'], 'pb_part_invisible', true) == 'on') { $class .= ' display-none'; } } elseif (preg_match('/^chapter-/', $k)) { $class = 'chapter'; $class .= \PressBooks\Taxonomy\chapter_type($v['ID']); $subtitle = trim(get_post_meta($v['ID'], 'pb_subtitle', true)); $author = trim(get_post_meta($v['ID'], 'pb_section_author', true)); $license = $options['copyright_license'] ? get_post_meta($v['ID'], 'pb_section_license', true) : ''; if ($this->numbered && \PressBooks\Taxonomy\chapter_type($v['ID']) !== 'numberless') { $title = " {$i}. " . $title; } if (\PressBooks\Taxonomy\chapter_type($v['ID']) !== 'numberless') { ++$i; } } elseif (preg_match('/^back-matter-/', $k)) { $class = 'back-matter '; $class .= \PressBooks\Taxonomy\back_matter_type($v['ID']); $subtitle = trim(get_post_meta($v['ID'], 'pb_subtitle', true)); $author = trim(get_post_meta($v['ID'], 'pb_section_author', true)); $license = $options['copyright_license'] ? get_post_meta($v['ID'], 'pb_section_license', true) : ''; } else { continue; } $html .= sprintf('<li class="%s"><a href="%s"><span class="toc-chapter-title">%s</span>', $class, $v['filename'], Sanitize\decode($title)); if ($subtitle) { $html .= ' <span class="chapter-subtitle">' . Sanitize\decode($subtitle) . '</span>'; } if ($author) { $html .= ' <span class="chapter-author">' . Sanitize\decode($author) . '</span>'; } if ($license) { $html .= ' <span class="chapter-license">' . $license . '</span> '; } $html .= "</a>"; if (\PressBooks\Export\Export::shouldParseSections() == true) { $sections = \PressBooks\Book::getSubsections($v['ID']); if ($sections) { $s = 1; $html .= '<ul class="sections">'; foreach ($sections as $section) { $html .= '<li class="section"><a href="' . $v['filename'] . '#section-' . $s . '"><span class="toc-subsection-title">' . Sanitize\decode($section) . '</span></a></li>'; ++$s; } $html .= '</ul>'; } } $html .= "</li>\n"; ++$li_count; } if (0 == $li_count) { $html .= '<li></li>'; } $html .= "</ul></div>\n"; // Create file $vars['post_content'] = $html; file_put_contents($this->tmpDir . "/OEBPS/{$filename}", $this->loadTemplate($this->dir . '/templates/xhtml.php', $vars)); }
/** * Restructures \PressBooks\Book::getBookContents() into a format more useful * for direct iteration, and tracks a nesting level for Bookmark and ToC * entries. * * @return array */ function getOrderedBookContents() { $book_contents = \PressBooks\Book::getBookContents(); $ordered = array(); foreach ($book_contents as $type => $struct) { if (strpos($type, '__') === 0) { continue; // Skip __magic keys } switch ($type) { case 'part': foreach ($struct as $part) { $part_content = trim(get_post_meta($part['ID'], 'pb_part_content', true)); if ($part_content || $this->atLeastOneExport($part['chapters'])) { if (!empty($part['post_content'])) { $part['mpdf_level'] = 1; $part['post_content'] .= $part_content; } else { $part['post_content'] = $part_content; $part['mpdf_level'] = 0; } $ordered[] = $part; foreach ($part['chapters'] as $chapter) { if (!$chapter['export']) { continue; } $chapter['mpdf_level'] = $part['mpdf_level'] + 1; $ordered[] = $chapter; if (\PressBooks\Export\Export::shouldParseSections() == true) { $sections = \PressBooks\Book::getSubsections($chapter['ID']); if ($sections) { foreach ($sections as $section) { $section['mpdf_level'] = $part['mpdf_level'] + 2; $ordered[] = $section; } } } } } } break; default: foreach ($struct as $item) { if (!$item['export']) { continue; } $item['mpdf_level'] = 1; $ordered[] = $item; if (\PressBooks\Export\Export::shouldParseSections() == true) { $sections = \PressBooks\Book::getSubsections($item['ID']); if ($sections) { foreach ($sections as $section) { $section['mpdf_level'] = 2; $ordered[] = $section; } } } } break; } } return $ordered; }
/** * @param array $book_contents * @param array $metadata */ protected function echoToc($book_contents, $metadata) { $option = get_option('pressbooks_theme_options_global'); echo '<div id="toc"><h1>' . __('Contents', 'pressbooks') . '</h1><ul>'; foreach ($book_contents as $type => $struct) { $s = 1; // Start section counter if (preg_match('/^__/', $type)) { continue; } // Skip __magic keys if ('part' == $type) { foreach ($struct as $part) { $slug = $part['post_name']; $title = Sanitize\strip_br($part['post_title']); $part_content = trim(get_post_meta($part['ID'], 'pb_part_content', true)); if (get_post_meta($part['ID'], 'pb_part_invisible', true) !== 'on') { // visible if (count($book_contents['part']) == 1) { // only part if ($part_content) { // has content printf('<li class="part"><a href="#%s">%s</a></li>', $slug, Sanitize\decode($title)); // show in TOC } else { // no content printf('<li class="part display-none"><a href="#%s">%s</a></li>', $slug, Sanitize\decode($title)); // hide from TOC } } elseif (count($book_contents['part']) > 1) { // multiple parts if ($this->atLeastOneExport($part['chapters'])) { // has chapter printf('<li class="part"><a href="#%s">%s</a></li>', $slug, Sanitize\decode($title)); // show in TOC } else { // no chapter if ($part_content) { // has content printf('<li class="part"><a href="#%s">%s</a></li>', $slug, Sanitize\decode($title)); // show in TOC } else { // no content printf('<li class="part display-none"><a href="#%s">%s</a></li>', $slug, Sanitize\decode($title)); // hide from TOC } } } } elseif (get_post_meta($part['ID'], 'pb_part_invisible', true) == 'on') { // invisible printf('<li class="part display-none"><a href="#%s">%s</a></li>', $slug, Sanitize\decode($title)); // hide from TOC } foreach ($part['chapters'] as $j => $chapter) { if (!$chapter['export']) { continue; } $subclass = \PressBooks\Taxonomy\chapter_type($chapter['ID']); $slug = $chapter['post_name']; $title = Sanitize\strip_br($chapter['post_title']); $subtitle = trim(get_post_meta($chapter['ID'], 'pb_subtitle', true)); $author = trim(get_post_meta($chapter['ID'], 'pb_section_author', true)); $license = $option['copyright_license'] ? get_post_meta($chapter['ID'], 'pb_section_license', true) : ''; printf('<li class="chapter %s"><a href="#%s"><span class="toc-chapter-title">%s</span>', $subclass, $slug, Sanitize\decode($title)); if ($subtitle) { echo ' <span class="chapter-subtitle">' . Sanitize\decode($subtitle) . '</span>'; } if ($author) { echo ' <span class="chapter-author">' . Sanitize\decode($author) . '</span>'; } if ($license) { echo ' <span class="chapter-license">' . $license . '</span> '; } echo '</a>'; if (\PressBooks\Export\Export::shouldParseSections() == true) { $sections = \PressBooks\Book::getSubsections($chapter['ID']); if ($sections) { echo '<ul class="sections">'; foreach ($sections as $section) { echo '<li class="section"><a href="#section-' . $s . '"><span class="toc-subsection-title">' . $section . '</span></a></li>'; ++$s; } echo '</ul>'; } } echo '</li>'; } } } else { foreach ($struct as $val) { if (!$val['export']) { continue; } $typetype = ''; $subtitle = ''; $author = ''; $license = ''; $slug = $val['post_name']; $title = Sanitize\strip_br($val['post_title']); if ('front-matter' == $type) { $subclass = \PressBooks\Taxonomy\front_matter_type($val['ID']); if ('dedication' == $subclass || 'epigraph' == $subclass || 'title-page' == $subclass || 'before-title' == $subclass) { continue; // Skip } else { $typetype = $type . ' ' . $subclass; $subtitle = trim(get_post_meta($val['ID'], 'pb_subtitle', true)); $author = trim(get_post_meta($val['ID'], 'pb_section_author', true)); $license = $option['copyright_license'] ? get_post_meta($val['ID'], 'pb_section_license', true) : ''; } } elseif ('back-matter' == $type) { $typetype = $type . ' ' . \PressBooks\Taxonomy\back_matter_type($val['ID']); $subtitle = trim(get_post_meta($val['ID'], 'pb_subtitle', true)); $author = trim(get_post_meta($val['ID'], 'pb_section_author', true)); $license = $option['copyright_license'] ? get_post_meta($val['ID'], 'pb_section_license', true) : ''; } printf('<li class="%s"><a href="#%s"><span class="toc-chapter-title">%s</span>', $typetype, $slug, Sanitize\decode($title)); if ($subtitle) { echo ' <span class="chapter-subtitle">' . Sanitize\decode($subtitle) . '</span>'; } if ($author) { echo ' <span class="chapter-author">' . Sanitize\decode($author) . '</span>'; } if ($license) { echo ' <span class="chapter-license">' . $license . '</span> '; } echo '</a>'; if (\PressBooks\Export\Export::shouldParseSections() == true) { $sections = \PressBooks\Book::getSubsections($val['ID']); if ($sections) { echo '<ul class="sections">'; foreach ($sections as $section) { echo '<li class="section"><a href="#' . $type . '-section-' . $s . '"><span class="toc-subsection-title">' . $section . '</span></a></li>'; ++$s; } echo '</ul>'; } } echo '</li>'; } } } echo "</ul></div>\n"; }
/** * Use the book locale to load POT translations? * * @return bool */ function use_book_locale() { if (\PressBooks\Export\Export::isFormSubmission() && is_array(@$_POST['export_formats'])) { return true; } $uri = $_SERVER['REQUEST_URI']; if (strpos($uri, '/format/xhtml') !== false) { return true; } return false; }
/** * Is the parse sections option true? * * @return boolean */ function pb_should_parse_sections() { return \PressBooks\Export\Export::shouldParseSections(); }
/** * Add $this->outputPath as additional log info, fallback to parent. * * @param $message * @param array $more_info (unused, overridden) */ function logError($message, array $more_info = array()) { $more_info = array('path' => $this->outputPath); parent::logError($message, $more_info); }
/** * Add $this->url as additional log info, fallback to parent. * * @param $message * @param array $more_info (unused, overridden) */ function logError($message, array $more_info = array()) { $more_info = array('url' => $this->url); parent::logError($message, $more_info); }
<a class="btn black" href="<?php echo get_option('home'); ?>/buy"><span class="buy-icon"></span><?php _e('Buy', 'pressbooks'); ?></a> <?php endif; ?> </div> <!-- end .call-to-action --> </div><!-- end .call-to-action-wrap --> <!-- display links to files --> <?php $files = \PBT\Utility\latest_exports(); $options = get_option( 'pbt_redistribute_settings' ); if ( ! empty( $files ) && ( true == $options['latest_files_public'] ) ) { echo '<div class="alt-formats">' . '<h4>Download in the following formats:</h4>'; $dir = \PressBooks\Export\Export::getExportFolder(); foreach ( $files as $ext => $filename ) { $file_extension = substr( strrchr( $ext, '.' ), 1 ); $pre_suffix = (false == strstr( $ext, '._3.epub' )) ? strstr( $ext, '._vanilla.xml' ) : strstr( $ext, '._3.epub' ); switch ( $file_extension ) { case 'html': $file_class = 'xhtml'; break; case 'xml': $file_class = ( false == $pre_suffix) ? 'wxr' : 'vanillawxr'; break; case 'epub': $file_class = ( false == $pre_suffix ) ? 'epub' : 'epub3'; break; default:
/** * @param array $book_contents * @param array $metadata */ protected function echoBackMatter($book_contents, $metadata) { $back_matter_printf = '<div class="back-matter %s" id="%s">'; $back_matter_printf .= '<div class="back-matter-title-wrap"><h3 class="back-matter-number">%s</h3><h1 class="back-matter-title">%s</h1></div>'; $back_matter_printf .= '<div class="ugc back-matter-ugc">%s</div>%s'; $back_matter_printf .= '</div>'; $i = $s = 1; foreach ($book_contents['back-matter'] as $back_matter) { if (!$back_matter['export']) { continue; } $id = $back_matter['ID']; $subclass = \PressBooks\Taxonomy\back_matter_type($id); $slug = $back_matter['post_name']; $title = get_post_meta($id, 'pb_show_title', true) ? $back_matter['post_title'] : '<span class="display-none">' . $back_matter['post_title'] . '</span>'; // Preserve auto-indexing in Prince using hidden span $content = $back_matter['post_content']; $short_title = trim(get_post_meta($id, 'pb_short_title', true)); $subtitle = trim(get_post_meta($id, 'pb_subtitle', true)); $author = trim(get_post_meta($id, 'pb_section_author', true)); if (\PressBooks\Export\Export::shouldParseSections() == true) { $sections = \PressBooks\Book::getSubsections($id); if ($sections) { $content = \PressBooks\Book::tagSubsections($content, $id); } } if ($author) { $content = '<h2 class="chapter-author">' . Sanitize\decode($author) . '</h2>' . $content; } if ($subtitle) { $content = '<h2 class="chapter-subtitle">' . Sanitize\decode($subtitle) . '</h2>' . $content; } if ($short_title) { $content = '<h6 class="short-title">' . Sanitize\decode($short_title) . '</h6>' . $content; } printf($back_matter_printf, $subclass, $slug, $i, Sanitize\decode($title), $content, $this->doEndnotes($id)); echo "\n"; ++$i; } }