print.module 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. <?php
  2. /**
  3. * @defgroup print Printer, email and PDF versions
  4. *
  5. * Welcome to the print module developer's documentation. The interesting
  6. * functions for themers are those that start with 'theme_'.
  7. *
  8. * - Printer-friendly pages
  9. * - @link print.module Module main file @endlink
  10. * - @link print.admin.inc Settings form @endlink
  11. * - @link print.pages.inc HTML generation @endlink
  12. * - @link print.install (Un)Install routines @endlink
  13. * - @link print.tpl.php Page generation template @endlink
  14. * - Send by email
  15. * - @link print_mail.module Module main file @endlink
  16. * - @link print_mail.admin.inc Settings form @endlink
  17. * - @link print_mail.inc Mail form and send mail routine @endlink
  18. * - @link print_mail.install (Un)Install routines @endlink
  19. * - PDF version
  20. * - @link print_pdf.module Module main file @endlink
  21. * - @link print_pdf.admin.inc Settings form @endlink
  22. * - @link print_pdf.pages.inc PDF generation @endlink
  23. * - @link print_pdf.class.inc Auxiliary PHP5 class @endlink
  24. * - @link print_pdf.class_php4.inc Auxiliary PHP4 class @endlink
  25. * - @link print_pdf.install (Un)Install routines @endlink
  26. */
  27. /**
  28. * @file
  29. * Displays Printer-friendly versions of Drupal pages.
  30. *
  31. * This is the core module of the PF package, with the Drupal hooks
  32. * and other administrative functions.
  33. *
  34. * @ingroup print
  35. */
  36. define('PRINT_PATH', 'print');
  37. define('PRINT_HTML_FORMAT', 'html');
  38. define('PRINT_MAIL_FORMAT', 'mail');
  39. define('PRINT_PDF_FORMAT', 'pdf');
  40. define('PRINT_LOGO_OPTIONS_DEFAULT', 1);
  41. define('PRINT_LOGO_URL_DEFAULT', '');
  42. define('PRINT_FOOTER_OPTIONS_DEFAULT', 1);
  43. define('PRINT_FOOTER_USER_DEFAULT', '');
  44. define('PRINT_CSS_DEFAULT', '');
  45. define('PRINT_KEEP_THEME_CSS_DEFAULT', 0);
  46. define('PRINT_URLS_DEFAULT', 1);
  47. define('PRINT_URLS_ANCHORS_DEFAULT', 0);
  48. define('PRINT_COMMENTS_DEFAULT', 0);
  49. define('PRINT_NEWWINDOW_DEFAULT', 1);
  50. define('PRINT_HTML_LINK_POS_DEFAULT', '{ "link": "link", "block": "block", "help": "help" }');
  51. define('PRINT_HTML_LINK_TEASER_DEFAULT', 0);
  52. define('PRINT_HTML_SHOW_LINK_DEFAULT', 1);
  53. define('PRINT_HTML_NODE_LINK_VISIBILITY_DEFAULT', 0);
  54. define('PRINT_HTML_NODE_LINK_PAGES_DEFAULT', '');
  55. define('PRINT_HTML_LINK_CLASS_DEFAULT', 'print-page');
  56. define('PRINT_HTML_SYS_LINK_VISIBILITY_DEFAULT', 1);
  57. define('PRINT_HTML_SYS_LINK_PAGES_DEFAULT', '');
  58. define('PRINT_HTML_LINK_USE_ALIAS_DEFAULT', 0);
  59. define('PRINT_HTML_BOOK_LINK_DEFAULT', 1);
  60. define('PRINT_HTML_NEW_WINDOW_DEFAULT', 0);
  61. define('PRINT_HTML_SENDTOPRINTER_DEFAULT', 0);
  62. define('PRINT_HTML_WINDOWCLOSE_DEFAULT', 1);
  63. define('PRINT_SOURCEURL_ENABLED_DEFAULT', 1);
  64. define('PRINT_SOURCEURL_DATE_DEFAULT', 0);
  65. define('PRINT_SOURCEURL_FORCENODE_DEFAULT', 0);
  66. define('PRINT_ROBOTS_NOINDEX_DEFAULT', 1);
  67. define('PRINT_ROBOTS_NOFOLLOW_DEFAULT', 1);
  68. define('PRINT_ROBOTS_NOARCHIVE_DEFAULT', 0);
  69. define('PRINT_TYPE_SHOW_LINK_DEFAULT', 1);
  70. define('PRINT_TYPE_COMMENT_LINK_DEFAULT', 0);
  71. define('PRINT_TYPE_URLLIST_DEFAULT', 1);
  72. define('PRINT_TYPE_SYS_URLLIST_DEFAULT', 0);
  73. define('PRINT_ALLOW_NORMAL_LINK', 1);
  74. define('PRINT_ALLOW_BOOK_LINK', 2);
  75. define('PRINT_TYPE_FIELDS_WEIGHT', 30);
  76. /**
  77. * Implements hook_permission().
  78. */
  79. function print_permission() {
  80. return array(
  81. 'administer print' => array(
  82. 'title' => t('Administer the module'),
  83. 'description' => t('Perform maintenance tasks for the print module.'),
  84. ),
  85. 'node-specific print configuration' => array(
  86. 'title' => t('Node-specific configuration'),
  87. 'description' => t('Enable access to the per-node settings.'),
  88. ),
  89. 'access print' => array(
  90. 'title' => t('Access the printer-friendly page'),
  91. 'description' => t('View the printer-friendly pages and the links to them in the original pages.'),
  92. ),
  93. );
  94. }
  95. /**
  96. * Implements hook_theme().
  97. */
  98. function print_theme() {
  99. return array(
  100. 'print_format_link' => array(
  101. 'variables' => array(),
  102. ),
  103. 'print' => array(
  104. 'variables' => array('print' => array(), 'type' => PRINT_HTML_FORMAT, 'node' => NULL),
  105. 'template' => 'print',
  106. ),
  107. );
  108. }
  109. /**
  110. * Implements hook_preprocess_HOOK().
  111. */
  112. function print_preprocess_node(&$variables) {
  113. if (($variables['elements']['#view_mode'] == 'print') && isset($variables['elements']['#print_format'])) {
  114. $type = $variables['elements']['#node']->type;
  115. $format = $variables['elements']['#print_format'];
  116. $nid = $variables['elements']['#node']->nid;
  117. $variables['theme_hook_suggestions'][] = "node__print";
  118. $variables['theme_hook_suggestions'][] = "node__print__{$format}";
  119. $variables['theme_hook_suggestions'][] = "node__print__{$format}__node__{$type}";
  120. $variables['theme_hook_suggestions'][] = "node__print__{$format}__node__{$nid}";
  121. }
  122. }
  123. /**
  124. * Implements hook_preprocess_HOOK().
  125. */
  126. function print_preprocess_print(&$variables) {
  127. static $hooks = NULL;
  128. if (!isset($hooks)) {
  129. drupal_theme_initialize();
  130. $hooks = theme_get_registry();
  131. }
  132. $variables['page']['#show_messages'] = FALSE;
  133. // Stolen from theme() so that ALL preprocess functions are called
  134. $hook = 'page';
  135. $info = $hooks[$hook];
  136. if (isset($info['preprocess functions']) || isset($info['process functions'])) {
  137. foreach (array('preprocess functions', 'process functions') as $phase) {
  138. if (!empty($info[$phase])) {
  139. foreach ($info[$phase] as $processor_function) {
  140. if (function_exists($processor_function)) {
  141. // We don't want a poorly behaved process function changing $hook.
  142. $hook_clone = $hook;
  143. $processor_function($variables, $hook_clone);
  144. }
  145. }
  146. }
  147. }
  148. }
  149. $format = $variables['type'];
  150. $type = (isset($variables['node']->type)) ? $variables['node']->type : '';
  151. $nid = (isset($variables['node']->nid)) ? $variables['node']->nid : '';
  152. $variables['theme_hook_suggestions'] = array();
  153. $variables['theme_hook_suggestions'][] = "print__node__{$type}";
  154. $variables['theme_hook_suggestions'][] = "print__node__{$type}__{$nid}";
  155. $variables['theme_hook_suggestions'][] = "print__{$format}";
  156. $variables['theme_hook_suggestions'][] = "print__{$format}__node__{$type}";
  157. $variables['theme_hook_suggestions'][] = "print__{$format}__node__{$type}__{$nid}";
  158. }
  159. /**
  160. * Implements hook_menu().
  161. */
  162. function print_menu() {
  163. $items = array();
  164. $items[PRINT_PATH] = array(
  165. 'title' => 'Printer-friendly',
  166. 'page callback' => 'print_controller_html',
  167. 'access arguments' => array('access print'),
  168. 'type' => MENU_CALLBACK,
  169. 'file' => 'print.pages.inc',
  170. );
  171. $items[PRINT_PATH . '/' . PRINT_PATH] = array(
  172. 'access callback' => FALSE,
  173. );
  174. $items['admin/config/user-interface/print'] = array(
  175. 'title' => 'Printer, email and PDF versions',
  176. 'description' => 'Adds a printer-friendly version link to content and administrative pages.',
  177. 'page callback' => 'drupal_get_form',
  178. 'page arguments' => array('print_html_settings'),
  179. 'access arguments' => array('administer print'),
  180. 'file' => 'print.admin.inc',
  181. );
  182. $items['admin/config/user-interface/print/html'] = array(
  183. 'title' => 'Web page',
  184. 'weight' => 1,
  185. 'type' => MENU_DEFAULT_LOCAL_TASK,
  186. );
  187. $items['admin/config/user-interface/print/html/options'] = array(
  188. 'title' => 'Options',
  189. 'weight' => 1,
  190. 'type' => MENU_DEFAULT_LOCAL_TASK,
  191. );
  192. $items['admin/config/user-interface/print/html/strings'] = array(
  193. 'title' => 'Text strings',
  194. 'description' => 'Override the user-facing strings used in the printer-friendly version.',
  195. 'page callback' => 'drupal_get_form',
  196. 'page arguments' => array('print_html_strings_settings'),
  197. 'access arguments' => array('administer print'),
  198. 'weight' => 2,
  199. 'type' => MENU_LOCAL_TASK,
  200. 'file' => 'print.admin.inc',
  201. );
  202. $items['admin/config/user-interface/print/common'] = array(
  203. 'title' => 'Settings',
  204. 'description' => 'Settings for the common functionalities for all the print sub-modules.',
  205. 'page callback' => 'drupal_get_form',
  206. 'page arguments' => array('print_main_settings'),
  207. 'access arguments' => array('administer print'),
  208. 'weight' => 10,
  209. 'type' => MENU_LOCAL_TASK,
  210. 'file' => 'print.admin.inc',
  211. );
  212. $items['admin/config/user-interface/print/common/options'] = array(
  213. 'title' => 'Options',
  214. 'weight' => 1,
  215. 'type' => MENU_DEFAULT_LOCAL_TASK,
  216. );
  217. $items['admin/config/user-interface/print/common/strings'] = array(
  218. 'title' => 'Text strings',
  219. 'description' => 'Override the user-facing strings used by the print module.',
  220. 'page callback' => 'drupal_get_form',
  221. 'page arguments' => array('print_main_strings_settings'),
  222. 'access arguments' => array('administer print'),
  223. 'weight' => 2,
  224. 'type' => MENU_LOCAL_TASK,
  225. 'file' => 'print.admin.inc',
  226. );
  227. return $items;
  228. }
  229. /**
  230. * Implements hook_block_info().
  231. */
  232. function print_block_info() {
  233. $block['print-links']['info'] = t('Printer, email and PDF versions');
  234. $block['print-links']['cache'] = DRUPAL_CACHE_PER_PAGE;
  235. $block['print-top']['info'] = t('Most printed');
  236. $block['print-top']['cache'] = DRUPAL_CACHE_GLOBAL;
  237. return $block;
  238. }
  239. /**
  240. * Implements hook_block_view().
  241. */
  242. function print_block_view($delta = '') {
  243. switch ($delta) {
  244. case 'print-links':
  245. $nid = preg_replace('!^node/!', '', $_GET['q']);
  246. if (ctype_digit($nid)) {
  247. $node = node_load($nid);
  248. if (!node_access('view', $node)) {
  249. // If the user doesn't have access to the node, don't show any links
  250. $block['content'] = '';
  251. return;
  252. }
  253. }
  254. else {
  255. $node = NULL;
  256. }
  257. $block['content'] = '';
  258. foreach (array('html' => 'print', 'mail' => 'print_mail', 'pdf' => 'print_pdf') as $format => $module) {
  259. $link_pos = variable_get('print_' . $format . '_link_pos', drupal_json_decode(PRINT_HTML_LINK_POS_DEFAULT));
  260. if (!(empty($link_pos['block']))) {
  261. $func = $module . '_insert_link';
  262. if (function_exists($func)) {
  263. $links = $func(NULL, $node);
  264. if (!empty($links)) {
  265. $block['content'] .= $links;
  266. }
  267. }
  268. }
  269. }
  270. break;
  271. case 'print-top':
  272. $block['subject'] = t('Most printed');
  273. $result = db_query_range("SELECT path FROM {print_page_counter} LEFT JOIN {node} n ON path = CONCAT('node/', n.nid) WHERE status <> 0 OR status IS NULL ORDER BY totalcount DESC", 0, 3)
  274. ->fetchAll();
  275. if (count($result)) {
  276. $block['content'] = '<div class="item-list"><ul>';
  277. foreach ($result as $obj) {
  278. $block['content'] .= '<li>' . l(_print_get_title($obj->path), $obj->path) . '</li>';
  279. }
  280. $block['content'] .= '</ul></div>';
  281. }
  282. break;
  283. }
  284. return $block;
  285. }
  286. /**
  287. * Implements hook_node_view_alter().
  288. */
  289. function print_node_view_alter(&$build) {
  290. if (isset($build['links']['book']['#links']['book_printer'])) {
  291. $print_html_book_link = variable_get('print_html_book_link', PRINT_HTML_BOOK_LINK_DEFAULT);
  292. if ($print_html_book_link) {
  293. $print_html_link_pos = variable_get('print_html_link_pos', drupal_json_decode(PRINT_HTML_LINK_POS_DEFAULT));
  294. if (!empty($print_html_link_pos['link'])) {
  295. $format = theme('print_format_link');
  296. switch ($print_html_book_link) {
  297. case 1:
  298. $path = $build['links']['book']['#links']['book_printer']['href'];
  299. break;
  300. case 2:
  301. $print_html_link_use_alias = variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT);
  302. $path = ($print_html_link_use_alias && ($alias = drupal_lookup_path('alias', 'node/' . $build['#node']->nid))) ? $alias : $build['#node']->nid;
  303. break;
  304. }
  305. $build['links']['book']['#links']['book_printer'] = array(
  306. 'href' => PRINT_PATH . '/' . $path,
  307. 'title' => $format['text'],
  308. 'attributes' => $format['attributes'],
  309. 'html' => $format['html'],
  310. );
  311. }
  312. else {
  313. unset($build['links']['book']['#links']['book_printer']);
  314. }
  315. }
  316. }
  317. }
  318. /**
  319. * Implements hook_help().
  320. */
  321. function print_help($path, $arg) {
  322. switch ($path) {
  323. case 'admin/help#print':
  324. // Return a line-break version of the module README
  325. return _filter_autop(file_get_contents(drupal_get_path('module', 'print') . '/README.txt'));
  326. }
  327. $print_html_link_pos = variable_get('print_html_link_pos', drupal_json_decode(PRINT_HTML_LINK_POS_DEFAULT));
  328. if (($path !== 'node/%') && !(empty($print_html_link_pos['help']))) {
  329. static $output = FALSE;
  330. if ($output === FALSE) {
  331. $output = TRUE;
  332. $link = print_insert_link();
  333. if ($link) {
  334. return "<span class='print-syslink'>$link</span>";
  335. }
  336. }
  337. }
  338. }
  339. /**
  340. * Implements hook_node_view().
  341. */
  342. function print_node_view($node, $view_mode) {
  343. $print_html_link_pos = variable_get('print_html_link_pos', drupal_json_decode(PRINT_HTML_LINK_POS_DEFAULT));
  344. $print_html_link_use_alias = variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT);
  345. foreach (array('node', 'comment') as $type) {
  346. $allowed_type = print_link_allowed(array('type' => $type, 'node' => $node, 'view_mode' => $view_mode));
  347. if (($allowed_type === PRINT_ALLOW_NORMAL_LINK) && !isset($node->book) && !empty($print_html_link_pos['link'])) {
  348. drupal_add_css(drupal_get_path('module', 'print') . '/css/printlinks.css');
  349. $links = array();
  350. $format = theme('print_format_link');
  351. $path = (($print_html_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/' . $node->nid))) ? $alias : $node->nid;
  352. $links['print_html'] = array(
  353. 'href' => PRINT_PATH . '/' . $path,
  354. 'title' => $format['text'],
  355. 'attributes' => $format['attributes'],
  356. 'html' => $format['html'],
  357. 'query' => print_query_string_encode($_GET, array('q')),
  358. );
  359. $link_content = array(
  360. '#theme' => 'links',
  361. '#links' => $links,
  362. '#attributes' => array('class' => array('links', 'inline')),
  363. );
  364. if ($type == 'node') {
  365. $node->content['links']['print_html'] = $link_content;
  366. }
  367. elseif (($type == 'comment') && isset($node->content['comments']['comments'])) {
  368. foreach ($node->content['comments']['comments'] as $cid => $comment) {
  369. if (is_numeric($cid)) {
  370. $link_content['#links']['print_html']['query']['comment'] = $cid;
  371. $node->content['comments']['comments'][$cid]['links']['print_html'] = $link_content;
  372. }
  373. }
  374. }
  375. }
  376. }
  377. if ($view_mode == 'full') {
  378. // Insert content corner links
  379. $node->content['print_links'] = array(
  380. '#prefix' => '<span class="print-link">',
  381. '#markup' => '',
  382. '#suffix' => '</span>',
  383. '#weight' => -101,
  384. );
  385. if (!empty($print_html_link_pos['corner'])) {
  386. $node->content['print_links']['#markup'] .= print_insert_link(NULL, $node);
  387. }
  388. }
  389. }
  390. /**
  391. * Implements hook_node_load().
  392. */
  393. function print_node_load($nodes, $types) {
  394. $ids = array();
  395. foreach ($nodes as $node) {
  396. $ids[] = $node->nid;
  397. }
  398. $result = db_query('SELECT nid, link, comments, url_list FROM {print_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid');
  399. foreach ($nodes as $node) {
  400. $node->print_display = isset($result[$node->nid]) ? intval($result[$node->nid]->link) : variable_get('print_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
  401. $node->print_display_comment = isset($result[$node->nid]) ? intval($result[$node->nid]->comments) : variable_get('print_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
  402. $node->print_display_urllist = isset($result[$node->nid]) ? intval($result[$node->nid]->url_list) : variable_get('print_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT);
  403. }
  404. }
  405. /**
  406. * Implements hook_node_insert().
  407. */
  408. function print_node_insert($node) {
  409. if (user_access('administer print') || user_access('node-specific print configuration')) {
  410. if (!isset($node->print_display)) $node->print_display = variable_get('print_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
  411. if (!isset($node->print_display_comment)) $node->print_display_comment = variable_get('print_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
  412. if (!isset($node->print_display_urllist)) $node->print_display_urllist = variable_get('print_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT);
  413. _print_node_conf_modify($node->nid, $node->print_display, $node->print_display_comment, $node->print_display_urllist);
  414. }
  415. }
  416. /**
  417. * Implements hook_node_update().
  418. */
  419. function print_node_update($node) {
  420. if (user_access('administer print') || user_access('node-specific print configuration')) {
  421. if (!isset($node->print_display)) $node->print_display = variable_get('print_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
  422. if (!isset($node->print_display_comment)) $node->print_display_comment = variable_get('print_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
  423. if (!isset($node->print_display_urllist)) $node->print_display_urllist = variable_get('print_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT);
  424. _print_node_conf_modify($node->nid, $node->print_display, $node->print_display_comment, $node->print_display_urllist);
  425. }
  426. }
  427. /**
  428. * Implements hook_node_delete().
  429. */
  430. function print_node_delete($node) {
  431. db_delete('print_node_conf')
  432. ->condition('nid', $node->nid)
  433. ->execute();
  434. db_delete('print_page_counter')
  435. ->condition('path', 'node/' . $node->nid)
  436. ->execute();
  437. }
  438. /**
  439. * Implements hook_form_alter().
  440. */
  441. function print_form_alter(&$form, &$form_state, $form_id) {
  442. // Add the node-type settings option to activate the printer-friendly version link
  443. if ((user_access('administer print') || user_access('node-specific print configuration')) &&
  444. (($form_id == 'node_type_form') || !empty($form['#node_edit_form']))) {
  445. $form['print'] = array(
  446. '#type' => 'fieldset',
  447. '#title' => t('Printer, email and PDF versions'),
  448. '#collapsible' => TRUE,
  449. '#collapsed' => TRUE,
  450. '#weight' => PRINT_TYPE_FIELDS_WEIGHT,
  451. '#group' => 'additional_settings',
  452. );
  453. $form['print']['label'] = array(
  454. '#type' => 'markup',
  455. '#markup' => '<p><strong>' . t('Printer-friendly version') . '</strong></p>',
  456. );
  457. $form['print']['print_display'] = array(
  458. '#type' => 'checkbox',
  459. '#title' => t('Show link'),
  460. );
  461. $form['print']['print_display_comment'] = array(
  462. '#type' => 'checkbox',
  463. '#title' => t('Show link in individual comments'),
  464. );
  465. $form['print']['print_display_urllist'] = array(
  466. '#type' => 'checkbox',
  467. '#title' => t('Show Printer-friendly URLs list'),
  468. );
  469. if ($form_id == 'node_type_form') {
  470. $form['print']['print_display']['#default_value'] = variable_get('print_display_' . $form['#node_type']->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
  471. $form['print']['print_display_comment']['#default_value'] = variable_get('print_display_comment_' . $form['#node_type']->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
  472. $form['print']['print_display_urllist']['#default_value'] = variable_get('print_display_urllist_' . $form['#node_type']->type, PRINT_TYPE_URLLIST_DEFAULT);
  473. }
  474. else {
  475. $node = $form['#node'];
  476. $form['print']['print_display']['#default_value'] = isset($node->print_display) ? $node->print_display : variable_get('print_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
  477. $form['print']['print_display_comment']['#default_value'] = isset($node->print_display_comment) ? $node->print_display_comment : variable_get('print_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
  478. $form['print']['print_display_urllist']['#default_value'] = isset($node->print_display_urllist) ? $node->print_display_urllist : variable_get('print_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT);
  479. }
  480. }
  481. }
  482. /**
  483. * Implements hook_entity_info_alter().
  484. */
  485. function print_entity_info_alter(&$info) {
  486. // Add the 'Print' view mode for nodes.
  487. $info['node']['view modes'] += array(
  488. 'print' => array(
  489. 'label' => t('Print'),
  490. 'custom settings' => TRUE,
  491. ),
  492. );
  493. }
  494. /**
  495. * Auxiliary function to discover a given page's title
  496. *
  497. * @param $path
  498. * path of the page being identified
  499. * @return
  500. * string with the page's title
  501. */
  502. function _print_get_title($path) {
  503. $path = drupal_get_normal_path($path);
  504. $nid = preg_replace('!^node/!', '', $path);
  505. if (ctype_digit($nid)) {
  506. return db_query("SELECT title FROM {node} WHERE nid = :nid", array(':nid' => $nid))
  507. ->fetchField();
  508. }
  509. else {
  510. // Not a node, try to get title from the menu system
  511. $menu_item = menu_get_item($path);
  512. if (!empty($menu_item['title'])) {
  513. return $menu_item['title'];
  514. }
  515. elseif (drupal_substr($menu_item['page_callback'], 0, 6) == 'views_') {
  516. // It's a view, load the view to have access to the title
  517. $view = views_get_view($menu_item['page_arguments']['0']);
  518. return $view->get_title();
  519. }
  520. else {
  521. return NULL;
  522. }
  523. }
  524. }
  525. /**
  526. * Modify the print_node_conf_table
  527. *
  528. * Update the print_node_conf table to reflect the given attributes.
  529. * If updating to the default values, delete the record.
  530. *
  531. * @param $nid
  532. * value of the nid field (primary key)
  533. * @param $link
  534. * value of the link field (0 or 1)
  535. * @param $comments
  536. * value of the comments field (0 or 1)
  537. * @param $url_list
  538. * value of the url_list field (0 or 1)
  539. */
  540. function _print_node_conf_modify($nid, $link, $comments, $url_list) {
  541. db_merge('print_node_conf')
  542. ->key(array('nid' => $nid))
  543. ->fields(array(
  544. 'link' => $link,
  545. 'comments' => $comments,
  546. 'url_list' => $url_list,
  547. ))
  548. ->execute();
  549. }
  550. /**
  551. * Auxiliary function to fill the Printer-friendly link attributes
  552. *
  553. * @param $title
  554. * text to displayed by the link when hovering over it with the mouse
  555. * @param $class
  556. * class attribute to be used in the link
  557. * @param $new_window
  558. * if TRUE opens the target page in a new window
  559. * @return
  560. * array of formatted attributes
  561. */
  562. function print_fill_attributes($title = '', $class = '', $new_window = FALSE) {
  563. $print_newwindow = variable_get('print_newwindow', PRINT_NEWWINDOW_DEFAULT);
  564. $print_robots_noindex = variable_get('print_robots_noindex', PRINT_ROBOTS_NOINDEX_DEFAULT);
  565. $attributes = array();
  566. $attributes['title'] = $title;
  567. if (!empty($class)) {
  568. $attributes['class'] = array($class);
  569. }
  570. if ($new_window) {
  571. switch ($print_newwindow) {
  572. case 0:
  573. $attributes['target'] = '_blank';
  574. break;
  575. case 1:
  576. $attributes['onclick'] = 'window.open(this.href); return false';
  577. break;
  578. }
  579. }
  580. if (!empty($print_robots_noindex)) {
  581. $attributes['rel'] = 'nofollow';
  582. }
  583. return $attributes;
  584. }
  585. /**
  586. * Auxiliary function to set the link text and html flag
  587. *
  588. * @param $type
  589. * type of link: 0 or 1 for a text-only link, 2 for icon-only and 3 for
  590. * both text and icon
  591. * @param $text
  592. * text to be displayed on the link to the printer-friendly page
  593. * @param $img
  594. * path to the icon file
  595. * @return
  596. * array with the link text and html flag
  597. */
  598. function _print_format_link_aux($type = 0, $text = '', $img = '') {
  599. if ($type >= 2) {
  600. $html = TRUE;
  601. switch ($type) {
  602. case 2:
  603. $text = theme('image', array('path' => $img, 'alt' => $text, 'title' => $text, 'attributes' => array('class' => array('print-icon'))));
  604. break;
  605. case 3:
  606. $text = theme('image', array('path' => $img, 'alt' => $text, 'title' => $text, 'attributes' => array('class' => array('print-icon', 'print-icon-margin')))) . $text;
  607. break;
  608. }
  609. }
  610. else {
  611. $html = FALSE;
  612. }
  613. return array('text' => $text,
  614. 'html' => $html,
  615. );
  616. }
  617. /**
  618. * Format the Printer-friendly link
  619. *
  620. * @return
  621. * array of formatted attributes
  622. * @ingroup themeable
  623. */
  624. function theme_print_format_link() {
  625. $print_html_link_class = variable_get('print_html_link_class', PRINT_HTML_LINK_CLASS_DEFAULT);
  626. $print_html_new_window = variable_get('print_html_new_window', PRINT_HTML_NEW_WINDOW_DEFAULT);
  627. $print_html_show_link = variable_get('print_html_show_link', PRINT_HTML_SHOW_LINK_DEFAULT);
  628. $print_html_link_text = filter_xss(variable_get('print_html_link_text', t('Printer-friendly version')));
  629. $img = drupal_get_path('module', 'print') . '/icons/print_icon.gif';
  630. $title = t('Display a printer-friendly version of this page.');
  631. $class = strip_tags($print_html_link_class);
  632. $new_window = $print_html_new_window;
  633. $format = _print_format_link_aux($print_html_show_link, $print_html_link_text, $img);
  634. return array('text' => $format['text'],
  635. 'html' => $format['html'],
  636. 'attributes' => print_fill_attributes($title, $class, $new_window),
  637. );
  638. }
  639. /**
  640. * Auxiliary function to display a formatted Printer-friendly link
  641. *
  642. * Function made available so that developers may call this function from
  643. * their defined pages/blocks.
  644. *
  645. * @param $path
  646. * path of the original page (optional). If not specified, the current URL
  647. * is used
  648. * @param $node
  649. * an optional node object, to be used in defining the path, if used, the
  650. * path argument is irrelevant
  651. * @return
  652. * string with the HTML link to the printer-friendly page
  653. */
  654. function print_insert_link($path = NULL, $node = NULL) {
  655. if ($node !== NULL) {
  656. $nid = $node->nid;
  657. $path = 'node/' . $nid;
  658. $allowed_type = print_link_allowed(array('node' => $node));
  659. }
  660. else {
  661. if ($path === NULL) {
  662. $nid = preg_replace('!^node/([\d]+)!', '$1', $_GET['q']);
  663. $path = $_GET['q'];
  664. }
  665. else {
  666. $nid = NULL;
  667. }
  668. $allowed_type = print_link_allowed(array('path' => $path));
  669. }
  670. if ($allowed_type) {
  671. if ($nid !== NULL) {
  672. if ($allowed_type === PRINT_ALLOW_BOOK_LINK) {
  673. $path = 'book/export/html/' . $nid;
  674. }
  675. else {
  676. if (variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT) && ($alias = drupal_lookup_path('alias', $path))) {
  677. $path = $alias;
  678. }
  679. else {
  680. $path = $nid;
  681. }
  682. }
  683. $path = PRINT_PATH . '/' . $path;
  684. $query = print_query_string_encode($_GET, array('q'));
  685. }
  686. else {
  687. $query = NULL;
  688. }
  689. drupal_add_css(drupal_get_path('module', 'print') . '/css/printlinks.css');
  690. $format = theme('print_format_link');
  691. return '<span class="print_html">' . l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) . '</span>';
  692. }
  693. else {
  694. return FALSE;
  695. }
  696. }
  697. /**
  698. * Check if the provided page is enabled according to the visibility settings
  699. *
  700. * @param $visibility
  701. * current visibility settings:
  702. * 0 for show on every page except the listed pages
  703. * 1 for show on only the listed pages
  704. * @param $pages
  705. * list of pages
  706. * @return
  707. * TRUE if it is enabled, FALSE otherwise
  708. */
  709. function _print_page_match($visibility, $path, $pages) {
  710. if ($pages) {
  711. if ($visibility == 2) {
  712. if (module_exists('php')) {
  713. return php_eval($pages);
  714. }
  715. else {
  716. return FALSE;
  717. }
  718. }
  719. $alias = drupal_get_path_alias($path);
  720. $page_match = drupal_match_path($path, $pages);
  721. if ($alias != $path) {
  722. $page_match = $page_match || drupal_match_path($alias, $pages);
  723. }
  724. return !($visibility xor $page_match);
  725. }
  726. else {
  727. return !$visibility;
  728. }
  729. }
  730. /**
  731. * Check if the link to the PF version is allowed depending on the settings
  732. *
  733. * @param $args
  734. * array containing the possible parameters:
  735. * teaser, node, type, path
  736. * @return
  737. * FALSE if not allowed
  738. * PRINT_ALLOW_NORMAL_LINK if a normal link is allowed
  739. * PRINT_ALLOW_BOOK_LINK if a link is allowed in a book node
  740. */
  741. function print_link_allowed($args) {
  742. $view_mode = isset($args['view_mode']) ? $args['view_mode'] : '';
  743. if ((($view_mode == 'teaser') && !variable_get('print_html_link_teaser', PRINT_HTML_LINK_TEASER_DEFAULT))
  744. || !in_array($view_mode, array('full', 'teaser', '')) || !user_access('access print')) {
  745. // If the teaser link is disabled or the user is not allowed
  746. return FALSE;
  747. }
  748. if (!empty($args['path'])) {
  749. $nid = preg_replace('!^node/!', '', drupal_get_normal_path($args['path']));
  750. if (ctype_digit($nid)) {
  751. $args['node'] = node_load($nid);
  752. }
  753. }
  754. if (!empty($args['node'])) {
  755. static $node_type = '';
  756. $node = $args['node'];
  757. if (isset($node->type)) {
  758. $node_type = $node->type;
  759. }
  760. // Node
  761. $print_html_node_link_visibility = variable_get('print_html_node_link_visibility', PRINT_HTML_NODE_LINK_VISIBILITY_DEFAULT);
  762. $print_html_node_link_pages = variable_get('print_html_node_link_pages', PRINT_HTML_NODE_LINK_PAGES_DEFAULT);
  763. if (!_print_page_match($print_html_node_link_visibility, "node/" . $node->nid, $print_html_node_link_pages)) {
  764. // Page not in visibility list
  765. return FALSE;
  766. }
  767. elseif (isset($args['type']) && ($args['type'] == 'comment') && isset($node_type)) {
  768. // Link is for a comment, return the configured setting
  769. // Cache this statically to avoid duplicate queries for every comment.
  770. static $res = array();
  771. if (!isset($res[$node->nid])) {
  772. $res[$node->nid] = db_query("SELECT comments FROM {print_node_conf} WHERE nid = :nid", array(':nid' => $node->nid))->fetchField();
  773. }
  774. $print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? $res[$node->nid] : variable_get('print_display_comment_' . $node_type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
  775. if ($print_display_comment) {
  776. return PRINT_ALLOW_NORMAL_LINK;
  777. }
  778. }
  779. else {
  780. // Node link
  781. if (isset($node->print_display) && !$node->print_display) {
  782. // Link for this node is disabled
  783. return FALSE;
  784. }
  785. elseif (isset($node->book)) {
  786. // Node is a book;
  787. $print_html_book_link = variable_get('print_html_book_link', PRINT_HTML_BOOK_LINK_DEFAULT);
  788. switch ($print_html_book_link) {
  789. case 1:
  790. if (user_access('access printer-friendly version')) {
  791. return PRINT_ALLOW_BOOK_LINK;
  792. }
  793. break;
  794. case 2:
  795. return PRINT_ALLOW_NORMAL_LINK;
  796. }
  797. }
  798. else {
  799. return PRINT_ALLOW_NORMAL_LINK;
  800. }
  801. }
  802. }
  803. else {
  804. // 'System' page
  805. $print_html_sys_link_visibility = variable_get('print_html_sys_link_visibility', PRINT_HTML_SYS_LINK_VISIBILITY_DEFAULT);
  806. $print_html_sys_link_pages = variable_get('print_html_sys_link_pages', PRINT_HTML_SYS_LINK_PAGES_DEFAULT);
  807. return _print_page_match($print_html_sys_link_visibility, $_GET['q'], $print_html_sys_link_pages);
  808. }
  809. return FALSE;
  810. }
  811. /**
  812. * Parse an array into a valid urlencoded query string.
  813. *
  814. * Modified from drupal_query_string_encode to prevent re-encoding of
  815. * encoded original. (see #301192)
  816. *
  817. * @param $query
  818. * The array to be processed e.g. $_GET
  819. * @param $exclude
  820. * The array filled with keys to be excluded.
  821. * @return
  822. * urlencoded string which can be appended to/as the URL query string
  823. */
  824. function print_query_string_encode($query, $exclude = array(), $parent = '') {
  825. $params = array();
  826. foreach ($query as $key => $value) {
  827. if (in_array($key, $exclude, TRUE)) {
  828. continue;
  829. }
  830. if (is_array($value)) {
  831. $params[$key] = print_query_string_encode($value, $exclude, $key);
  832. }
  833. else {
  834. $params[$key] = $value;
  835. }
  836. }
  837. return empty($params) ? NULL : $params;
  838. }
  839. /**
  840. * Implements hook_contextual_links_view_alter().
  841. */
  842. function print_contextual_links_view_alter(&$element, $items) {
  843. // Hide all contextual links
  844. if (preg_match('!^print!', $_GET['q'])) {
  845. unset($element['#links']);
  846. }
  847. }
  848. /**
  849. * Callback function for the preg_replace_callback replacing spaces with %20
  850. *
  851. * Replace spaces in URLs with %20
  852. *
  853. * @param array $matches
  854. * array with the matched tag patterns, usually <a...>+text+</a>
  855. *
  856. * @return string
  857. * tag with re-written URL
  858. */
  859. function _print_replace_spaces($matches) {
  860. // first, split the html into the different tag attributes
  861. $pattern = '!\s*(\w+\s*=\s*"(?:\\\"|[^"])*")\s*|\s*(\w+\s*=\s*\'(?:\\\\\'|[^\'])*\')\s*|\s*(\w+\s*=\s*\w+)\s*|\s+!';
  862. $attribs = preg_split($pattern, $matches[1], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  863. foreach ($attribs as $key => $value) {
  864. $attribs[$key] = preg_replace('!(\w)\s*=\s*(.*)!', '$1=$2', $value);
  865. }
  866. $size = count($attribs);
  867. for ($i=1; $i < $size; $i++) {
  868. // If the attribute is href or src, we may need to rewrite the URL in the value
  869. if (preg_match('!^(?:href|src)\s*?=(.*)!i', $attribs[$i], $urls) > 0) {
  870. $url = trim($urls[1], " \t\n\r\0\x0B\"'");
  871. $new_url = str_replace(' ', '%20', $url);
  872. $matches[1] = str_replace($url, $new_url, $matches[1]);
  873. }
  874. }
  875. $ret = '<' . $matches[1] . '>';
  876. if (count($matches) == 4) {
  877. $ret .= $matches[2] . $matches[3];
  878. }
  879. return $ret;
  880. }
  881. /**
  882. * Implements hook_views_api().
  883. */
  884. function print_views_api() {
  885. return array(
  886. 'api' => 2.0,
  887. 'path' => drupal_get_path('module', 'print'),
  888. );
  889. }