Read Offline Hooks Reference
Comprehensive list of filters and actions exposed by the Read Offline plugin (version 0.2.4).
Each entry shows: Purpose • Arguments • Expected return (for filters) • Example usage.
Table of Contents
Section titled “Table of Contents”- Filters
- Actions
- Cloudflare Browser Rendering Filters & Actions
- Validation Filter
- Download Integrity Headers
- Helper Methods (Public)
- Notes
Filters
Section titled “Filters”1. Content & Format
Section titled “1. Content & Format”read_offline_enabled_formats
Section titled “read_offline_enabled_formats”Modify which export format slugs are exposed in the frontend UI (after user settings).
Args: (array $formats)
Return: array filtered list (subset of ['pdf','epub','md'])
add_filter( 'read_offline_enabled_formats', function( $formats ) { // Hide EPUB site‑wide, for example. return array_diff( $formats, [ 'epub' ] );} );read_offline_content_html
Section titled “read_offline_content_html”Last chance to adjust the post HTML before conversion per format.
Args: (string $html, WP_Post $post, string $format) Return: string
add_filter( 'read_offline_content_html', function( $html, $post, $format ) { if ( 'pdf' === $format ) { $html .= '<p><em>Downloaded on ' . esc_html( date( 'c' ) ) . '</em></p>'; } return $html;}, 10, 3 );2. Markdown
Section titled “2. Markdown”read_offline_markdown_pre
Section titled “read_offline_markdown_pre”Provide fully generated Markdown yourself (short‑circuit). Return non-null to skip internal conversion.
Args: (null|string $override, string $title, string $originalHtml, array $args) Return: string|null
read_offline_markdown_post
Section titled “read_offline_markdown_post”Tweak final Markdown after internal conversion.
Args: (string $markdown, string $title, string $originalHtml, array $args) Return: string
add_filter( 'read_offline_markdown_post', function( $md ) { return $md . "\n\n---\nGenerated by MySite";} );3. EPUB
Section titled “3. EPUB”read_offline_epub_css
Section titled “read_offline_epub_css”Alter the computed EPUB CSS (profile + custom CSS amalgam).
Args: (string $css, WP_Post|null $post, array $epub_opts) Return: string
read_offline_epub_toc_html
Section titled “read_offline_epub_toc_html”Modify the inline EPUB TOC <ul>…</ul> before insertion.
Args: (string $tocHtml, WP_Post|null $post, int $depth) Return: string
add_filter( 'read_offline_epub_toc_html', fn( $toc ) => '<nav class="toc">' . $toc . '</nav>' );read_offline_epub_cover
Section titled “read_offline_epub_cover”Supply a custom cover before plugin resolves featured/logo/custom.
Args: (null|array $current, WP_Post|null $post, array $epub_opts)
Return: null|array [$filename, $binaryBytes, $mime]
add_filter( 'read_offline_epub_cover', function( $cover, $post ) { if ( $cover || ! $post ) return $cover; $custom_path = WP_CONTENT_DIR . '/uploads/branding/epub-cover.jpg'; if ( file_exists( $custom_path ) ) { return [ 'brand-cover.jpg', file_get_contents( $custom_path ), 'image/jpeg' ]; } return $cover;}, 10, 2 );4. PDF
Section titled “4. PDF”read_offline_pdf_css
Section titled “read_offline_pdf_css”Append or override PDF CSS (returned string concatenated after base rules + custom setting).
Args: (string $appendCss, WP_Post|null $post) Return: string
add_filter( 'read_offline_pdf_css', function( $extra ) { return $extra . ' h2{color:#336699;} '; // simple tint} );5. TOC
Section titled “5. TOC”read_offline_pdf_toc_html
Section titled “read_offline_pdf_toc_html”Modify manual PDF TOC <ul> (used ONLY when page numbers are disabled; with page numbers mPDF builds its own TOC from bookmarks).
Args: (string $tocHtml, WP_Post|null $post, int $depth) Return: string
read_offline_toc_title
Section titled “read_offline_toc_title”Change the heading text (default “Contents”) for both PDF & EPUB TOCs.
Args: (string $defaultTitle, string $format) Return: string
add_filter( 'read_offline_toc_title', function( $title, $format ) { return ( 'pdf' === $format ) ? __( 'Document Overview', 'mytheme' ) : $title;}, 10, 2 );6. Covers / Assets
Section titled “6. Covers / Assets”See read_offline_epub_cover above.
7. Bulk / UI
Section titled “7. Bulk / UI”read_offline_bulk_combine
Section titled “read_offline_bulk_combine”Control whether a bulk export should combine into one file.
Args: (bool $combine, array $post_ids, string $format, string $post_type) Return: bool
add_filter( 'read_offline_bulk_combine', function( $combine, $post_ids, $format ) { if ( 'pdf' === $format && count( $post_ids ) > 25 ) { // Force ZIP for very large selections. return false; } return $combine;}, 10, 3 );read_offline_bulk_zip_name
Section titled “read_offline_bulk_zip_name”Modify the ZIP filename (string) prior to creating a bulk archive (when not combining).
Args: (string $zip_name, array $generated, string $format, string $post_type) Return: string
add_filter( 'read_offline_bulk_zip_name', function( $name, $generated, $format ) { return 'my-site-' . $format . '-' . date( 'Ymd-His' ) . '.zip';}, 10, 3 );8. Internal Paths
Section titled “8. Internal Paths”read_offline_db_path
Section titled “read_offline_db_path”Adjust the temporary auxiliary DB/storage directory path if used.
Args: (string $defaultPath) Return: string
add_filter( 'read_offline_db_path', fn( $p ) => WP_CONTENT_DIR . '/cache/read-offline-db/' );Actions
Section titled “Actions”read_offline_db_deleted
Section titled “read_offline_db_deleted”Fires after an internal auxiliary DB directory is removed.
Args: (string $path, bool $success)
add_action( 'read_offline_db_deleted', function( $path, $ok ) { error_log( 'Read Offline cache dir deleted: ' . $path . ' (success=' . ( $ok ? '1' : '0' ) . ')' );} );read_offline_epub_generated
Section titled “read_offline_epub_generated”Runs immediately after a single EPUB has been written (before optional validation filter outcome is enforced). Use to trigger async validation processes or logging.
Args: (string $path, WP_Post $post, array $epub_opts)
add_action( 'read_offline_epub_generated', function( $path, $post ) { error_log( 'EPUB created: ' . $path );}, 10, 2 );Cloudflare Browser Rendering Filters & Actions
Section titled “Cloudflare Browser Rendering Filters & Actions”read_offline_use_cloudflare
Section titled “read_offline_use_cloudflare”Filter whether to use Cloudflare Browser Rendering for single PDF generation. Defaults to true if Cloudflare credentials are configured.
Args: (bool $use_cloudflare, WP_Post $post, array $pdf_opts, array $gen_opts) Return: bool
add_filter( 'read_offline_use_cloudflare', function( $use, $post, $pdf_opts, $gen_opts ) { // Always use mPDF for specific post types. if ( 'product' === $post->post_type ) { return false; } return $use;}, 10, 4 );read_offline_use_cloudflare_combined
Section titled “read_offline_use_cloudflare_combined”Filter whether to use Cloudflare Browser Rendering for combined PDF generation. Defaults to true if Cloudflare credentials are configured.
Args: (bool $use_cloudflare, array $post_ids, array $pdf_opts, array $gen_opts) Return: bool
add_filter( 'read_offline_use_cloudflare_combined', function( $use, $post_ids, $pdf_opts, $gen_opts ) { // Use Cloudflare only for large exports (10+ posts). return count( $post_ids ) >= 10;}, 10, 4 );read_offline_cloudflare_fallback
Section titled “read_offline_cloudflare_fallback”Triggered when Cloudflare PDF generation fails. Return true to fallback to mPDF, false to propagate error.
Args: (bool $fallback, WP_Error $error, WP_Post|null $post) Return: bool
add_filter( 'read_offline_cloudflare_fallback', function( $fallback, $error, $post ) { // Never fallback for premium content. if ( $post && has_term( 'premium', 'category', $post ) ) { return false; // Force Cloudflare, propagate error if it fails. } return $fallback; // Default behavior.}, 10, 3 );read_offline_cloudflare_pdf_options
Section titled “read_offline_cloudflare_pdf_options”Filter Cloudflare PDF options before building Puppeteer script. Allows customization of format, margins, headers, footers, etc.
Args: (array $options, WP_Post|null $post) Return: array
add_filter( 'read_offline_cloudflare_pdf_options', function( $options, $post ) { // Force landscape for specific posts. if ( $post && has_tag( 'wide-content', $post ) ) { $options['landscape'] = true; } return $options;}, 10, 2 );read_offline_cloudflare_puppeteer_script
Section titled “read_offline_cloudflare_puppeteer_script”Filter the raw Puppeteer JavaScript sent to Cloudflare Browser Rendering API.
Args: (string $script, array $options, WP_Post|null $post) Return: string
add_filter( 'read_offline_cloudflare_puppeteer_script', function( $script, $options, $post ) { // Add custom JavaScript before PDF generation. $custom = "await page.evaluate(() => { console.log('Generating PDF...'); });"; return str_replace( 'await page.pdf(', $custom . "\n await page.pdf(", $script );}, 10, 3 );read_offline_cloudflare_html
Section titled “read_offline_cloudflare_html”Filter the complete HTML document before sending to Cloudflare for PDF rendering.
Args: (string $full_html, WP_Post|null $post, array $pdf_opts, array $gen_opts) Return: string
add_filter( 'read_offline_cloudflare_html', function( $html, $post, $pdf_opts, $gen_opts ) { // Inject custom analytics or tracking scripts. $tracking = '<script>console.log("PDF generated via Cloudflare");</script>'; return str_replace( '</body>', $tracking . '</body>', $html );}, 10, 4 );read_offline_cloudflare_combined_html
Section titled “read_offline_cloudflare_combined_html”Filter the combined HTML document for multi-post PDFs before sending to Cloudflare.
Args: (string $full_html, array $post_ids, array $pdf_opts, array $gen_opts) Return: string
add_filter( 'read_offline_cloudflare_combined_html', function( $html, $post_ids, $pdf_opts, $gen_opts ) { // Add cover page for combined exports. $cover = '<div style="page-break-after:always;"><h1>Combined Export</h1><p>' . count( $post_ids ) . ' posts</p></div>'; return str_replace( '<div class="combined-content">', $cover . '<div class="combined-content">', $html );}, 10, 4 );read_offline_cloudflare_timeout
Section titled “read_offline_cloudflare_timeout”Filter the HTTP timeout for Cloudflare API requests (default: 60 seconds).
Args: (int $timeout) Return: int
add_filter( 'read_offline_cloudflare_timeout', function( $timeout ) { // Increase timeout for large documents. return 120; // 2 minutes} );read_offline_cloudflare_pdf_generated
Section titled “read_offline_cloudflare_pdf_generated”Action fired after successful Cloudflare PDF generation.
Args: (string $path, WP_Post|null $post, array $response)
add_action( 'read_offline_cloudflare_pdf_generated', function( $path, $post, $response ) { // Log successful generation. error_log( sprintf( 'Cloudflare PDF generated: %s (Post ID: %d)', basename( $path ), $post ? $post->ID : 0 ) );}, 10, 3 );read_offline_cloudflare_pdf_failed
Section titled “read_offline_cloudflare_pdf_failed”Action fired when Cloudflare PDF generation fails.
Args: (WP_Error $error, WP_Post|null $post, string $html)
add_action( 'read_offline_cloudflare_pdf_failed', function( $error, $post, $html ) { // Alert admins of Cloudflare failures. $admin_email = get_option( 'admin_email' ); wp_mail( $admin_email, 'Cloudflare PDF Generation Failed', sprintf( 'Error: %s\nPost ID: %d', $error->get_error_message(), $post ? $post->ID : 0 ) );}, 10, 3 );Validation Filter
Section titled “Validation Filter”read_offline_epub_validate
Section titled “read_offline_epub_validate”Allows you to validate or veto a generated EPUB file. Return WP_Error to signal a failure (the file stays on disk; caller will receive the error).
Args: (mixed $ok, string $path, WP_Post $post, array $epub_opts) Return: bool|WP_Error (true to accept, WP_Error to reject)
Example integrating epubcheck (Java) if installed server-side:
add_filter( 'read_offline_epub_validate', function( $ok, $path ) { if ( is_wp_error( $ok ) ) { return $ok; } $jar = '/usr/local/bin/epubcheck.jar'; if ( ! file_exists( $jar ) ) { return $ok; } $cmd = escapeshellcmd( 'java -jar ' . $jar . ' ' . escapeshellarg( $path ) . ' 2>&1' ); @exec( $cmd, $out, $code ); if ( $code !== 0 ) { return new WP_Error( 'epub_invalid', 'EPUB failed validation', array( 'output' => $out ) ); } return $ok; // pass through}, 10, 2 );Download Integrity Headers
Section titled “Download Integrity Headers”For ZIP and combined downloads the plugin now sends: Content-Length, X-Checksum-MD5, X-Checksum-SHA256 allowing clients to verify integrity.
Helper Methods (Public)
Section titled “Helper Methods (Public)”Read_Offline_Export::invalidate_post_cache( $post_id, $format = null )– Remove cached exports so they regenerate.Read_Offline_Export::debug_smoke_capabilities()– Returns array of environment availability (mPDF / PHPePub).
- Standard WordPress hooks like
the_contentstill apply before plugin filters. - When PDF page numbers are enabled, mPDF’s own TOC replaces the manual TOC filter (
read_offline_pdf_toc_htmlnot invoked in that case).
Suggestions or missing hook docs? Open an issue / submit a PR.
📦 Source: soderlind/read-offline · Edit on GitHub