0) { $robots_meta = implode(', ', $robots_meta); $robots_meta = "\n"; } else { $robots_meta = ''; } return $robots_meta; } /** * Post-processor that fills the array for the template with common details * * @param $node * generated node with a printer-friendly node body * @param $cid * id of current comment being generated (NULL when not generating * an individual comment) * @return * array with the fields to be used in the template */ function _print_var_generator($node, $cid = NULL) { global $base_url; $path = empty($node->nid) ? $node->path : "node/$node->nid"; $themed = theme('print_text'); // print module settings $print_settings = variable_get('print_settings', print_settings_default()); $print_sourceurl_settings = variable_get('print_sourceurl_settings', print_sourceurl_settings_default()); $print["language"] = $GLOBALS['locale']; $print["title"] = $node->title; $print["head"] = drupal_get_html_head(); $print["scripts"] = drupal_get_js(); $print["robots_meta"] = _print_robots_meta_generator(); $print["url"] = url($path, NULL, NULL, TRUE); $print["base_href"] = "\n"; $print["favicon"] = theme_get_setting("toggle_favicon") ? "\n" : ""; $css_files = array(); if (!empty($print_settings['css'])) { $css_files[] = strip_tags($print_settings['css']); } else { $css_files[] = base_path() . drupal_get_path('module', 'print') ."/print.css"; } // Add CCK's CSS file to properly display the fields if (module_exists('content')) { $css_files[] = base_path() . drupal_get_path('module', 'content') ."/content.css"; } $print["css"] = ""; foreach ($css_files as $value) { $print["css"] .= "\n"; } $print["sendtoprinter"] = $print_settings['sendtoprinter'] ? " onload=\"window.print();\"" : ""; $logo_url = !empty($print_settings['logo_url']) ? strip_tags($print_settings['logo_url']) : theme_get_setting('logo'); $print["logo"] = $logo_url ? "\"\"\n" : ""; $published_site = variable_get('site_name', 0); if ($published_site) { $published = (empty($themed["published"])) ? t('Published on %site_name', array('%site_name' => $published_site)) : ($themed['published'] ." ". $published_site); $print["site_name"] = $published ." (". l($base_url, $base_url) .")"; } else { $print["site_name"] = ""; } if ($print_sourceurl_settings['enabled'] == 1) { /* Grab and format the src URL */ if (empty($print_sourceurl_settings['forcenode'])) { $url = $print["url"]; } else { $url = $base_url .'/'. (((bool)variable_get('clean_url', '0')) ? '' : '?q=') . $path; } if ($cid) { $url .= "#comment-$cid"; } $retrieved_date = format_date(time(), 'small'); $retrieved = (empty($themed["retrieved"])) ? t('retrieved on %date', array('%date' => $retrieved_date)) : ($themed["retrieved"] ." ". $retrieved_date); $print["printdate"] = $print_sourceurl_settings['date'] ? " ($retrieved)" : ""; $source_url = (empty($themed["sourceURL"])) ? t('Source URL') : $themed["sourceURL"]; $print["source_url"] = "". $source_url . $print["printdate"] .": ". l($url, $url); } else { $print["source_url"] = ""; } if (isset($node->type)) { $node_type = $node->type; if (theme_get_setting("toggle_node_info_$node_type")) { $by_author = ($node->name ? $node->name : variable_get('anonymous', t('Anonymous'))); $by = (empty($themed["by"])) ? t('By %author', array('%author' => $by_author)) : ($themed["by"] ." ". $by_author); $print["submitted"] = $by; $created_datetime = format_date($node->created, 'small'); $created = (empty($themed["created"])) ? t('Created %date', array('%date' => $created_datetime)) : ($themed["created"] ." ". $created_datetime); $print["created"] = $created; } else { $print["submitted"] = ""; $print["created"] = ""; } $print["type"] = $node->type; } else { $print["submitted"] = ""; $print["created"] = ""; $print["type"] = ''; } menu_set_active_item($path); $breadcrumb = drupal_get_breadcrumb(); if (!empty($breadcrumb)) { $breadcrumb[] = menu_get_active_title(); $print["breadcrumb"] = implode(" > ", $breadcrumb); } else { $print["breadcrumb"] = ""; } // Display the collected links at the bottom of the page. Code once taken from Kjartan Mannes' project.module if (!empty($print_settings['urls'])) { $urls = _print_friendly_urls(); $max = count($urls); $pfp_links = ''; if ($max) { for ($i = 0; $i < $max; $i++) { $pfp_links .= '['. ($i + 1) .'] '. $urls[$i] ."
\n"; } $links = (empty($themed["links"])) ? t('Links') : $themed["links"]; $print["pfp_links"] = "

". $links .":
". $pfp_links ."

"; } } if (module_exists('taxonomy')) { $terms = taxonomy_link('taxonomy terms', $node); $print["taxonomy"] = theme('links', $terms); } $print["content"] = $node->body; $print["node"] = $node; $print["footer_message"] = filter_xss_admin(variable_get('site_footer', FALSE)) ."\n". theme('blocks', 'footer') ; return $print; } /** * Callback function for the preg_replace_callback for URL-capable patterns * * Manipulate URLs to make them absolute in the URLs list, and to add a * [n] footnote marker. * * @param $matches * array with the matched tag patterns, usually +text+ * @return * tag with re-written URL and when appropriate the [n] index to the * URL list */ function _print_rewrite_urls($matches) { global $base_url, $base_root; // Get value of Printer-friendly URLs setting $print_settings = variable_get('print_settings', print_settings_default()); $pfurls = (!empty($print_settings['urls'])); //Temporarily convert spaces to %20 so that it isn't split below $in_string = FALSE; for ($i=0; $i < strlen($matches[1]); $i++) { if ($matches[1][$i] == '"') { $in_string = !$in_string; } if (($matches[1][$i] == ' ') && ($in_string)) { $matches[1]=substr_replace($matches[1], "%20", $i, 1); } } // remove whitespace immediately before and after the '=' sign $matches[1]=preg_replace("/\s*=\s*/", "=", $matches[1]); // first, split the html into the different tag attributes $attribs = preg_split("/\s+/m", $matches[1]); for ($i=1; $i < count($attribs); $i++) { // If the attribute is href or src, we may need to rewrite the URL in the value if (preg_match("/^(href|src)\s*?=/i", $attribs[$i]) > 0) { // We may need to rewrite the URL, so let's isolate it preg_match("/.*?=(.*)/is", $attribs[$i], $urls); $url = trim($urls[1], " \t\n\r\0\x0B\"\'"); if (strpos($url, '://') || preg_match("/^mailto:.*?@.*?\..*?$/iu", $url)) { // URL is absolute, do nothing $newurl = urldecode($url); } else { if (substr($url, 0, 1) == "#") { // URL is an anchor tag if ($pfurls) { $path = substr($_GET['q'], strpos($_GET['q'], '/')+1); if (is_numeric($path)) { $path = "node/$path"; } // Printer-friendly URLs is on, so we need to make it absolute $newurl = url($path, NULL, substr(urldecode($url), 1), TRUE); } // Because base href is the original page, change the link to // still be usable inside the print page $matches[1] = str_replace($url, $_GET['q'] . $url, $matches[1]); } else { // URL is relative, convert it into absolute URL $clean_url = (bool)variable_get('clean_url', '0'); if (substr($url, 0, 1) == "/") { // If it starts with '/' just append it to the server name $newurl = $base_root .'/'. trim(urldecode($url), "/"); } elseif ((!$clean_url) && (preg_match("/^[index.php]?\?q=.*/i", $url))) { // If Clean URLs is disabled, and it starts with q=?, just prepend with the base URL $newurl = $base_url .'/'. trim(urldecode($url), "/"); } else { $newurl = url(trim(urldecode($url), "/"), NULL, NULL, TRUE); } $matches[1] = str_replace($url, $newurl, $matches[1]); } } } } //Revert all %20 in strings back to spaces $matches[1] = str_replace("%20", " ", $matches[1]); $ret = '<'. $matches[1] .'>'; if (count($matches) == 4) { $ret .= $matches[2] . $matches[3]; if (($pfurls) && (isset($newurl))) { $ret .= ' ['. _print_friendly_urls(trim(stripslashes($newurl))) .']'; } } return $ret; } /** * Auxiliary function to store the Printer-friendly URLs list as static. * * @param $url * absolute URL to be inserted in the list * @return * list of URLs previously stored if $url is 0, or the current count * otherwise. */ function _print_friendly_urls($url = 0) { static $urls = array(); if ($url) { $url_idx = array_search($url, $urls); if ($url_idx !== FALSE) { return ($url_idx + 1); } else { $urls[] = $url; return count($urls); } } return $urls; } /** * Choose most appropriate template * * Auxiliary function to resolve the most appropriate template trying to find * a content specific template in the theme or module dir before falling back * on a generic template also in those dirs. * * @param $type * name of the node type being rendered in a PF page * @return * filename of the most suitable template */ function _print_get_template($type = NULL) { $filenames = array(); // If the node type is known, then try to find that type's template file if (!empty($type)) { $filenames[] = "print.node-$type.tpl.php"; $filenames[] = "print.$type.tpl.php"; } // Finally search for a generic template file $filenames[] = "print.tpl.php"; foreach ($filenames as $value) { // First in the theme directory $file = drupal_get_path('theme', $GLOBALS['theme_key']) ."/". $value; if (file_exists($file)) { return $file; } // Then in the module directory $file = drupal_get_path('module', 'print') ."/". $value; if (file_exists($file)) { return $file; } } } /** * Prepare a Printer-friendly-ready node body for content nodes * * @param $nid * node ID of the node to be rendered into a printer-friendly page * @param $cid * comment ID of the individual comment to be rendered * @return * filled array ready to be used in the template */ function _print_generate_node($nid, $cid = NULL) { // We can take a node id $node = node_load(array('nid' => $nid)); if (!node_access('view', $node)) { // Access is denied return drupal_access_denied(); } drupal_set_title($node->title); //alert other modules that we are generating a printer-friendly page, so they can choose to show/hide info $node->printing = TRUE; // Turn off Pagination by the Paging module unset($node->pages); unset($node->pages_count); unset($node->page_count); unset($node->teaser); $node = (object)$node; if ($cid === NULL) { // Adapted (simplified) version of node_view for Drupal 5.x //Render the node content $node = node_build_content($node, FALSE, TRUE); // Disable fivestar widget output unset($node->content["fivestar_widget"]); // Disable service links module output unset($node->content["service_links"]); $node->body = drupal_render($node->content); } $print_settings = variable_get('print_settings', print_settings_default()); if (function_exists('comment_render') && (($cid != NULL) || ($print_settings['comments']))) { //Print only the requested comment (or if $cid is NULL, all of them) $comments = comment_render($node, $cid); //Remove the comment forms $comments = preg_replace("/.*?<\/form>/sim", "", $comments); //Remove the 'Post new comment' title $comments = preg_replace("/Post new comment<\/h2>/", "", $comments); //Remove the comment title hyperlink $comments = preg_replace("/()()(.*?)<\/a>(<\/h3>)/", "$1$3$4", $comments); //Remove the comment author link $pattern = "/()(.*?)(.*?)<\/a>(<\/span>)/sim"; if (preg_match($pattern, $comments)) { $comments = preg_replace($pattern , "$1$2$3$4", $comments); } //Remove the comment links $comments = preg_replace("/\s*
    .*?<\/ul>/sim", "", $comments); if ($cid != NULL) { // Single comment requested, output only the comment unset($node->body); } $node->body .= $comments; } node_invoke_nodeapi($node, 'alter', FALSE, TRUE); // Convert the a href elements $pattern = "@<(a\s[^>]*?)>(.*?)()@is"; $node->body = preg_replace_callback($pattern, "_print_rewrite_urls", $node->body); init_theme(); $print = _print_var_generator($node, $cid); return $print; } /** * Prepare a Printer-friendly-ready node body for non-content pages * * @param $path * path of the node to be rendered into a printer-friendly page * @return * filled array ready to be used in the template */ function _print_generate_path($path) { $path = drupal_get_normal_path($path); $_GET['q'] = $path; _menu_append_contextual_items(); menu_set_active_item($path); // Adapted from index.php. $node = new stdClass(); $node->body = menu_execute_active_handler(); $node->title = drupal_get_title(); $node->path = $path; // It may happen that a drupal_not_found is called in the above call if (preg_match('/404 Not Found/', drupal_get_headers()) == 1) { return; } switch ($node->body) { case MENU_NOT_FOUND: return drupal_not_found(); break; case MENU_ACCESS_DENIED: return drupal_access_denied(); break; } // Delete any links area $node->body = preg_replace("/\s*
    .*?<\/div>/sim", "", $node->body); // Convert the a href elements $pattern = "@<(a\s[^>]*?)>(.*?)()@is"; $node->body = preg_replace_callback($pattern, "_print_rewrite_urls", $node->body); init_theme(); $print = _print_var_generator($node); return $print; } /** * Prepare a Printer-friendly-ready node body for book pages * * @param $nid * node ID of the node to be rendered into a printer-friendly page * @return * filled array ready to be used in the template */ function _print_generate_book($nid) { $node = node_load(array('nid' => $nid)); if (!node_access('view', $node) || (!user_access('see printer-friendly version'))) { // Access is denied return drupal_access_denied(); } $depth = count(book_location($node)) + 1; $node->body = book_recurse($nid, $depth, '_print_node_visitor_html_pre', 'book_node_visitor_html_post'); // Convert the a href elements $pattern = "@<(a\s[^>]*?)>(.*?)()@is"; $node->body = preg_replace_callback($pattern, "_print_rewrite_urls", $node->body); init_theme(); $print = _print_var_generator($node); // The title is already displayed by the book_recurse, so avoid duplication $print["title"] = ""; return $print; } /** * Generates printer-friendly HTML for a node. This function is a 'pre-node' visitor function for book_recurse() * * My own version of book_node_visitor_html_pre so that CCK pages in book nodes * come out right * * @param $node * the node to generate output for. * @param $depth * the depth of the given node in the hierarchy. This is used only for * generating output. * @param $nid * the node id (nid) of the given node. This is used only for generating * output. * @return * the HTML generated for the given node. */ function _print_node_visitor_html_pre($node, $depth, $nid) { $node = node_build_content($node, FALSE, TRUE); unset($node->content["book_navigation"]); $output .= "
    nid ."\" class=\"section-$depth\">\n"; $output .= "

    ". check_plain($node->title) ."

    \n"; $output .= drupal_render($node->content); return $output; }