New module 'Printer-friendly pages'

This commit is contained in:
Manuel Cillero 2017-07-26 19:32:04 +02:00
parent ae482480b2
commit b70f11745a
38 changed files with 8667 additions and 0 deletions

View file

@ -0,0 +1,911 @@
August 22, 2010
Update CHANGELOG
Updated Polish translation by dargod
Update translations
Coder fixes
August 20, 2010
Use theme_token_help to generate token list
August 18, 2010
Fix #884936: Check if the select PDF tool is accessible and executable (wkhtmltopdf)
Fix #886766: Make unreadable custom CSS file a warning and not an error when submitting the settings form
Fix #885420: restore the call to init_theme()
Remove some PHP warnings in non-content pages
Fix #883952: Put base href at the top of the print template
Don't create configuration records if the content type settings are still the default value
August 15, 2010
Fix #883086: blank CSS file field caused form validation failure in settings
August 14, 2010
Fix #881650: hide insert warnings during node updates
Fix #881074 by ceme: use SCRIPT_FILENAME instead of DOCUMENT_ROOT when replacing image paths for local access
Fix #881870 by Shiny: recent update routines were not PostgreSQL compatible
August 13, 2010
Updated Hungarian translation.
August 12, 2010
Fix #880954: Enable translation of 'send page as' options
Fix #880400: document alternative sites/all/libraries path in INSTALL.txt
August 11, 2010
SA-CONTRIB-2010-TBD: disable local file access with wkhtmltopdf
Update CHANGELOG
August 9, 2010
Convert to local file access only for TCPDF and dompdf
August 4, 2010
Templates are also searched in the core directories
August 1, 2010
Coder fixes
July 31, 2010
Update functions to modify the node_conf tables and the custom CSS path
July 30, 2010
rename vars to variables in MODULE_preprocess_HOOK functions
July 25, 2010
Fix #726082: Remove dependency on allow_url_fopen by converting all image URLs to local files
July 24, 2010
Add option to set default mail sending format
Fix #850844: Use drupal_add_css for the custom CSS
July 22, 2010
Another fix for #358838: print.tpl.php in theme path wasn't working properly
Fix #763810: Configure module weights to ensure that the core module is always called before the others
July 20, 2010
Provide missing info on the arguments of print_pdf theme functions
Use type-default settings if a node is being created/updated leaving them unspecified
Use type-default settings if a node is being created/updated leaving them unspecified
July 16, 2010
Fix #803580: Add alt text to printer-friendly page logo
Fix #771300: warn the site admin if dompdf's lib/fonts is not writable
Fix #715800: type-specific settings act as default settings only, not as a type-wide configuration switch
July 15, 2010
Fix #358838: use template_preprocess_node() to initialize node.tpl.php variables
July 14, 2010
LANGUAGE_RTL is always defined in Drupal
Final part of the fix for #646544: update block cache values in the database
Fix #764204: align source url and links on the left side for RTL languages
Fix #801974: only call spl_autoload_register when it exists
Fix #358838 by EugenMayer: Use theme preprocess functions for the template suggestions
July 13, 2010
Fix #608518 by ISPTraderChris: Option to send e-mail as link only or as attachments
Fix #321128 by AndyF: add option to display PF links in teaser mode
Fix #726146 by marrch_caat: node-specific settings ain't saved on node creation
Fix #835814 and #451408 by kingandy: use #prefix and #suffix for the content corner span
Fix #806616 by v.sidorov: use strict comparison when checking the current build mode
Fix #785364: solve incompatibility with PHP 5.3 when using TCPDF
Fix #696318 by JamesK: move body onload javascript into Drupal.behaviors
Fix #735260: Disable named anchors in URL list by default
July 12, 2010
Fix #719486 by moonray: Print link not showing up in content corner if using panels to display nodes
Fix #835470 by adrien.gibrat: Transliterate generated PDF filenames if transliteration module is enabled
Fix #631150 by smk-ka: wkhtmltopdf on windows can use the output pipe again
Fix #257896: Add support for dompdf 0.6+ Unicode mode
Fix #684678: Support dompdf 0.6 adding some required defines
July 10, 2010
Fix #639420, #697616 and #700566: remove use of Xvfb server with wkhtmltopdf
Remove use of Xvfb by wkhtmltopdf
Fix #842462 by sbatman: Use proper hook_theme() arguments format
July 9, 2010
Fix #707534 by truecms.net.au: use Form API for required fields in send e-mail form
June 1, 2010
Fix #704480 by marrch_caat: TCDPF outputs empty PDF
January 11, 2010
Fix #623712: Remove unnecessary urldecode() calls and check URLs using html_entity_decode()
Proper fix for #480916: only use cached node type when processing comments also for mail and pdf links
Fix #665820: handle wkhtmltopdf executable filename finishing in -i386 or -amd64
Fix #631760: add query string to user-specified print.css to force browser reload after cache is cleared
Fix #658208 by Dave Reid: Vertical tabify the print fieldsets
Fix #646544: use correct block cache settings
November 21, 2009
Updated Hungarian translation
November 19, 2009
#244351 by seals: Minor update of Swedish translation.
#244351 by seals: Updated Swedish translation
November 1, 2009
Correct typo/bug in the fix for #521776
Fix #552646: don't add the page to be sent title field in the send-by-email form when the title is empty
Fix #610878: enlarge the wkhtmltopdf and Xvfb options fields
Fix #617888: fix anchor links in pages located in sub-directories
October 16, 2009
by Zoltan Balogh: Updated Hungarian translation
Fix #605264: check node alias also when accessing the print_mail form
October 14, 2009
SA-CONTRIB-2009-073: remove XSS vulnerability in PF URLs list and unathorized access to node titles
Update changelog
October 13, 2009
Fix #521776: support wkhtmltopdf in Windows
Fix #599840: use the real page path and not the current URL when determining link visibility
October 8, 2009
Fix #552882: register dompdf's autoload function to prevent fatal errors
October 7, 2009
Fix #578990: enable tokens in the wkhtmltopdf options string
October 3, 2009
Fix #582360: don't complain about missing e-mail addresses when there's a blank line at the end
Fix #582104: look for PDF libraries in sites/all/libraries
Fix #572848 by aether: Use theme_username() for print_mail_form defaults
Fix #566138: add setting to close the window when both the new window and send to printer are enabled
September 12, 2009
Updated Hungarian translation
September 10, 2009
Fix #554940: escape mysql query string
August 20, 2009
SA-CONTRIB-2009-052: remove multiple XSS vulnerabilities
Try to fix #495946: Don't repeat module updates when already performed in the 5.x version
Fix #544890 by dereine: use node_load with nid only to allow caching
July 15, 2009
Fix #519320: typo in setting non-blocking wkhtmltopdf pipes
Fix #517828: replace the euro sign with an HTML entity
July 9, 2009
add new 'access send to friend' and 'access PDF version' permissions to any role which has 'access print'
Stop using @mainpage in API documentation comments
July 3, 2009
Fix #495814: remove the word core from .info file
Fix #495898: handle node/nid/tab paths correctly
Fix #480916: only use cached node type when processing comments
Fix #495386: make local anchor links navigable inside the PDF
June 15, 2009
Fix #484926: Increase stylesheet URL max field size to 250
Update dompdf download URL
June 7, 2009
Re-enable the use of build_mode (when using CCK, version >= 6.x-2.3 is needed)
revert icon changes
Fix #472920: deny access to paths starting with print/print
June 5, 2009
Fix #481350: Don't show book link in links area when only that option is disabled
Fix #478196: use CSS instead of break tags to arrange block links vertically
May 28, 2009
Fix #468342: Add mail and PDF-specific access permissions
May 21, 2009
Fix #469458: Web version passes XML 1.0 Strict validation test
May 20, 2009
Add some help text to content-type settings to explain that the module-wide settings must be enabled.
Add option to auto-configure the TCPDF library (on by default)
Only remove queries from img URLs which TCPDF will try to access locally
May 17, 2009
Updated German translation by Frank Tartler
Updated Hungarian translation by Zoltan Balogh
Use image scale 1 with TCPDF >= 4.6.002
May 16, 2009
by Zoltan Balogh: Updated Hungarian translation
May 13, 2009
Move title after the meta content-type tag to prevent XSS attacks
Update translations and .pot to current code
Update changelog
Coder fixes
Fix #457528: When using TCPDF remove queries from the image URL
May 11, 2009
Disable corner link span when empty
Add CCK's print_content_build_modes hook (currently disabled)
May 6, 2009
Forgot quotes around UTF-8 in fix for #435578
Fix #451036: don't call drupal_get_title when the non-node path was not found
Don't try to use URL aliases when the node doesn't have one
May 5, 2009
by Zoltan Balogh: Updated Hungarian translation
May 4, 2009
Last part of the fix for the last part of #435578
Fix #420460: When using TCPDF remove imagefield/filefield numerical query from image filenames
Fix #449446 by rsantiag: Use the job_queue module to send emails during the cron run
May 2, 2009
Fix another part of #435578: decode HTML entities in TCPDF title
April 29, 2009
Fix #441770: Footer was placed at top of page in TCPDF => 4.6
April 27, 2009
Improve wkhtmltopdf documentation, configuration and add a directory to place external libraries
Fix #385994: Printer-friendly pages do not inherit organic group membership from original page
April 25, 2009
by Zoltan Balogh: Updated Hungarian translation
April 23, 2009
Prevent PHP from blocking in the wkhtmltopdf code
Use cyclical numbering for the X display instead of random
Coder fixes
April 22, 2009
Fix #283950: clean the output buffer to recover from any TCPDF warning/error
Fix #440376 by rsantiag: add hooks before and after the email sending action
Use Drupal log for wkhtmltopdf errors
Fix #429054: decode html entities in image URLs passed to TCPDF
Fix a notice with undefined node->type when printing system pages
Remove some dead code for an untested fix to #254863
Fix #435578: for now, don't use build_mode as CCK is not ready for it yet
April 21, 2009
Updated German translation by rastatt
Fix #419296 by noelbush: ** Use wkhtmltopdf for PDF generation **
Fix #439314: use better pattern matching for TCPDF's paragraph replacement
April 20, 2009
Fix #437128 by florin: add some bottom padding to the corner link
April 16, 2009
Fix #435386 by rhys: accept recepient lists with consecutive separators \(newlines or commas\)
April 15, 2009
Filter node titles using check_plain
Hide TCPDF notices
Fix #428024: use build_mode in hook_nodeapi and elsewhere
March 27, 2009
Expand the advanced link options by default (too many users couldn't see it) and move the book link inside the fieldset
Fix #391790: display CCK fields (and labels) better in PDFs generated with TCPDF
Try to fix #414910 by using a smaller default weight
Fix #404052: allow node tabs pages to display the links for system pages
Fix #405564: display the content corner links above the content
Try to use other functions to convert from UTF-8 to ISO-8859-1 for the PDF generation with dompdf
March 24, 2009
Fix #408238 by chris.cohen: improve PHP in the default print template
Updated Italian translation by fabrizioprocopio
Updated French translation by xmacinfo
March 18, 2009
SA-CONTRIB-2009-012 Print module can be used as a spam relay
March 17, 2009
Make tests successful again
Coder fixes
March 12, 2009
Fix #303506 partly by joostvdl: remove the country code from paths to private image files used in generating PDFs
Simpler fix to #388008: Use a 'heavier' weight even in the absense of the CCK module
March 10, 2009
Fix #388008: implement CCK's hook_content_extra_fields to manage the order of the per-content type settings
March 5, 2009
Fix #384294 by ron_s: use padding instead of margin in icons
Fix #381586 by Fleshgrinder: add space at the end of the reset button in the send mail form
Fix #372250: Add page title to send mail form and the ability to use the !title token
Improvements to the API index.php
Updated slovak translation by etki
February 20, 2009
Fix #371455: Convert all links in the PDF to absolute
Better fix for #371388: handle tbody tags with attributes
Fix #375892: Don't validate mail send form when pressing cancel
Improved Turkish translation by drupalhizmetleri
Document print_[format].tpl better in the README.txt
February 11, 2009
by Zoltan Balogh: Updated Hungarian translation
February 10, 2009
Update changelog
February 9, 2009
Current mimemail 6.x-1.x-dev no longer causes problems for the mail function, so remove the warnings
Fix #371388 by victorkane and gurubert: delete tbody tags since dompdf can't handle them
Fix #370870: do not delete node-specific settings when users without permission to change them edit a node
February 5, 2009
Update changelog
Add warning for incompatible mimemail settings
Fix for #364535: add some warnings about incompatibility of custom strings and the localization mechanism
Add explanation of the relation between the type- and node-specific print settings
Updated all translations (Dutch 100% thanks to joostvdl)
February 2, 2009
Fix #365041: node-specific settings not initialized when adding new content
Fix #364535: move custom text strings to separate form to prevent conflicts with the translation mechanism
Fix #366835: support RTL languages in TCPDF generated PDFs
January 27, 2009
by Zoltan Balogh: Updated Hungarian translation
January 21, 2009
Updated french translation by remi
Coder fixes
Fix #361107: Ensure that per-node configurations are available for block view use
Revert #349991 until the cause of #359343 can be determined
January 14, 2009
Add configuration for a default sender message
Update changelog
Fix #349991 by moshe weitzman: Use node build_mode instead of custom property for customizing node fields
Fix #351043: Add specific permission to edit the node-specific settings
Fix #356073: Check for CSS file before expanding it and replace spaces with %20 in mails sent
December 19, 2008
Use integers as SQL int default values instead of strings
December 17, 2008
Add PHP visibility option
Move cache disabling code to print_controller() instead of print_pdf_init()
December 16, 2008
Fix #347518: nid is not yet set in node prepare
December 13, 2008
Remove AdSense module's ads from the output
Updated Spanish translation by gusgsm1
Updated Portuguese translation
December 12, 2008
Simplify hook_mail
December 10, 2008
Update changelog
Update translations
Minor coder fixes
December 8, 2008
Fix #344036 by eMPee584: generated PDF filename configurable via tokens (requires the token module)
Fix #343985 by eMPee584: improve removal of comment form and links
Add ability to configure link text strings
Improve variable cleanup at uninstall
December 6, 2008
Fix content corner problem and other minor fixes
December 3, 2008
Fix the different teaser comparison
Try to fix #336865: also replace the opening <p>
Use different teaser comparison
December 2, 2008
Fix #333049 and #333957: Add ability to change user-visible strings in the settings pages
Fix #177358: Link options by node
Fix #247578: Print URLs by content type
Fix #298063: Most printed, emailed and PDFd blocks
December 1, 2008
Disable footer in dompdf
Fix #336860 by Limiting Factor: use realpath for the path replacement when using private files
Fix #339111: Disable caching for PDF files
November 25, 2008
Fix #336065: change nodeapi content weight to make sure that the content area link is rendered first
November 21, 2008
by aries and Zoltan Balogh: Updated Hungarian translation
November 14, 2008
Handle unclean URLs when using private files
November 7, 2008
Use link format and icon options also in book links.
Fix #315204: Add options to show only the current page in book links
Fix #314521: Use file:// access when accessing images if private file system is enabled
November 5, 2008
Use ratio of 0 when image size is not set
Updated Hungarian translation
Revert multi-file translation
November 1, 2008
Translation of the Print, Print mail and Print PDF modules (complete)
October 22, 2008
coder fixes
Improved UTF-8 conversion for dompdf
October 21, 2008
Since dompdf can't handle Unicode, decode it to ISO-8859-1
October 18, 2008
Don't validate the PDF settings when the form is empty
October 17, 2008
Improve handling of no PDF tool installed
October 16, 2008
Change PF link class from print to print_html
Fix #319529: Use referer URL if no path is provided
Fix #321451: Use reset button on email form
Update translations
October 15, 2008
Minor coder fixes
October 14, 2008
Fix #258095: Add block with links to PF versions
Fix #318939: Add title tag to icons
October 8, 2008
Fix #314521: Use real path when private download method is enabled
October 3, 2008
Fix #315014: redirect back to original page after sending email from book node
October 2, 2008
Set query to NULL when the link doesn't contain a query
September 25, 2008
Verify print_controller return value to avoid PHP warnings
Add option to use URL alias in the link
September 23, 2008
Avoid system CSS conflict with dompdf
September 22, 2008
Fix #311270: Use node_not_found() instead of node_access_denied() when appropriate
Make the code closer to Drupal's node_view()
September 20, 2008
Fix #310703 by eMPee584: remove undefined teaser notice
September 18, 2008
Fix #300277: don't break tables when modifying TCPDF's input
September 18, 2008
Add Vietnamese translation by thehong
Fix #309084 by gl0tzk0wski: use addslashes in the dompdf footer function
Fix #308620 by robertDouglass: cast cid to int
Fix #308478 by Obsidiandh: avoid mod_security error in print_mail settings form
September 13, 2008
Remove default front page mail and PDF links
Removed useless redirect of pdf theming functions
September 11, 2008
Updated german translation
Update changelog
Update translations with current .pot
September 10, 2008
Update documentation
Remove some more notices
Use module's CSS files
September 8, 2008
Footer can now be choice between none, site or user-defined
Add footer to the dompdf generation (themeable).
September 7, 2008
Display normal link in pages of type book that are not in books
September 5, 2008
Slightly better API index
September 4, 2008
Repair type-specific link settings
September 3, 2008
Fix wrong fix to #299123
Improve documentation
September 2, 2008
Remove some more PHP notices
Fix #298654: Drupal's theme function doesn't handle references when using PHP4
Fix fix for #301192: don't use drupal_query_string_encode for recursive calls
Use quotes around sender's name
Force menu rebuild after upgrade
Updated german translation
Use better system of detecting TCPDF's PHP version being used
September 1, 2008
Fix #301192: handle arrays in queries correctly
Fix #299123 and #299133: remove PHP notices
August 22, 2008
index.php for the API module
August 21, 2008
Fix use of TCPDF versions later than 4.0.018
Fix use of TCPDF theming with PHP4
Fix #297198: Use SCRIPT_FILENAME instead of DOCUMENT_ROOT to determine Drupal's location in the file-system
Updated german translation (thanks rastatt)
August 14, 2008
Organize everything in folders before the 1.0 release
Some minor coder corrections and updated print.pot
August 13, 2008
Prevent setting of font size to 0 or negative
Font family and size in PDFs generated by TCPDF can now be user-configured
August 9, 2008
Updated german translation. Thanks rastatt
Added the TCPDF footer layout to the themeable functions
Code documentation
Misc changes to comply with the coder module
August 8, 2008
Enable theming of the TCPDF output
August 7, 2008
Only use logo in TCPDF if the temporary file copy was successful
Use the template some more when using TCPDF
Add the links CSS file for the normal link
Add the logo to the TCPDF page
August 6, 2008
Fix #291816: Use CCK's 6.x release path for its CSS file
Update simpletest test for the 6.x-2.x series (compatible with Drupal 7)
Fix bug with visibility where the link was shown when no page was specified but the 'show only in listed pages' was selected
Minor fixes
August 5, 2008
Use more accurate pattern matching in the URL rewrite function
Add some simpletest unit tests
Fix bug where legal characters were being trimmed from the edges of URLS
Delete new variables when uninstalling
Update translations
Prepare _print_friendly_urls for simpletest testing
August 4, 2008
Enable flood control of the send by e-mail functionality
Fix #290262 by Asif99: sys pages starting with 2 or 3 would return error 404
Fix #290587: When send to printer was enabled, the generated PDF was empty
August 2, 2008
Update Hungarian translation by aries
August 1, 2008
Simplify settings form by using more collapsible fieldsets
Added RTL link CSS
Remove some coder warnings
July 30, 2008
Fix #282385: Add CSS margin between icon and text
Fix #288064: Large books sometimes resulted in blank PDFs
Fix #261338: Enable selection of none, theme or user-defined logo. Added also capability to upload logo directly from the settings form.
Fix PDF bug that prevented correct PDF generation introduced in the last patch.
Move the setting form elements back to the defined fieldsets.
Fix #280949: Add macros to the CSS input
Fix #285496: prevent re-encoding of the encoded query
Fix some minor coder warnings
Add some TCPDF calls for better quality output
July 29, 2008
Add option to select location of the links
July 28, 2008
Further improvements to the link enabled detection routines
Fix print*_insert_link functions to point to print*/nn and not print*/node/nn
July 27, 2008
Improve link enabled detection routines
July 25, 2008
Prepare a new link area in the upper right corner of the content
Replaced all inline styles with a core-loaded CSS file
Updated German translation
July 24, 2008
Fix visibility so that it works both with the internal and the aliased paths
July 23, 2008
Re-engineer the variables to no longer use the #tree hierarchy
July 22, 2008
Increase mail form label width to avoid line wrapping
Enable translation of mail form buttons text
July 21, 2008
Fix obscure pattern matching bug for sites that still use index.php in the URL
Moved taxonomy to lower right corner
Remove DOS CR+LF
July 17, 2008
Slightly better current path discovery in the PDF and Web mods
Fix #283799: Allow icons in book links
July 16, 2008
Fix #283423: correct the CSS path inclusion when sending by mail
Vietnamese translation by thehong.
Updated all translations
Misc fixes from the coder module
July 15, 2008
Fix #282385: Remove whitespace between icon and text, use margin instead
July 9, 2008
To make the job easier for themers, added access to the $node var inside the template
Fix #278922: Add support to the RTL languages
Fix #276627: Accept paths of the form node/nnn/args
June 17, 2008
Self configure TCPDF
June 16, 2008
With the new agreement between the major search engines, robots=nocache is obsolete
Set PDF version to 1.6 (Acrobat 7.x)
Use own panel in node type edit form, instead of workflow and comment panels.
June 13, 2008
Fix #270095 by suit4: prevent validation error when the class field is empty
June 6, 2008
Add path-based visibility options to all modules
Minor code documentation fixes
June 4, 2008
Fix #257900: Add capability to use different templates for PDF, mail, etc.
Simplify CSS inclusion code a bit.
Fix #266186 by aaustin: Use drupal_get_title to obtain the page title
Fix #266318 by sun: Use theme_image for the icons (also fix #262900)
June 3, 2008
Added capability to send a user-defined message with the send by e-mail function.
Streamlined the look of the send mail form.
June 2, 2008
Change sys link option to list of paths on which to show the link.
Add option to choose to send only the message teaser.
May 30, 2008
Fix #263349: Add CCK's CSS file to properly display inlined fields
May 29, 2008
Working implementation of the mail sending code
May 26, 2008
Initial send by e-mail support
Fix #262853: Use unicode-enabled fonts in TCPDF
Completed the Turkish translation based on the print.pot version 1.7 (by serkan.arikusu)
May 24, 2008
Completed the Turkish translation based on the print.pot version 1.7 (by serkan.arikusu)
May 23, 2008
Small improvements to the PDF admin functions
Separate open in new window option, so that PDF and web versions can have different settings
Use the template a bit more when using the TCPDF tool.
Make the title in the template be a heading 1.
May 22, 2008
Add ability to configure PDF paper size and page orientation
Misc changes to PDF processing
Add aux vars print['node'] and print['url']
Misc improvements
May 21, 2008
Fix the 'Show book link' option in the PDF version module
Fix the display of links to PF pages and PDF in individual comments
May 20, 2008
Correct display of README.txt in the help
Restore the print_fill_attributes function
Remove the greybox and thickbox selection
Add ability to specify customised classes to the PF links
May 19, 2008
Fix #258689: remove some undefined var warnings
May 13, 2008
Add capability to open PDFs inline or to a save dialog
Added Danish translation. Thanks topsys!
Update Changelog for 6.x-1.0-rc3
May 12, 2008
Slightly better template vars handling
May 11, 2008
Improve translability of template strings
May 10, 2008
Improve the documentation
May 9, 2008
Revert back the last patch
May 8, 2008
Remove what seems to be unnecessary code in print_link
May 7, 2008
Small changes to sync better with the 5.x version
May 6, 2008
Changes to comply with http://www.drupaltoughlove.com/review/printer-friendly-pages
April 22, 2008
Add Printer-friendly module group
April 21, 2008
Added Indonesian translation. Thanks SepedaTua!
Added Slovak translation. Thanks empError!
Fix #249526: correct German translation
Try to fix #230013: only call preg_replace with comment author link if there's anything to replace
April 17, 2008
Remove PDF admin pages dependecy on PHP5.
Added Polish translation. Thanks sir_kula!
Added Swedish translation. Thanks seals!
April 3, 2008
Add thickbox module support.
Fix #239896: Make sure drupal_get_title() returns the original page's title
April 2, 2008
Added Turkish translation. Thanks turkyilmaz1963
March 27, 2008
Remove hard-coding of the greybox class name, now changes to what greybox uses (#233203)
March 24, 2008
Updated Romanian translation. Thanks Andrei
March 21, 2008
Updated translation files to match current code
March 19, 2008
Remove some more PHP warnings
March 14, 2008
Fix #233203: Add option to open in new window using the jQuery Greybox Redux module
March 11, 2008
Some more misc changes by zuriel
March 7, 2008
Some misc changes suggested by zuriel
March 5, 2008
Fix #230318 by shaisachs: include page query in PF link
March 4, 2008
Improve the theme_print_format_link functions
Update changelog for release 6.x-1.0-rc1
Better fix for #227127: use number of patterns instead of comparing to a
Separation of the configuration variables for the HTML and common sections
Ability to configure use of text, icon or both in the PF links
February 28, 2008
Adding icons. Thanks to the Plone Foundation
Fix #227625: add print['url'] var with absolute source url
Add PDF module settings
February 27, 2008
Handle uppercase 'a' tags
February 26, 2008
Properly document the PDF tools installation steps
Rename the print_fill_attributes function back to the previous name
Correct the support for the PDF per-node-type settings
Support print.node-.tpl.php filenames
February 22, 2008
Auto-discovery of the PDF generation tools
February 21, 2008
Make CSS path a full URL so that dompdf can find it
Add PDF support
February 16, 2008
Fix #222234: Use Drupal 6 language var
February 15, 2008
Correct print vars when using the printable engine
February 14, 2008
Better support for Drupal 6.x (performance enhancements via include files and new translation I/F)
Add current page title to printed breadcrumb
Fix #216728 better: if first link was duplicate a new ref was generated
February 9, 2008
Better support for Drupal sites that do not reside in the server root.
Fix the 'printable' engine to display the page title.
Cleanup code (ran latest coder module)
February 8, 2008
Replace module CSS import with an @import statement
February 5, 2008
Fix 217928: add default value to variable_get('anonymous')
February 4, 2008
Fix #217439: Add defined javascript to the PF page
Fix #198688: remove added %20
Remove whitespace immediately before and after the '=' sign
Fix #216728 by jpereza: Don't show duplicate URLs in the URL list
Fix #216716: do not process hreflang attributes
January 25, 2008
Add rel=nofollow tag to PF link (#213951)
Add taxonomy terms to the PF page (#214081)
Small fixes to 6.x
January 24, 2008
Sync 5.x to 6.x
Remove comment forms from PF page (fix for #213425)
January 23, 2008
Fix wrong Paginate hack (replace pages_count with page_count)
January 22, 2008
Added ability to change the output strings through theming (as per #206365)
Slightly better solution to #211349.
Added Portuguese (Brazil) translation (thanks psychopath_mind!)
January 21, 2008
Fix #211349: Add current query params to PF link
January 8, 2008
Update changelog
January 5, 2008
Add div tags around the logo image (fix for #206568)
January 2, 2008
Fix #202243: Use the anonymous setting for pages with a blank author variable
December 14, 2007
Added ability to theme the print_format_link function (fix for #198397)
Added access check to the print_insert_link function
December 4, 2007
Minor fix to #192855, use full base_url if it does not include subdirs
December 3, 2007
Sync print 5.x to 4.7.x
Sync 5.x to 6.x
Proper fix to the book_node_visitor_html_pre which was incorrectly committed with 'print' instead of 'view'
Fix #195917: Use correct module check in hook_link_alter
December 2, 2007
Add replacement book_node_visitor_html_pre so that CCK pages in book nodes print correctly
November 22, 2007
Fix #192855: If relative links start with '/' just append them to the server name (commit to 5.x-3.x-dev)
Fix #192855: If relative links start with '/' just append them to the server name
November 19, 2007
Sync print 5.x to 4.7.x
Sync print 5.x to 4.7.x
Update changelog
Complete Spanish translation. Thanks gustz!
Complete French translation. Thanks rondev!
November 17, 2007
Complete versions of the Hungarian and German translations. Thanks hinger and hailstorm!
Try to solve #192855, by checking also for index.php in relative links
November 15, 2007
Sync print 5.x to 6.x
Sync print 5.x to 4.7.x
Final translation to russian. Thanks VladSavitsky!
Remove TODOs in the .po files
Updated Norwegian translation to final. Thanks stenjo!
Added (partial) Italian translation. Thanks ccattaneo74!
Added (partial) Ukrainian translation. Thanks artem_sokolov!
Added (partial) Romanian translation. Thanks baudolino!
November 15, 2007
Added (partial) Romanian translation. Thanks baudolino!
November 13, 2007
Make anchor tags (#id) links usable in the PF version again (after the base href fix broke it).
Add setting to control the book PF link via this module
Update all .po files to the latest print.pot from the potx module
November 9, 2007
Add the capability to handle book's PF link via this module
November 8, 2007
Enable choice of method to open the new window via radio boxes (now possible to select a Javascript XHTML Strict compliant method)
November 7, 2007
Correct fix for the duplicate PF link in book pages
Sync documentation in HEAD with the 5.x version
Russian translation by VladSavitsky. Thanks!
Remove duplicate PF link in book pages
November 6, 2007
Updated the installation instructions (INSTALL.txt)
Update documentation (README, CREDITS and CHANGELOG)
October 31, 2007
Fix #172100: use drupal_get_html_head to starting building the head section
October 30, 2007
Backport of version 5.x-2.x-dev into Drupal 4.7
Minor changes
Minor changes
Minor changes
October 29, 2007
Sync HEAD with latest print-5.x-2.x-dev
Changes to work with drupal 6.x
October 28, 2007
Add an inactive line for an XHTML Strict compliant way of opening the PF page in a new window.
Fixed small code details raised by the coder module.
Updated Norwegian and Hungarian translation. Thanks stenjo and hinger!
October 27, 2007
Added Portuguese (Portugal) translation. Thanks jcnventura :)
Fixed settings description bug in the URL list still describing the old link deactivation feature.
Remove link area in system pages
Update print.pot to current version (and the fr, de, hu and no .po files)
Fix problem with printing pages if printing comments is enabled, but the comments module is disabled.
Move the print/ path to a constant for easier modification of this hard-coded setting.
October 25, 2007
Fix some issues with the book detection routine and check for access rights for system pages
Make the print_insert_link parameter optional.
Configure the display of the link for non-node types.
Prevent display of the link in book types.
Finish comment printing functions (configuration settings and print all comments with node contents capability). Solve #135089
Add print_insert_link function for use by content writers to position link anywhere in the content. Solves #186216 and (maybe) #180975
Support templates for specific content types and location of templates in both tthe theme directory (checked first) and the module directory. Solves #181458 and #171172
Support for printing individual comments
October 24, 2007
Support printer-friendly pages everywhere in Drupal (adapted from printable module)
October 23, 2007
Fix #184776 by deviantintegral: <a> tag rewrite affected <address>
No need to transalate spaces and paranthesis on " (retrieved on "
Changed print.pot to use string locations in print.module and not print.node.tpl.php
German translation by hailstorm
Norwegian translation by stenjo
October 9, 2007
Re-structure template and code by moving all the printer-friendly-specific output processing to a dedicated function
October 6, 2007
Hungarian translation by hinger.. Thanks!
October 1, 2007
French translation by rondev
Fix #178596 and #178743 by Waldemar: Fix base URL, CSS import and logo code problems with IE 6/7
September 24, 2007
Fixed bug in url alias destination nid, get it from the dst string now
Fix #174983: if clean urls is disabled use url() only if it is an a link that does not start with =q?
Fix #128049: also accept print/url_alias
September 13, 2007
Try to fix #174983: handling of URLs with Drupal's ?q=
September 12, 2007
Added $node->printing flag to alert other modules.
Fix #60817, #74949, #171146, #117236, #172252, #173244.
Fixed buggy link in comments, removed service links and fivestar modules output and removed Paginate's module pagination.
Correctly handle spaces in filenames and URLs.
August 30, 2007
Fix #171039. urldecode() the input URL before calling url(/) so that unicode chars are processed correctly
August 28, 2007
Fix bug of printer-friendly link being displayed for teasers
Fix bug where anchor tags were not correctly converted to absolute and the anchor destination was marked with '[Array]'
Made anchor links still navigable when the print urls option is selected
Fix bug of string parsing for t() calls in print.node.tpl.php
Regenerate po/print.pot with potx module
August 27, 2007
File containing the default CSS styles
Changed the render method to behave more like node_view
Added the ability to enable/disable the printer-friendly like in the content type form
Configuration options regarding the Source URL and the ability to open the page in a new window and print it
New URL re-writing method
Overall definition of CSS classes and style
Hyphenated the words "printer-friendly"
August 26, 2007
New URL rewriting engine; Definition of new CSS classes and styles; Configuration options regarding the Source URL and the ability to open the page in a new window and print it
August 24, 2007
Sync with HEAD
Sync with HEAD
Profile printing is not working. Since utility is not clear, I am removing itfor now
Try to fix #71391 and try to display other node types through the use of the drupal render engine
Change maintainer information
Fix links to relative/internal URLs (#58100)
Fix #129535. Use ->url instead of
Fix #49794 and #89724. Use print/nid instead of node/nid/print
#60334 by the greenman. Handle 'a name' tags
Apply to CVS HEAD Andy Kirkham's DRUPAL-SA-2007-014: fixing access bypass bug for private issues
August 23, 2007
Add current time/date before the Source URL
Make the printer friendly page XHTML Strict compliant.
July 10, 2007
DRUPAL-SA-2007-014: fixing access bypass bug for private issues
DRUPAL-SA-2007-014: fixing access bypass bug for private issues
March 26, 2007
clean up menu.
clean up menu.
remove dead code.
remove dead code.
adding .info file.
#88162 -- update to 5.0. patch by hunmonk, diggersf.
October 23, 2006
French translation of print.module Drupal 4.7
August 2, 2006
updated Dutch translation
July 15, 2006
Czech translation of print.module
March 30, 2006
issue #54997: extra slash in URLs
issue #54997: extra slash in URLs
issue #50299: missing t()
issue #50299: missing t()
January 15, 2006
backport of semi-fix for issue #33909
backport of issue #42857
December 31, 2005
Added init_theme to fix bug with logo.
http://drupal.org/node/42857
December 30, 2005
update stable to HEAD
put some bug fixes from HEAD into DRUPAL-4-7
Fixed bug: http://drupal.org/node/25437
Fixed print url friendly (http://drupal.org/node/18716)
Updated to DRUPAL-4-7
December 21, 2005
update version requirements
summarize tonight's changes
contrib by Markus Petrux for Drupal 4.6
remove hardcode print.css location, let robots meta work for print_generate_profile(), update users table query for Drupal 4.7, and fix an error missing parameter to variable_get()
December 21, 2005
default settings point to a css file and it makes a lot of 404 errors to not have one to match
work on forms API compatability, and fixes towards issues #33909, #28265, #17322, #25437
bug fix #17317
December 20, 2005
bug fixes #33909, #25275, #31715, #17317
fix bug #18716
Updated with patch for 4.7.
Updated for 4.
August 24, 2005
Added missing word.
Added missing word.
July 27, 2005
* Renamed file to print.node.tpl.php
* Created a general print controller to allow modules to generate printer friendly views.
* Printer friendly profile pages. See INSTALL.txt for details.
* Renamed the node print template from print.tpl.php to print.node.tpl.php
July 14, 2005
Commited my patch from
http://drupal.org/node/25458
with permission of the maintainer.
June 21, 2005
Added German translation.
June 1, 2005
- Brazilian Portuguese Translation of print.module
- Added print.tpl.php strings
April 26, 2005
Updated print.pot file.
February 14, 2005
km - corrected printing of source URL
km - changed the syntax of some lines to pass code-style.pl checks
January 28, 2005
km - removed hint on site logo
km - changed strings back to 'printer friendly page'
January 28, 2005
km - introduced printer friendly icon
January 26, 2005
km - changed line numbers and added strings from print.tpl.php
km - changed strings, added strings from print.tpl.php
km - included changes from HEAD
km - changed link
km - improved layout and localized strings
January 25, 2005
km - honor themes' global settings for "Display post information"
km - print_link() checks if page is a book
km - changed maintainer
November 25, 2004
* Made CSS import work
November 15, 2004
created pot-file with extractor.php and added dutch translation
November 12, 2004
added CUSTOMIZATION
November 5, 2004
Taking over maintainance
October 30, 2004
* Created a print.tpl.php template file to give site admins control of what node parts this module renders and how the pages are structured. This feature, combined with the custom print stylesheet option, gives max freedom in rendering print friendly pages.
* Created a print.tpl.php template file to give site admins control of what node parts this module renders and how the pages are structured. This feature, combined with the custom print stylesheet option, gives max freedom in rendering print friendly pages.
October 28, 2004
* Generate printer friendly pages for all node types. Features include the ability to list $node->body URL references at the end of the page, custom print stylesheet and choosing which node elements to display.
January 9, 2002
print.module- initial commit.
- attempted to fix the bugs with the chatbox module. Feedback requested.
- need some installation instructions. Anyone?
file print.module was initially added on branch DRUPAL-3-0.
October 19, 2001
file LICENSE was initially added on branch DRUPAL-3-0.

View file

@ -0,0 +1,5 @@
This module was created by Matt Westgate <drupal at asitis dot org>
Maintained up to version 4.6 by Karsten Mueller <kmue at mac dot com>
Maintained up to version 4.7 by Peter John Hartman <peterjohnhartman at gmail.com>
Some bug fixes by David Kent Norman on Dec 20, 2005 <deekayen at: deekayen {dot} net>
and is currently maintained by Joao Ventura <joao at venturas dot org>.

View file

@ -0,0 +1,97 @@
INSTALLATION
------------
Decompress the print-n.x-n.n.tar.gz file into your Drupal modules
directory (usually sites/all/modules, see http://drupal.org/node/176044 for
more information).
Enable the print module: Administer > Site building > Modules
(admin/build/modules)
PDF TOOL
--------
The print_pdf module requires the use of an external PDF generation tool.
The currently supported tools are dompdf, TCPDF and wkhtmltopdf. Please
note that any errors/bugs in those tools need to be reported and fixed by
their maintainers. DO NOT report bugs in those tools in the print module's
issue queue at Drupal.org.
supported paths:
* print module lib directory (usually sites/all/modules/print/lib)
* libraries directory (sites/all/libraries)
dompdf support:
The dompdf tool produces results that are more faithful to the HTML
printer-friendly page. Unicode is not supported (only ISO-8859-1).
This tool is not supported and there are several known bugs that result
from its incomplete implementation.
1. Download dompdf from http://code.google.com/p/dompdf/downloads/list
2. Extract the contents of the downloaded package into one of the
supported paths.
3. Check if dompdf_config.inc.php fits your installation. In 99% of cases,
no changes are necessary, so just try to use it and only edit anything if
the PDF generation fails.
4. Grant write access to the lib/fonts directory to your webserver user.
5. If you're using dompdf-0.5.1, delete the dompdf.php file as it contains
a security vulnerability
6. If you're using dompdf-0.6 or later, you can try to enable the Unicode
support, but you'll need to add some Unicode fonts. See
http://groups.google.com/group/dompdf/browse_thread/thread/9f7bc0162b04d5cf
for further info on this.
7. Check http://code.google.com/p/dompdf/ for further information.
TCPDF support:
TCPDF seems to be more actively developed than dompdf, but it's support
for CSS is considerably worse. Unicode is supported (use of Unicode fonts
result in HUGE files). Page header and footer are supported. This module
requires TCPDF >= 4.0.000.
1. Download TCPDF from http://sourceforge.net/projects/tcpdf/
2. Extract the contents of the downloaded package into one of the
supported paths. There is no need to modify the config/tcpdf_config.php
file, as the module self-configures TCPDF.
3. Grant write access to the cache and images directories to your
webserver user.
4. Check http://tcpdf.sourceforge.net/ for further information.
wkhtmltopdf support:
1. Download wkhtmltopdf from
http://code.google.com/p/wkhtmltopdf/downloads/list. You can choose to
download the source and compile it or simply download the static binary,
which doesn't require you to compile anything. Note that the compiled
version may require a running X server (static uses patched libs that can
work without one).
2. Place the wkhtmltopdf executable into one of the supported paths.
(usually sites/all/modules/print/lib). You can also place a symbolic link
to the executable.
3. Check http://code.google.com/p/wkhtmltopdf/ for further information.
UPDATE
------
When updating from a previous version, just remove the print directory and
follow the instructions above. Make sure that you backup any costumization
to the print.tpl.php and print.css files.
ROBOTS
------
Even though it is possible to set per-page robots settings, the following
can be placed in your robots.txt file after the User-agent line to prevent
search engines from even asking for the page:
Disallow: /print/
Also, for updates from older versions (<=4.7.x-1.0 and <=5.x-1.2) which used
node/nnn/print instead of print/nnn, the following lines can prevent
requests from Google for the obsolete print URLs:
Disallow: /*/print$
Note that pattern matching in robots.txt is a Google extension (see
http://www.google.com/support/webmasters/bin/answer.py?answer=40367 for more
information).

View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -0,0 +1,3 @@
PRINT MODULE
M: Joao Ventura <joao at venturas dot org>
S: maintained

View file

@ -0,0 +1,127 @@
DESCRIPTION
-----------
This module allows you to generate the following printer-friendly versions
of any node:
* Web page printer-friendly version (at www.example.com/print/nid)
* PDF version (at www.example.com/printpdf/nid)
* Send by-email (at www.example.com/printmail/nid)
where nid is the node id of content to render.
A link is inserted in the each node (configurable in the content type
settings), that opens a version of the page with no sidebars, search boxes,
navigation pages, etc.
INSTALLATION
------------
Follow the instructions in the provided INSTALL.txt file.
CONFIGURATION
-------------
- There are several settings that can be configured in the following places:
Administer > Site building > Modules (admin/build/modules)
Enable or disable the module. (default: disabled)
Administer > User management > Permissions (admin/user/permissions)
Under print module:
access print: Enable access to the PF page and display of the PF link in
other pages. (default: disabled)
administer print: Enable access to the module settings page. (default:
disabled)
Administer > Content management > Content types (admin/content/types)
For each content type it is possible to enable or disable the PF link
via the "Show printer-friendly version link" checkbox. (default:
enabled)
It is also possible to enable or disable the PF link in individual
comments via the "Show printer-friendly version link in individual
comments" checkbox. (default: disabled)
Administer > Site configuration > Printer-friendly (admin/settings/print)
This is where all the module-specific configuration options can be set.
- To modify the template of printer friendly pages, simply edit the
print.tpl.php or the css/print.css files.
- It is possible to set per-content-type and/or theme-specific templates
which are searched for in the following order:
1. print_[format].node-[type].tpl.php in the theme directory
2. print_[format].node-[type].tpl.php in the module directory
3. print_[format].tpl.php in the theme directory
4. print_[format].tpl.php in the module directory
5. print.node-[type].tpl.php in the theme directory
6. print.node-[type].tpl.php in the module directory
7. print.tpl.php in the theme directory
8. print.tpl.php in the module directory (supplied by the module)
format is either html, mail or pdf, and type is Drupal's node type (e.g.
page, story, etc.)
API
---
print_insert_link(), print_mail_insert_link(), print_pdf_insert_link()
The *_insert_link functions are available to content developers that prefer
to place the printer-friendly link in a custom location. It is advisable to
disable the regular Printer-friendly link so that it is not shown in both
locations.
Calling the function like this:
print_insert_link()
will return the HTML for a link pointing to a Printer-friendly version of
the current page.
It is also possible to specify the link to the page yourself:
print_insert_link("print/42")
will return the HTML pointing to the printer-friendly version of node 42.
THEMEABLE FUNCTIONS
-------------------
The following themeable functions are defined:
* theme_print_format_link()
* theme_print_mail_format_link()
* theme_print_pdf_format_link()
Returns an array of formatted attributes for the Printer-friendly
link.
* print_pdf_dompdf_footer($html)
Format the dompdf footer contents
* print_pdf_tcpdf_header($pdf, $html, $font)
Format the TCPDF header
* print_pdf_tcpdf_page($pdf)
Format the TCPDF page settings (margins, etc)
* print_pdf_tcpdf_content($pdf, $html, $font)
Format the TCPDF page content
* print_pdf_tcpdf_footer($pdf, $html, $font)
Format the TCPDF footer contents
* print_pdf_tcpdf_footer2($pdf)
Format the TCPDF footer layout
MORE INFORMATION
----------------
For more information, consult the modules' documentation at
http://drupal.org/node/190171.
ACKNOWLEDGMENTS
---------------
The print, pdf and mail icons are copyright Plone Foundation. Thanks for
letting me use them!

View file

@ -0,0 +1,12 @@
body {
direction: rtl;
}
th {
text-align: right;
}
.print-links,
.print-source_url,
.print-taxonomy {
text-align: left;
}

View file

@ -0,0 +1,59 @@
body {
margin: 1em;
background-color: #fff;
font-family: sans-serif;
}
th {
text-align: left; /* LTR */
color: #006;
border-bottom: 1px solid #ccc;
}
tr.odd {
background-color: #ddd;
}
tr.even {
background-color: #fff;
}
td {
padding: 5px;
}
#menu {
visibility: hidden;
}
#main {
margin: 1em;
}
a:link {color: #000;}
a:visited {color: #000;}
a:hover {color: #00f;}
a:link img, a:visited img {border: 0;}
.print-footnote {font-size: xx-small;}
img.print-logo {border: 0;}
.print-site_name {}
.print-breadcrumb {font-size: x-small;}
.print-title {}
.print-submitted {font-size: small;}
.print-created {font-size: small;}
.print-taxonomy {
text-align: right;
}
.print-taxonomy li {display: inline;}
.print-content {}
.print-hr {
border: 0;
height: 1px;
width: 100%;
color: #9E9E9E;
background-color: #9E9E9E;
}
.print-source-and-links {
page-break-before: always;
}
.print-message {
border: medium dotted blue;
padding: 1em;
}
.print-source_url {font-size: small; margin-bottom: 1em;}
.print-links {font-size: small;}
.print-footer {text-align: center;}

View file

@ -0,0 +1,27 @@
.print-link {
/* Use these for links above the content */
text-align: left;
/* Use these for links in a corner of the content */
/*
float:left;
*/
}
.print_html, .print_mail, .print_pdf {
margin-left: 0;
margin-right: 1em;
}
.print-syslink {
margin-right: 0;
margin-left: 1em;
}
img.print-icon-margin {
padding-left: 4px;
}
label.printmail-label {
float: right;
}

View file

@ -0,0 +1,38 @@
.print-link {
/* Use these for links above the content */
display: block;
text-align: right;
padding-bottom: 0.5em;
/* Use these for links in a corner of the content */
/*
position:relative;
bottom: 0.5em;
float:right;
*/
}
div#block-print-0 span {
display: block;
}
.print_html, .print_mail, .print_pdf {
margin-left: 1em;
}
.print-syslink {
margin-right: 1em;
}
img.print-icon {
vertical-align: middle;
}
img.print-icon-margin {
padding-right: 4px;
}
label.printmail-label {
width: 175px;
float: left;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

View file

@ -0,0 +1,6 @@
Instead of placing the downloaded external libs (such as TCPDF, dompdf,
etc.) used by the print module here, you should place them in
sites/all/libraries.
This directory is still a valid location for them, however. The Libraries
API module library path is also valid.

View file

@ -0,0 +1,420 @@
<?php
/**
* @file
* Contains the administrative functions of the PF module.
*
* This file is included by the core PF module, and includes the
* settings form.
*
* @ingroup print
*/
/**
* Menu callback for the Printer-friendly pages module settings form.
*
* @ingroup forms
*/
function print_main_settings() {
$print_css = variable_get('print_css', PRINT_CSS_DEFAULT);
// Check that the stylesheet path is indeed valid and relative to base_path()
if (!empty($print_css) && empty($_POST)) {
$css_path = dirname($_SERVER['SCRIPT_FILENAME']) .'/'. strtr($print_css, array('%t' => drupal_get_path('theme', variable_get('theme_default', 'garland'))));
if (!is_file($css_path) || !is_readable($css_path)) {
drupal_set_message(t("File %file is not readable by the web server.", array('%file' => $css_path)), 'warning', FALSE);
}
}
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Common settings'),
);
$form['settings']['print_css'] = array(
'#type' => 'textfield',
'#title' => t('Custom stylesheet'),
'#default_value' => $print_css,
'#size' => 60,
'#maxlength' => 250,
'#description' => t('The path to your custom print cascading stylesheet, if any. The path provided must be relative to the base path. When none is specified, the default module CSS file is used.') .'<br />'.
t('Macros: %t (path to theme: "%theme")', array('%theme' => drupal_get_path('theme', variable_get('theme_default', 'garland')))) .'<br />'.
t('Requires the <em>administer site configuration</em> permission.'),
'#disabled' => !user_access('administer site configuration'),
);
$form['settings']['print_keep_theme_css'] = array(
'#type' => 'checkbox',
'#title' => t('Keep the current theme CSS'),
'#default_value' => variable_get('print_keep_theme_css', PRINT_KEEP_THEME_CSS_DEFAULT),
'#description' => t('If set, the current theme css will still be applied to the printer-friendly versions.'),
);
$form['settings']['print_urls'] = array(
'#type' => 'checkbox',
'#title' => t('Printer-friendly URLs list'),
'#default_value' => variable_get('print_urls', PRINT_URLS_DEFAULT),
'#description' => t('If set, a list of the destination URLs for the page links will be displayed at the bottom of the page.') .'<br />'.
t('Note that you can enable/disable the URL list for each content type individually from the !url.', array('!url' => l(t('Content Types page'), 'admin/content/types'))),
);
$form['settings']['print_urls_anchors'] = array(
'#type' => 'checkbox',
'#title' => t('Include named anchors in printer-friendly URLs list'),
'#default_value' => variable_get('print_urls_anchors', PRINT_URLS_ANCHORS_DEFAULT),
'#description' => t('If set, the list of the URLs at the bottom of the page will include anchors links on the same page.'),
);
$form['settings']['print_comments'] = array(
'#type' => 'checkbox',
'#title' => t('Include comments in printer-friendly version'),
'#default_value' => variable_get('print_comments', PRINT_COMMENTS_DEFAULT),
'#description' => t('When this option is active, user comments are also included in the printer-friendly version. Requires the comment module.'),
);
$form['settings']['print_newwindow'] = array(
'#type' => 'radios',
'#title' => t('New window method'),
'#options' => array(t('Use HTML target (does not validate as XHTML Strict)'), t('Use Javascript (requires browser support)')),
'#default_value' => variable_get('print_newwindow', PRINT_NEWWINDOW_DEFAULT),
'#description' => t('Choose the method used to open pages in a new window/tab.'),
);
$form['settings']['logo'] = array(
'#type' => 'fieldset',
'#title' => t('Logo options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['settings']['logo']['print_logo_options'] = array(
'#type' => 'radios',
'#title' => t('Logo type'),
'#options' => array(t('None (Disabled)'), t("Current theme's logo"), t('User-specified')),
'#default_value' => variable_get('print_logo_options', PRINT_LOGO_OPTIONS_DEFAULT),
'#description' => t("Select the type of logo to display on the printer-friendly version. In case of a user-specified location, insert the path or URL below."),
);
$form['settings']['logo']['print_logo_url'] = array(
'#type' => 'textfield',
'#title' => t('Logo URL'),
'#default_value' => variable_get('print_logo_url', PRINT_LOGO_URL_DEFAULT),
'#size' => 60,
'#maxlength' => 250,
);
$form['settings']['logo']['print_logo_upload'] = array(
'#type' => 'file',
'#title' => t('Upload logo'),
'#size' => 60,
'#maxlength' => 250,
'#description' => t("If you don't have direct file access to the server, use this field to upload your logo."),
);
$form['settings']['footer'] = array(
'#type' => 'fieldset',
'#title' => t('Footer options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['settings']['footer']['print_footer_options'] = array(
'#type' => 'radios',
'#title' => t('Footer type'),
'#options' => array(t('None (Disabled)'), t("Site's footer"), t('User-specified')),
'#default_value' => variable_get('print_footer_options', PRINT_FOOTER_OPTIONS_DEFAULT),
'#description' => t("Select the type of footer to display on the printer-friendly version. In case of a user-specified footer, insert it below."),
);
$form['settings']['footer']['print_footer_user'] = array(
'#type' => 'textfield',
'#title' => t('User-specified'),
'#default_value' => variable_get('print_footer_user', PRINT_FOOTER_USER_DEFAULT),
'#size' => 60,
'#maxlength' => 250,
);
$form['settings']['print_sourceurl_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Source URL'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['settings']['print_sourceurl_settings']['print_sourceurl_enabled'] = array(
'#type' => 'checkbox',
'#title' => t('Display source URL'),
'#default_value' => variable_get('print_sourceurl_enabled', PRINT_SOURCEURL_ENABLED_DEFAULT),
'#description' => t('When this option is selected, the URL for the original page will be displayed at the bottom of the printer-friendly version.'),
);
$form['settings']['print_sourceurl_settings']['print_sourceurl_date'] = array(
'#type' => 'checkbox',
'#title' => t('Add current time/date to the source URL'),
'#default_value' => variable_get('print_sourceurl_date', PRINT_SOURCEURL_DATE_DEFAULT),
'#description' => t('Display the current date and time in the Source URL line.'),
);
$form['settings']['print_sourceurl_settings']['print_sourceurl_forcenode'] = array(
'#type' => 'checkbox',
'#title' => t('Force use of node ID in source URL'),
'#default_value' => variable_get('print_sourceurl_forcenode', PRINT_SOURCEURL_FORCENODE_DEFAULT),
'#description' => t("Drupal will attempt to use the page's defined alias in case there is one. To force the use of the fixed URL, activate this option."),
);
$form['#attributes'] = array('enctype' => 'multipart/form-data');
$form['#validate'][] = '_print_main_settings_validate';
return system_settings_form($form);
}
/**
* Validate print_main_settings form.
*/
function _print_main_settings_validate($form, &$form_state) {
global $base_url;
// Check for a new uploaded logo, and use that instead.
if ($file = file_save_upload('print_logo_upload', array('file_validate_is_image' => array()))) {
$parts = pathinfo($file->filename);
$filename = 'print_logo.'. drupal_strtolower($parts['extension']);
// The image was saved using file_save_upload() and was added to the
// files table as a temporary file. We'll make a copy and let the garbage
// collector delete the original upload.
if (file_copy($file, $filename, FILE_EXISTS_REPLACE)) {
$form_state['values']['print_logo_options'] = 2;
$form_state['values']['print_logo_url'] = base_path() . $file->filepath;
}
}
}
/**
* Menu callback for the Printer-friendly pages HTML settings form.
*
* @ingroup forms
*/
function print_html_settings() {
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Web page options'),
);
$form['settings']['print_html_link_pos'] = array(
'#type' => 'checkboxes',
'#title' => t('Printer-friendly page link'),
'#default_value' => variable_get('print_html_link_pos', unserialize(PRINT_HTML_LINK_POS_DEFAULT)),
'#options' => array('link' => t('Links area'), 'corner' => t('Content corner'), 'block' => t('Block'), 'help' => t('Help area')),
'#description' => t('Choose the location of the link(s) to the printer-friendly page. The Links area is usually below the node content, whereas the Content corner is placed in the upper-right corner of the node content. Unselect all options to disable the link. Even if the link is disabled, you can still view the print version of a node by going to !path/nid where nid is the numeric id of the node.', array('!path' => PRINT_PATH)),
);
$form['settings']['print_html_link_teaser'] = array(
'#type' => 'checkbox',
'#title' => t('Display printer-friendly link in teaser'),
'#default_value' => variable_get('print_html_link_teaser', PRINT_HTML_LINK_TEASER_DEFAULT),
'#description' => t('Enabling this will display the link in teaser mode.'),
);
$form['settings']['adv_link'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced link options'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['settings']['adv_link']['print_html_show_link'] = array(
'#type' => 'radios',
'#title' => t('Link style'),
'#default_value' => variable_get('print_html_show_link', PRINT_HTML_SHOW_LINK_DEFAULT),
'#options' => array(1 => t('Text only'), 2 => t('Icon only'), 3 => t('Icon and Text')),
'#description' => t('Select the visual style of the link.'),
);
$form['settings']['adv_link']['print_html_link_use_alias'] = array(
'#type' => 'checkbox',
'#title' => t('Use URL alias instead of node ID'),
'#default_value' => variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT),
'#description' => t('Enabling this will create the link using the URL alias instead of the node ID.'),
);
$form['settings']['adv_link']['print_html_link_class'] = array(
'#type' => 'textfield',
'#title' => t('Link class'),
'#default_value' => variable_get('print_html_link_class', PRINT_HTML_LINK_CLASS_DEFAULT),
'#size' => 60,
'#maxlength' => 250,
'#description' => t('This can be used by themers to change the link style or by jQuery modules to open in a new window (e.g. greybox or thickbox). Multiple classes can be specified, separated by spaces.'),
);
$form['settings']['adv_link']['print_html_node_link_visibility'] = array(
'#type' => 'radios',
'#title' => t('Link visibility'),
'#default_value' => variable_get('print_html_node_link_visibility', PRINT_HTML_NODE_LINK_VISIBILITY_DEFAULT),
'#options' => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.')),
);
$form['settings']['adv_link']['print_html_node_link_pages'] = array(
'#type' => 'textarea',
'#default_value' => variable_get('print_html_node_link_pages', PRINT_HTML_NODE_LINK_PAGES_DEFAULT),
'#rows' => 3,
'#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>')),
'#wysiwyg' => FALSE,
);
$access = user_access('use PHP for link visibility');
if ($form['settings']['adv_link']['print_html_node_link_visibility']['#default_value'] == 2 && !$access) {
$form['settings']['adv_link']['print_html_node_link_visibility'] = array('#type' => 'value', '#value' => 2);
$form['settings']['adv_link']['print_html_node_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_html_node_link_pages']['#default_value']);
}
elseif ($access) {
$form['settings']['adv_link']['print_html_node_link_visibility']['#options'][] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$form['settings']['adv_link']['print_html_node_link_pages']['#description'] .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
}
$form['settings']['adv_link']['print_html_sys_link_visibility'] = array(
'#type' => 'radios',
'#title' => t('Show link in system (non-content) pages'),
'#description' => 'Any page that is not a Drupal node. Usually pages generated by Drupal or a module such as Views or Panels.',
'#default_value' => variable_get('print_html_sys_link_visibility', PRINT_HTML_SYS_LINK_VISIBILITY_DEFAULT),
'#options' => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.')),
);
$form['settings']['adv_link']['print_html_sys_link_pages'] = array(
'#type' => 'textarea',
'#default_value' => variable_get('print_html_sys_link_pages', PRINT_HTML_SYS_LINK_PAGES_DEFAULT),
'#rows' => 3,
'#description' => t('Setting this option will add a printer-friendly version page link on pages created by Drupal or the enabled modules.') .'<br />'.
t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>')),
'#wysiwyg' => FALSE,
);
if ($form['settings']['adv_link']['print_html_sys_link_visibility']['#default_value'] == 2 && !$access) {
$form['settings']['adv_link']['print_html_sys_link_visibility'] = array('#type' => 'value', '#value' => 2);
$form['settings']['adv_link']['print_html_sys_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_html_sys_link_pages']['#default_value']);
}
elseif ($access) {
$form['settings']['adv_link']['print_html_sys_link_visibility']['#options'][] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$form['settings']['adv_link']['print_html_sys_link_pages']['#description'] .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
}
$form['settings']['adv_link']['print_html_book_link'] = array(
'#type' => 'radios',
'#title' => t('Link in book hierarchy nodes'),
'#default_value' => variable_get('print_html_book_link', PRINT_HTML_BOOK_LINK_DEFAULT),
'#options' => array(t('Book module link not modified'), t('Current page and sub-pages'), t('Current page only')),
);
$form['settings']['print_html_new_window'] = array(
'#type' => 'checkbox',
'#title' => t('Open the printer-friendly version in a new window'),
'#default_value' => variable_get('print_html_new_window', PRINT_HTML_NEW_WINDOW_DEFAULT),
'#description' => t('Setting this option will make the printer-friendly version open in a new window/tab.'),
);
$form['settings']['print_html_sendtoprinter'] = array(
'#type' => 'checkbox',
'#title' => t('Send to printer'),
'#default_value' => variable_get('print_html_sendtoprinter', PRINT_HTML_SENDTOPRINTER_DEFAULT),
'#description' => t("Automatically calls the browser's print function when the printer-friendly version is displayed."),
);
$form['settings']['print_html_windowclose'] = array(
'#type' => 'checkbox',
'#title' => t('Close window after sending to printer'),
'#default_value' => variable_get('print_html_windowclose', PRINT_HTML_WINDOWCLOSE_DEFAULT),
'#description' => t("When the above options are enabled, this option will close the window after its contents are printed."),
);
$form['settings']['print_display_sys_urllist'] = array(
'#type' => 'checkbox',
'#title' => t('Printer-friendly URLs list in system pages'),
'#default_value' => variable_get('print_display_sys_urllist', PRINT_TYPE_SYS_URLLIST_DEFAULT),
'#description' => t('Enabling this option will display a list of printer-friendly destination URLs at the bottom of the page.'),
);
$form['settings']['print_robots_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Robots META tags'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['settings']['print_robots_settings']['print_robots_noindex'] = array(
'#type' => 'checkbox',
'#title' => t('Add noindex'),
'#default_value' => variable_get('print_robots_noindex', PRINT_ROBOTS_NOINDEX_DEFAULT),
'#description' => t('Instruct robots to not index printer-friendly pages. Recommended for good search engine karma.'),
);
$form['settings']['print_robots_settings']['print_robots_nofollow'] = array(
'#type' => 'checkbox',
'#title' => t('Add nofollow'),
'#default_value' => variable_get('print_robots_nofollow', PRINT_ROBOTS_NOFOLLOW_DEFAULT),
'#description' => t('Instruct robots to not follow outgoing links on printer-friendly pages.'),
);
$form['settings']['print_robots_settings']['print_robots_noarchive'] = array(
'#type' => 'checkbox',
'#title' => t('Add noarchive'),
'#default_value' => variable_get('print_robots_noarchive', PRINT_ROBOTS_NOARCHIVE_DEFAULT),
'#description' => t('Non-standard tag to instruct search engines to not show a "Cached" link for your printer-friendly pages. Recognized by Googlebot.'),
);
return system_settings_form($form);
}
/**
* Menu callback for the common print module text strings settings form
*
* @ingroup forms
*/
function print_main_strings_settings() {
drupal_set_message(t("Saving these strings will disable their translation via Drupal's language system. Use the reset button to return them to the original state."), 'warning');
$form['print_main_text'] = array(
'#type' => 'fieldset',
'#title' => t('Text strings'),
);
$form['print_main_text']['print_text_published'] = array(
'#type' => 'textfield',
'#default_value' => variable_get('print_text_published', t('Published on %site_name')),
);
$form['print_main_text']['print_text_source_url'] = array(
'#type' => 'textfield',
'#default_value' => variable_get('print_text_source_url', t('Source URL')),
);
$form['print_main_text']['print_text_retrieved'] = array(
'#type' => 'textfield',
'#default_value' => variable_get('print_text_retrieved', t('retrieved on %date')),
);
$form['print_main_text']['print_text_links'] = array(
'#type' => 'textfield',
'#default_value' => variable_get('print_text_links', t('Links')),
);
return system_settings_form($form);
}
/**
* Menu callback for the printer-friendly version text strings settings form
*
* @ingroup forms
*/
function print_html_strings_settings() {
drupal_set_message(t("Saving these strings will disable their translation via Drupal's language system. Use the reset button to return them to the original state."), 'warning');
$form['print_html_text'] = array(
'#type' => 'fieldset',
'#title' => t('Text strings'),
);
$form['print_html_text']['print_html_link_text'] = array(
'#type' => 'textfield',
'#title' => t('Link text'),
'#default_value' => variable_get('print_html_link_text', t('Printer-friendly version')),
'#description' => t('Text used in the link to the printer-friendly version.'),
);
return system_settings_form($form);
}

View file

@ -0,0 +1,11 @@
name = "Printer-friendly pages"
description = "Adds a printer-friendly version link to content and administrative pages."
core=6.x
package = "Printer, email and PDF versions"
; Information added by Drupal.org packaging script on 2014-04-02
version = "6.x-1.19"
core = "6.x"
project = "print"
datestamp = "1396426748"

View file

@ -0,0 +1,395 @@
<?php
/**
* @file
* Install file of the print module
*
* @ingroup print
*/
/**
* Implementation of hook_install().
*/
function print_install() {
drupal_install_schema('print');
// Module weight
update_sql("UPDATE {system} SET weight = 0 WHERE name = 'print'");
$t = get_t();
drupal_set_message($t('Printer-friendly Page settings are available under !link',
array('!link' => l($t('Administer > Site configuration > Printer-friendly Pages'), 'admin/settings/print'))
));
}
/**
* Implementation of hook_uninstall().
*/
function print_uninstall() {
drupal_uninstall_schema('print');
variable_del('print_settings');
variable_del('print_sourceurl_settings');
variable_del('print_html_settings');
variable_del('print_robot_settings');
variable_del('print_logo_url');
variable_del('print_logo_options');
variable_del('print_css');
variable_del('print_keep_theme_css');
variable_del('print_urls');
variable_del('print_urls_anchors');
variable_del('print_comments');
variable_del('print_newwindow');
variable_del('print_sourceurl_enabled');
variable_del('print_sourceurl_date');
variable_del('print_sourceurl_forcenode');
variable_del('print_html_show_link');
variable_del('print_html_link_pos');
variable_del('print_html_link_teaser');
variable_del('print_html_node_link_visibility');
variable_del('print_html_node_link_pages');
variable_del('print_html_link_class');
variable_del('print_html_sys_link_visibility');
variable_del('print_html_sys_link_pages');
variable_del('print_html_book_link');
variable_del('print_html_new_window');
variable_del('print_html_sendtoprinter');
variable_del('print_html_windowclose');
variable_del('print_display_sys_urllist');
variable_del('print_robots_noindex');
variable_del('print_robots_nofollow');
variable_del('print_robots_noarchive');
variable_del('print_footer_options');
variable_del('print_footer_user');
variable_del('print_html_link_text');
variable_del('print_html_link_use_alias');
variable_del('print_text_links');
variable_del('print_text_published');
variable_del('print_text_retrieved');
variable_del('print_text_source_url');
$settings = db_query("SELECT name FROM {variable} WHERE name LIKE 'print\_display\_%'");
while ($variable = db_fetch_object($settings)) {
variable_del($variable->name);
}
}
/**
* Implementation of hook_schema().
*/
function print_schema() {
$schema['print_node_conf'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'link' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
'comments' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
'url_list' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
),
'primary key' => array('nid'),
);
$schema['print_page_counter'] = array(
'fields' => array(
'path' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
),
'totalcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('path'),
);
return $schema;
}
/**
* Update to version 6.x-1.0
*/
function print_update_6000() {
global $conf;
$ret = array();
$lastversion = drupal_get_installed_schema_version('print');
if (($lastversion >= 5300) && ($lastversion < 6000)) {
return $ret;
}
if (isset($conf['print_settings'])) {
$print_settings = variable_get('print_settings', '');
variable_set('print_logo_options', ($print_settings['logo_url'] ? 2 : 1));
variable_set('print_logo_url', $print_settings['logo_url']);
variable_set('print_css', $print_settings['css']);
variable_set('print_urls', $print_settings['urls']);
variable_set('print_comments', $print_settings['comments']);
variable_set('print_newwindow', $print_settings['newwindow']);
variable_del('print_settings');
}
if (isset($conf['print_sourceurl_settings'])) {
$print_sourceurl_settings = variable_get('print_sourceurl_settings', '');
variable_set('print_sourceurl_enabled', $print_sourceurl_settings['enabled']);
variable_set('print_sourceurl_date', $print_sourceurl_settings['date']);
variable_set('print_sourceurl_forcenode', $print_sourceurl_settings['forcenode']);
variable_del('print_sourceurl_settings');
}
if (isset($conf['print_html_settings'])) {
$print_html_settings = variable_get('print_html_settings', '');
variable_set('print_html_link_pos', array('link' => ($print_html_settings['show_link'] ? 'link' : 0) ));
variable_set('print_html_show_link', max(1, $print_html_settings['show_link']));
variable_set('print_html_node_link_visibility', $print_html_settings['node_link_visibility']);
variable_set('print_html_node_link_pages', $print_html_settings['node_link_pages']);
variable_set('print_html_link_class', $print_html_settings['link_class']);
variable_set('print_html_sys_link_visibility', $print_html_settings['sys_link_visibility']);
variable_set('print_html_sys_link_pages', $print_html_settings['sys_link_pages']);
variable_set('print_html_book_link', $print_html_settings['book_link']);
variable_set('print_html_new_window', $print_html_settings['new_window']);
variable_set('print_html_sendtoprinter', $print_html_settings['sendtoprinter']);
variable_del('print_html_settings');
}
if (isset($conf['print_robot_settings'])) {
$print_robot_settings = variable_get('print_robot_settings', '');
variable_set('print_robots_noindex', $print_robot_settings['noindex']);
variable_set('print_robots_nofollow', $print_robot_settings['nofollow']);
variable_set('print_robots_noarchive', $print_robot_settings['noarchive']);
variable_del('print_robot_settings');
}
return $ret;
}
/**
* Update to version 6.x-1.0
*/
function print_update_6001() {
$ret = array();
$lastversion = drupal_get_installed_schema_version('print');
if (($lastversion >= 5301) && ($lastversion < 6000)) {
return $ret;
}
menu_rebuild();
return $ret;
}
/**
* Update to version 6.x-1.1
*/
function print_update_6002() {
$ret = array();
$lastversion = drupal_get_installed_schema_version('print');
if (($lastversion >= 5302) && ($lastversion < 6000)) {
return $ret;
}
$schema['print_node_conf'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'link' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
'comments' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
'url_list' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
),
'primary key' => array('nid'),
);
$schema['print_page_counter'] = array(
'fields' => array(
'path' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
),
'totalcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('path'),
);
db_create_table($ret, 'print_node_conf', $schema['print_node_conf']);
db_create_table($ret, 'print_page_counter', $schema['print_page_counter']);
return $ret;
}
/**
* Update to version 6.x-1.2
*/
function print_update_6003() {
$ret = array();
$lastversion = drupal_get_installed_schema_version('print');
if (($lastversion >= 5303) && ($lastversion < 6000)) {
return $ret;
}
// Delete custom text strings set to the default
$vars = array(
'print_html_link_text' => 'Printer-friendly version',
'print_text_published' => 'Published on %site_name',
'print_text_by' => 'By %author',
'print_text_created' => 'Created %date',
'print_text_source_url' => 'Source URL',
'print_text_retrieved' => 'retrieved on %date',
'print_text_links' => 'Links',
);
$t = get_t();
foreach ($vars as $name => $default) {
if (variable_get($name, '') == $t($default)) {
variable_del($name);
}
}
menu_rebuild();
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_update_6004() {
$ret = array();
// BLOCK_CACHE_PER_PAGE -> 4
$ret[] = update_sql("UPDATE {blocks} SET cache = 4 WHERE module = 'print' AND delta = '0'");
// BLOCK_CACHE_GLOBAL -> 8
$ret[] = update_sql("UPDATE {blocks} SET cache = 8 WHERE module = 'print' AND delta = '1'");
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_update_6005() {
$ret = array();
// Module weight
$ret[] = update_sql("UPDATE {system} SET weight = 0 WHERE name = 'print'");
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_update_6006() {
global $base_root, $base_path;
$ret = array();
$t = get_t();
$print_css = variable_get('print_css', '');
$pattern = "!(?:${base_root})?${base_path}(.*)!is";
if (preg_match($pattern, strtr($print_css, array('%b' => base_path())), $matches)) {
variable_set('print_css', $matches[1]);
}
elseif (!empty($print_css)) {
drupal_set_message($t('Please review your custom stylesheet path in the !url, as the path must now be relative to the base path of the site.', array('!url' => l($t('print module settings'), 'admin/settings/print/common'))));
}
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_update_6007() {
$ret = array();
foreach (node_get_types() as $key => $value) {
$print_display = variable_get('print_display_'. $value->type, 1);
$print_display_comment = variable_get('print_display_comment_'. $value->type, 0);
$print_display_urllist = variable_get('print_display_urllist_'. $value->type, 1);
$ret[] = update_sql("UPDATE {print_node_conf} SET link = (link AND $print_display), comments = (comments OR $print_display_comment), url_list = (url_list AND $print_display_urllist) WHERE nid IN (SELECT nid FROM {node} WHERE type = '$value->type');");
}
return $ret;
}
/**
* Update to version 6.x-1.13
*/
function print_update_6008() {
$ret = array();
variable_del('print_text_by');
variable_del('print_text_created');
return $ret;
}
/**
* Enable block and help area links
*/
function print_update_6118() {
$ret = array();
$link_pos = variable_get('print_html_link_pos', array('link' => 'link', 'block' => 'block', 'help' => 'help'));
$link_pos['block'] = 'block';
$link_pos['help'] = 'help';
variable_set('print_html_link_pos', $link_pos);
return $ret;
}

View file

@ -0,0 +1,964 @@
<?php
/**
* @defgroup print Printer, email and PDF versions
*
* Welcome to the print module developer's documentation. The interesting
* functions for themers are those that start with 'theme_'.
*
* - Printer-friendly pages
* - @link print.module Module main file @endlink
* - @link print.admin.inc Settings form @endlink
* - @link print.pages.inc HTML generation @endlink
* - @link print.install (Un)Install routines @endlink
* - @link print.tpl.php Page generation template @endlink
* - Send by email
* - @link print_mail.module Module main file @endlink
* - @link print_mail.admin.inc Settings form @endlink
* - @link print_mail.inc Mail form and send mail routine @endlink
* - @link print_mail.install (Un)Install routines @endlink
* - PDF version
* - @link print_pdf.module Module main file @endlink
* - @link print_pdf.admin.inc Settings form @endlink
* - @link print_pdf.pages.inc PDF generation @endlink
* - @link print_pdf.class.inc Auxiliary PHP5 class @endlink
* - @link print_pdf.class_php4.inc Auxiliary PHP4 class @endlink
* - @link print_pdf.install (Un)Install routines @endlink
*/
/**
* @file
* Displays Printer-friendly versions of Drupal pages.
*
* This is the core module of the PF package, with the Drupal hooks
* and other administrative functions.
*
* @ingroup print
*/
define('PRINT_PATH', 'print');
define('PRINT_HTML_FORMAT', 'html');
define('PRINT_LOGO_OPTIONS_DEFAULT', 1);
define('PRINT_LOGO_URL_DEFAULT', '');
define('PRINT_FOOTER_OPTIONS_DEFAULT', 1);
define('PRINT_FOOTER_USER_DEFAULT', '');
define('PRINT_CSS_DEFAULT', '');
define('PRINT_KEEP_THEME_CSS_DEFAULT', 0);
define('PRINT_URLS_DEFAULT', 1);
define('PRINT_URLS_ANCHORS_DEFAULT', 0);
define('PRINT_COMMENTS_DEFAULT', 0);
define('PRINT_NEWWINDOW_DEFAULT', 1);
define('PRINT_HTML_LINK_POS_DEFAULT', serialize(array('link' => 'link', 'block' => 'block', 'help' => 'help')));
define('PRINT_HTML_LINK_TEASER_DEFAULT', 0);
define('PRINT_HTML_SHOW_LINK_DEFAULT', 1);
define('PRINT_HTML_NODE_LINK_VISIBILITY_DEFAULT', 0);
define('PRINT_HTML_NODE_LINK_PAGES_DEFAULT', '');
define('PRINT_HTML_LINK_CLASS_DEFAULT', 'print-page');
define('PRINT_HTML_SYS_LINK_VISIBILITY_DEFAULT', 1);
define('PRINT_HTML_SYS_LINK_PAGES_DEFAULT', '');
define('PRINT_HTML_LINK_USE_ALIAS_DEFAULT', 0);
define('PRINT_HTML_BOOK_LINK_DEFAULT', 1);
define('PRINT_HTML_NEW_WINDOW_DEFAULT', 0);
define('PRINT_HTML_SENDTOPRINTER_DEFAULT', 0);
define('PRINT_HTML_WINDOWCLOSE_DEFAULT', 1);
define('PRINT_SOURCEURL_ENABLED_DEFAULT', 1);
define('PRINT_SOURCEURL_DATE_DEFAULT', 0);
define('PRINT_SOURCEURL_FORCENODE_DEFAULT', 0);
define('PRINT_ROBOTS_NOINDEX_DEFAULT', 1);
define('PRINT_ROBOTS_NOFOLLOW_DEFAULT', 1);
define('PRINT_ROBOTS_NOARCHIVE_DEFAULT', 0);
define('PRINT_TYPE_SHOW_LINK_DEFAULT', 1);
define('PRINT_TYPE_COMMENT_LINK_DEFAULT', 0);
define('PRINT_TYPE_URLLIST_DEFAULT', 1);
define('PRINT_TYPE_SYS_URLLIST_DEFAULT', 0);
define('PRINT_ALLOW_NORMAL_LINK', 1);
define('PRINT_ALLOW_BOOK_LINK', 2);
define('PRINT_TYPE_FIELDS_WEIGHT', 30);
/**
* Implementation of hook_perm().
*/
function print_perm() {
return array('access print', 'administer print', 'node-specific print configuration', 'use PHP for link visibility');
}
/**
* Implementation of hook_theme().
*/
function print_theme() {
return array(
'print_format_link' => array(
'arguments' => array(),
),
'print_node' => array(
'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE, 'type' => PRINT_HTML_FORMAT),
'template' => 'print_node',
),
'print_page' => array(
'arguments' => array('print' => NULL, 'type' => PRINT_HTML_FORMAT, 'node' => NULL),
'template' => 'print',
),
);
}
/**
* Implementation of hook_theme_registry_alter().
*/
function print_theme_registry_alter(&$theme_registry) {
$theme_registry['print_node']['theme paths'] = array_merge($theme_registry['print_node']['theme paths'], $theme_registry['node']['theme paths']);
$theme_registry['print_page']['theme paths'] = array_merge($theme_registry['print_page']['theme paths'], $theme_registry['page']['theme paths']);
}
/**
* Implementation of hook_preprocess_HOOK().
*/
function print_preprocess_print_node(&$variables) {
static $hooks = NULL;
if (!isset($hooks)) {
init_theme();
$hooks = theme_get_registry();
}
// Stolen from theme() so that ALL preprocess functions are called
$info = $hooks['node'];
if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) {
// This construct ensures that we can keep a reference through
// call_user_func_array.
$args = array(&$variables, 'node');
foreach ($info['preprocess functions'] as $preprocess_function) {
if (function_exists($preprocess_function)) {
call_user_func_array($preprocess_function, $args);
}
}
}
$variables += $args[0];
// Include the right template suggestions based on format (print, email) and type.
$format = $variables['type'];
$type = $variables['node']->type;
$variables['template_files'][] = "node";
$variables['template_files'][] = "node-$type";
$variables['template_files'][] = "print_node";
$variables['template_files'][] = "print_node_$format";
$variables['template_files'][] = "print_node_$format.node-$type";
}
/**
* Implementation of hook_preprocess_HOOK().
*/
function print_preprocess_print_page(&$variables) {
static $hooks = NULL;
if (!isset($hooks)) {
init_theme();
$hooks = theme_get_registry();
}
$variables['show_blocks'] = FALSE;
$variables['show_messages'] = FALSE;
// Stolen from theme() so that ALL preprocess functions are called
$info = $hooks['page'];
if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) {
// This construct ensures that we can keep a reference through
// call_user_func_array.
$args = array(&$variables, 'page');
foreach ($info['preprocess functions'] as $preprocess_function) {
if (function_exists($preprocess_function)) {
call_user_func_array($preprocess_function, $args);
}
}
}
$variables += $args[0];
$format = $variables['type'];
$type = (isset($variables['node']->type)) ? $variables['node']->type : '';
$nid = (isset($variables['node']->nid)) ? $variables['node']->nid : '';
$variables['template_files'][] = "print";
$variables['template_files'][] = "print.node-$type";
$variables['template_files'][] = "print.node-$type-$nid";
$variables['template_files'][] = "print_$format";
$variables['template_files'][] = "print_$format.node-$type";
$variables['template_files'][] = "print_$format.node-$type-$nid";
}
/**
* Implementation of hook_menu().
*/
function print_menu() {
$items = array();
$items[PRINT_PATH] = array(
'title' => 'Printer-friendly',
'page callback' => 'print_controller_html',
'access arguments' => array('access print'),
'type' => MENU_CALLBACK,
'file' => 'print.pages.inc',
);
$items[PRINT_PATH .'/'. PRINT_PATH] = array(
'access callback' => FALSE,
);
$items['admin/settings/print'] = array(
'title' => 'Printer, email and PDF versions',
'description' => 'Adds a printer-friendly version link to content and administrative pages.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_html_settings'),
'access arguments' => array('administer print'),
'file' => 'print.admin.inc',
);
$items['admin/settings/print/html'] = array(
'title' => 'Web page',
'weight' => 1,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/print/html/options'] = array(
'title' => 'Options',
'weight' => 1,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/print/html/strings'] = array(
'title' => 'Text strings',
'description' => 'Override the user-facing strings used in the printer-friendly version.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_html_strings_settings'),
'access arguments' => array('administer print'),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
'file' => 'print.admin.inc',
);
$items['admin/settings/print/common'] = array(
'title' => 'Settings',
'description' => 'Settings for the common functionalities for all the print sub-modules.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_main_settings'),
'access arguments' => array('administer print'),
'weight' => 10,
'type' => MENU_LOCAL_TASK,
'file' => 'print.admin.inc',
);
$items['admin/settings/print/common/options'] = array(
'title' => 'Options',
'weight' => 1,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/print/common/strings'] = array(
'title' => 'Text strings',
'description' => 'Override the user-facing strings used by the print module.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_main_strings_settings'),
'access arguments' => array('administer print'),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
'file' => 'print.admin.inc',
);
return $items;
}
/**
* Implementation of hook_block().
*/
function print_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$block[0]['info'] = t('Printer, email and PDF versions');
$block[0]['cache'] = BLOCK_CACHE_PER_PAGE;
$block[1]['info'] = t('Most printed');
$block[1]['cache'] = BLOCK_CACHE_GLOBAL;
return $block;
break;
case 'configure':
return '';
case 'save':
return;
case 'view':
switch ($delta) {
case 0:
$nid = preg_replace('!^node/!', '', $_GET['q']);
if (ctype_digit($nid)) {
$node = node_load($nid);
if (!node_access('view', $node)) {
// If the user doesn't have access to the node, don't show any links
$block['content'] = '';
return;
}
}
else {
$node = NULL;
}
$block['content'] = '';
foreach (array('html' => 'print', 'mail' => 'print_mail', 'pdf' => 'print_pdf') as $format => $module) {
$link_pos = variable_get('print_' . $format . '_link_pos', unserialize(PRINT_HTML_LINK_POS_DEFAULT));
if (!(empty($link_pos['block']))) {
$func = $module . '_insert_link';
if (function_exists($func)) {
$links = $func(NULL, $node);
if (!empty($links)) {
$block['content'] .= $links;
}
}
}
}
break;
case 1:
$block['subject'] = t('Most printed');
$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);
if (db_affected_rows()) {
$block['content'] = '<div class="item-list"><ul>';
while ($obj = db_fetch_object($result)) {
$block['content'] .= '<li>'. l(_print_get_title($obj->path), $obj->path) .'</li>';
}
$block['content'] .= '</ul></div>';
}
break;
}
return $block;
break;
}
}
/**
* Implementation of hook_link().
*/
function print_link($type, $node = NULL, $teaser = FALSE) {
$print_html_link_pos = variable_get('print_html_link_pos', unserialize(PRINT_HTML_LINK_POS_DEFAULT));
$print_html_link_use_alias = variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT);
$allowed_type = print_link_allowed(array('type' => $type, 'node' => $node, 'teaser' => $teaser));
if (($allowed_type === PRINT_ALLOW_NORMAL_LINK) && !isset($node->book) && !empty($print_html_link_pos['link'])) {
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$links = array();
$format = theme('print_format_link');
$query_arr = $_GET;
if ($type == 'comment') {
$query_arr['comment'] = $node->cid;
}
$query = print_query_string_encode($query_arr, array('q'));
if (empty($query)) $query = NULL;
if (($print_html_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/'. $node->nid))) {
$path = $alias;
}
else {
$path = $node->nid;
}
$links['print_html'] = array(
'href' => PRINT_PATH .'/'. $path,
'title' => $format['text'],
'attributes' => $format['attributes'],
'html' => $format['html'],
'query' => $query,
);
return $links;
}
else {
return;
}
}
/**
* Implementation of hook_link_alter().
*/
function print_link_alter(&$links, $node) {
foreach ($links as $module => $link) {
if (strpos($module, 'book_printer') !== FALSE) {
$print_html_book_link = variable_get('print_html_book_link', PRINT_HTML_BOOK_LINK_DEFAULT);
if ($print_html_book_link) {
$print_html_link_pos = variable_get('print_html_link_pos', unserialize(PRINT_HTML_LINK_POS_DEFAULT));
if (!empty($print_html_link_pos['link'])) {
$format = theme('print_format_link');
switch ($print_html_book_link) {
case 1:
$path = $link['href'];
break;
case 2:
$print_html_link_use_alias = variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT);
$path = ($print_html_link_use_alias && isset($node->path)) ? $node->path : $node->nid;
break;
}
$links[$module] = array(
'href' => PRINT_PATH .'/'. $path,
'title' => $format['text'],
'attributes' => $format['attributes'],
'html' => $format['html'],
);
}
else {
unset($links[$module]);
}
}
}
}
}
/**
* Implementation of hook_help().
*/
function print_help($path, $arg) {
switch ($path) {
case 'admin/help#print':
// Return a line-break version of the module README
return filter_filter('process', 1, NULL, file_get_contents(drupal_get_path('module', 'print') .'/README.txt') );
}
$print_html_link_pos = variable_get('print_html_link_pos', unserialize(PRINT_HTML_LINK_POS_DEFAULT));
if (($path !== 'node/%') && !(empty($print_html_link_pos['help']))) {
static $output = FALSE;
if ($output === FALSE) {
$output = TRUE;
$link = print_insert_link();
if ($link) {
return "<span class='print-syslink'>$link</span>";
}
}
}
}
/**
* Implementation of hook_nodeapi().
*/
function print_nodeapi(&$node, $op = 'view', $teaser, $page) {
switch ($op) {
case 'view':
// Insert content corner links
if ((!$teaser) && isset($node->build_mode) && ($node->build_mode === NODE_BUILD_NORMAL)) {
$node->content['print_links'] = array(
'#prefix' => '<span class="print-link">',
'#value' => '',
'#suffix' => '</span>',
'#weight' => -101,
);
$print_html_link_pos = variable_get('print_html_link_pos', unserialize(PRINT_HTML_LINK_POS_DEFAULT));
if (!empty($print_html_link_pos['corner'])) {
$node->content['print_links']['#value'] .= print_insert_link(NULL, $node);
}
}
break;
case 'load':
$res = db_fetch_object(db_query("SELECT link, comments, url_list FROM {print_node_conf} WHERE nid = %d", $node->nid));
$node->print_display = $res ? intval($res->link) : variable_get('print_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$node->print_display_comment = $res ? intval($res->comments) : variable_get('print_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$node->print_display_urllist = $res ? intval($res->url_list) : variable_get('print_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
break;
case 'insert':
case 'update':
if (user_access('administer print') || user_access('node-specific print configuration')) {
if (!isset($node->print_display)) $node->print_display = variable_get('print_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
if (!isset($node->print_display_comment)) $node->print_display_comment = variable_get('print_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
if (!isset($node->print_display_urllist)) $node->print_display_urllist = variable_get('print_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
_print_node_conf_modify($node->nid, $node->print_display, $node->print_display_comment, $node->print_display_urllist);
}
break;
case 'delete':
db_query("DELETE FROM {print_node_conf} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {print_page_counter} WHERE path = 'node/%d'", $node->nid);
break;
}
}
/**
* Implementation of hook_form_alter().
*/
function print_form_alter(&$form, $form_state, $form_id) {
// Add the node-type settings option to activate the printer-friendly version link
if ((user_access('administer print') || user_access('node-specific print configuration')) && (($form_id == 'node_type_form') ||
(isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id))) {
$form['print'] = array(
'#type' => 'fieldset',
'#title' => t('Printer, email and PDF versions'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => (function_exists('content_extra_field_weight') && isset($form['type'])) ? content_extra_field_weight($form['type']['#value'], 'print') : PRINT_TYPE_FIELDS_WEIGHT,
'#group' => 'additional_settings',
);
$form['print']['label'] = array(
'#type' => 'markup',
'#value' => '<p><strong>'. t('Printer-friendly version') .'</strong></p>',
);
$form['print']['print_display'] = array(
'#type' => 'checkbox',
'#title' => t('Show link'),
);
$form['print']['print_display_comment'] = array(
'#type' => 'checkbox',
'#title' => t('Show link in individual comments'),
);
$form['print']['print_display_urllist'] = array(
'#type' => 'checkbox',
'#title' => t('Show Printer-friendly URLs list'),
);
if ($form_id == 'node_type_form') {
$form['print']['print_display']['#default_value'] = variable_get('print_display_'. $form['#node_type']->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$form['print']['print_display_comment']['#default_value'] = variable_get('print_display_comment_'. $form['#node_type']->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$form['print']['print_display_urllist']['#default_value'] = variable_get('print_display_urllist_'. $form['#node_type']->type, PRINT_TYPE_URLLIST_DEFAULT);
}
else {
$node = $form['#node'];
$form['print']['print_display']['#default_value'] = isset($node->print_display) ? $node->print_display : variable_get('print_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$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);
$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);
}
}
}
/**
* Implementation of hook_content_extra_fields().
*/
function print_content_extra_fields($type_name) {
$fields['print'] = array(
'label' => t('Printer, email and PDF versions'),
'description' => t('Print module form.'),
'weight' => PRINT_TYPE_FIELDS_WEIGHT,
);
return $fields;
}
/**
* Implementation of hook_content_build_modes().
*/
function print_content_build_modes() {
return array(
'print' => array(
'title' => t('Print'),
'build modes' => array(
NODE_BUILD_PRINT => array(
'title' => t('Print'),
'views style' => TRUE,
),
),
),
);
}
/**
* Auxiliary function to discover a given page's title
*
* @param $path
* path of the page being identified
* @return
* string with the page's title
*/
function _print_get_title($path) {
$path = drupal_get_normal_path($path);
$nid = preg_replace('!^node/!', '', $path);
if (ctype_digit($nid)) {
$res = db_fetch_object(db_query("SELECT title FROM {node} WHERE nid = %d", $nid));
return $res->title;
}
else {
// Not a node, try to get title from the menu system
$menu_item = menu_get_item($path);
if (!empty($menu_item['title'])) {
return $menu_item['title'];
}
elseif (drupal_substr($menu_item['page_callback'], 0, 6) == 'views_') {
// It's a view, load the view to have access to the title
$view = views_get_view($menu_item['page_arguments']['0']);
return $view->get_title();
}
else {
return NULL;
}
}
}
/**
* Modify the print_node_conf_table
*
* Update the print_node_conf table to reflect the given attributes.
* If updating to the default values, delete the record.
*
* @param $nid
* value of the nid field (primary key)
* @param $link
* value of the link field (0 or 1)
* @param $comments
* value of the comments field (0 or 1)
* @param $url_list
* value of the url_list field (0 or 1)
*/
function _print_node_conf_modify($nid, $link, $comments, $url_list) {
db_query("UPDATE {print_node_conf} SET link = %d, comments = %d, url_list = %d WHERE nid = %d", $link, $comments, $url_list, $nid);
if (!db_affected_rows()) {
@db_query("INSERT INTO {print_node_conf} (nid, link, comments, url_list) VALUES (%d, %d, %d, %d)", $nid, $link, $comments, $url_list);
}
}
/**
* Auxiliary function to fill the Printer-friendly link attributes
*
* @param $title
* text to displayed by the link when hovering over it with the mouse
* @param $class
* class attribute to be used in the link
* @param $new_window
* if TRUE opens the target page in a new window
* @return
* array of formatted attributes
*/
function print_fill_attributes($title = '', $class = '', $new_window = FALSE) {
$print_newwindow = variable_get('print_newwindow', PRINT_NEWWINDOW_DEFAULT);
$print_robots_noindex = variable_get('print_robots_noindex', PRINT_ROBOTS_NOINDEX_DEFAULT);
$attributes = array();
$attributes['title'] = $title;
if (!empty($class)) {
$attributes['class'] = $class;
}
if ($new_window) {
switch ($print_newwindow) {
case 0:
$attributes['target'] = '_blank';
break;
case 1:
$attributes['onclick'] = 'window.open(this.href); return false';
break;
}
}
if (!empty($print_robots_noindex)) {
$attributes['rel'] = 'nofollow';
}
return $attributes;
}
/**
* Auxiliary function to set the link text and html flag
*
* @param $type
* type of link: 0 or 1 for a text-only link, 2 for icon-only and 3 for
* both text and icon
* @param $text
* text to be displayed on the link to the printer-friendly page
* @param $img
* path to the icon file
* @return
* array with the link text and html flag
*/
function _print_format_link_aux($type = 0, $text = '', $img = '') {
if ($type >= 2) {
$html = TRUE;
switch ($type) {
case 2:
$text = theme('image', $img, $text, $text, array('class' => 'print-icon'));
break;
case 3:
$text = theme('image', $img, $text, $text, array('class' => 'print-icon print-icon-margin')) . $text;
break;
}
}
else {
$html = FALSE;
}
return array('text' => $text,
'html' => $html,
);
}
/**
* Format the Printer-friendly link
*
* @return
* array of formatted attributes
* @ingroup themeable
*/
function theme_print_format_link() {
$print_html_link_class = variable_get('print_html_link_class', PRINT_HTML_LINK_CLASS_DEFAULT);
$print_html_new_window = variable_get('print_html_new_window', PRINT_HTML_NEW_WINDOW_DEFAULT);
$print_html_show_link = variable_get('print_html_show_link', PRINT_HTML_SHOW_LINK_DEFAULT);
$print_html_link_text = filter_xss(variable_get('print_html_link_text', t('Printer-friendly version')));
$img = drupal_get_path('module', 'print') .'/icons/print_icon.gif';
$title = t('Display a printer-friendly version of this page.');
$class = strip_tags($print_html_link_class);
$new_window = $print_html_new_window;
$format = _print_format_link_aux($print_html_show_link, $print_html_link_text, $img);
return array('text' => $format['text'],
'html' => $format['html'],
'attributes' => print_fill_attributes($title, $class, $new_window),
);
}
/**
* Auxiliary function to display a formatted Printer-friendly link
*
* Function made available so that developers may call this function from
* their defined pages/blocks.
*
* @param $path
* path of the original page (optional). If not specified, the current URL
* is used
* @param $node
* an optional node object, to be used in defining the path, if used, the
* path argument is irrelevant
* @return
* string with the HTML link to the printer-friendly page
*/
function print_insert_link($path = NULL, $node = NULL) {
if ($node !== NULL) {
$nid = $node->nid;
$path = 'node/'. $nid;
$allowed_type = print_link_allowed(array('node' => $node));
}
else {
if ($path === NULL) {
$nid = preg_replace('!^node/([\d]+)!', '$1', $_GET['q']);
$path = $_GET['q'];
}
else {
$nid = NULL;
}
$allowed_type = print_link_allowed(array('path' => $path));
}
if ($allowed_type) {
if ($nid !== NULL) {
if ($allowed_type === PRINT_ALLOW_BOOK_LINK) {
$path = 'book/export/html/'. $nid;
}
else {
if (variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT) && ($alias = drupal_lookup_path('alias', $path))) {
$path = $alias;
}
else {
$path = $nid;
}
}
$path = PRINT_PATH .'/'. $path;
$query = print_query_string_encode($_GET, array('q'));
if (empty($query)) {
$query = NULL;
}
}
else {
$query = NULL;
}
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$format = theme('print_format_link');
return '<span class="print_html">'. l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) .'</span>';
}
else {
return FALSE;
}
}
/**
* Check if the provided page is enabled according to the visibility settings
*
* @param $visibility
* current visibility settings:
* 0 for show on every page except the listed pages
* 1 for show on only the listed pages
* @param $pages
* list of pages
* @return
* TRUE if it is enabled, FALSE otherwise
*/
function _print_page_match($visibility, $path, $pages) {
if ($pages) {
if ($visibility == 2) {
return drupal_eval($pages);
}
$alias = drupal_get_path_alias($path);
$page_match = drupal_match_path($path, $pages);
if ($alias != $path) {
$page_match = $page_match || drupal_match_path($alias, $pages);
}
return !($visibility xor $page_match);
}
else {
return !$visibility;
}
}
/**
* Check if the link to the PF version is allowed depending on the settings
*
* @param $args
* array containing the possible parameters:
* teaser, node, type, path
* @return
* FALSE if not allowed
* PRINT_ALLOW_NORMAL_LINK if a normal link is allowed
* PRINT_ALLOW_BOOK_LINK if a link is allowed in a book node
*/
function print_link_allowed($args) {
if ((!empty($args['teaser']) && !variable_get('print_html_link_teaser', PRINT_HTML_LINK_TEASER_DEFAULT))
|| !user_access('access print')) {
// If the teaser link is disabled or the user is not allowed
return FALSE;
}
if (!empty($args['path'])) {
$nid = preg_replace('!^node/!', '', drupal_get_normal_path($args['path']));
if (ctype_digit($nid)) {
$args['node'] = node_load($nid);
}
}
if (!empty($args['node'])) {
static $node_type = '';
$node = $args['node'];
if (isset($node->type)) {
$node_type = $node->type;
}
// Node
$print_html_node_link_visibility = variable_get('print_html_node_link_visibility', PRINT_HTML_NODE_LINK_VISIBILITY_DEFAULT);
$print_html_node_link_pages = variable_get('print_html_node_link_pages', PRINT_HTML_NODE_LINK_PAGES_DEFAULT);
if (!_print_page_match($print_html_node_link_visibility, "node/". $node->nid, $print_html_node_link_pages)) {
// Page not in visibility list
return FALSE;
}
elseif (isset($args['type']) && ($args['type'] == 'comment') && isset($node_type)) {
// Link is for a comment, return the configured setting
// Cache this statically to avoid duplicate queries for every comment.
static $res = array();
if (!isset($res[$node->nid])) {
$res[$node->nid] = db_fetch_object(db_query("SELECT comments FROM {print_node_conf} WHERE nid = %d", $node->nid));
}
$print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? intval($res[$node->nid]->comments) : variable_get('print_display_comment_'. $node_type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
if ($print_display_comment) {
return PRINT_ALLOW_NORMAL_LINK;
}
}
else {
// Node link
if (isset($node->print_display) && !$node->print_display) {
// Link for this node is disabled
return FALSE;
}
elseif (isset($node->book)) {
// Node is a book;
$print_html_book_link = variable_get('print_html_book_link', PRINT_HTML_BOOK_LINK_DEFAULT);
switch ($print_html_book_link) {
case 1:
if (user_access('access printer-friendly version')) {
return PRINT_ALLOW_BOOK_LINK;
}
break;
case 2:
return PRINT_ALLOW_NORMAL_LINK;
}
}
else {
return PRINT_ALLOW_NORMAL_LINK;
}
}
}
else {
// 'System' page
$print_html_sys_link_visibility = variable_get('print_html_sys_link_visibility', PRINT_HTML_SYS_LINK_VISIBILITY_DEFAULT);
$print_html_sys_link_pages = variable_get('print_html_sys_link_pages', PRINT_HTML_SYS_LINK_PAGES_DEFAULT);
return _print_page_match($print_html_sys_link_visibility, $_GET['q'], $print_html_sys_link_pages);
}
return FALSE;
}
/**
* Parse an array into a valid urlencoded query string.
*
* Modified from drupal_query_string_encode to prevent re-encoding of
* encoded original.
*
* @param $query
* The array to be processed e.g. $_GET
* @param $exclude
* The array filled with keys to be excluded.
* @return
* urlencoded string which can be appended to/as the URL query string
*/
function print_query_string_encode($query, $exclude = array(), $parent = '') {
$params = array();
foreach ($query as $key => $value) {
if ($parent) {
$key = $parent .'['. $key .']';
}
if (in_array($key, $exclude, TRUE)) {
continue;
}
if (is_array($value)) {
$params[] = print_query_string_encode($value, $exclude, $key);
}
else {
$params[] = $key .'='. rawurlencode($value);
}
}
return implode('&', $params);
}
/**
* Callback function for the preg_replace_callback replacing spaces with %20
*
* Replace spaces in URLs with %20
*
* @param array $matches
* array with the matched tag patterns, usually <a...>+text+</a>
*
* @return string
* tag with re-written URL
*/
function _print_replace_spaces($matches) {
// first, split the html into the different tag attributes
$pattern = '!\s*(\w+\s*=\s*"(?:\\\"|[^"])*")\s*|\s*(\w+\s*=\s*\'(?:\\\\\'|[^\'])*\')\s*|\s*(\w+\s*=\s*\w+)\s*|\s+!';
$attribs = preg_split($pattern, $matches[1], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
foreach ($attribs as $key => $value) {
$attribs[$key] = preg_replace('!(\w)\s*=\s*(.*)!', '$1=$2', $value);
}
$size = count($attribs);
for ($i=1; $i < $size; $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], $urls) > 0) {
$url = trim($urls[1], " \t\n\r\0\x0B\"'");
$new_url = str_replace(' ', '%20', $url);
$matches[1] = str_replace($url, $new_url, $matches[1]);
}
}
$ret = '<' . $matches[1] . '>';
if (count($matches) == 4) {
$ret .= $matches[2] . $matches[3];
}
return $ret;
}
/**
* Implements hook_views_api().
*/
function print_views_api() {
return array(
'api' => 2.0,
'path' => drupal_get_path('module', 'print'),
);
}

View file

@ -0,0 +1,720 @@
<?php
/**
* @file
* Contains the functions to generate Printer-friendly pages.
*
* This file is included by the core PF module, and includes all the
* functions necessary to generate a PF version of the original page
* in HTML format.
*
* @ingroup print
*/
$_print_urls = PRINT_URLS_DEFAULT;
/**
* Generate an HTML version of the printer-friendly page
*
* @see print_controller()
*/
function print_controller_html() {
$args = func_get_args();
$path = filter_xss(implode('/', $args));
$cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;
$print = print_controller($path, $cid, PRINT_HTML_FORMAT);
if ($print !== FALSE) {
$node = $print['node'];
$html = theme('print_page', $print, PRINT_HTML_FORMAT, $node);
$html = drupal_final_markup($html);
print $html;
$nodepath = (isset($node->path) && is_string($node->path)) ? drupal_get_normal_path($node->path) : 'node/'. $path;
db_query("UPDATE {print_page_counter} SET totalcount = totalcount + 1, timestamp = %d WHERE path = '%s'", time(), $nodepath);
// If we affected 0 rows, this is the first time viewing the node.
if (!db_affected_rows()) {
// We must create a new row to store counters for the new node.
db_query("INSERT INTO {print_page_counter} (path, totalcount, timestamp) VALUES ('%s', 1, %d)", $nodepath, time());
}
}
}
/**
* Select the print generator function based on the page type
*
* Depending on the type of node, this functions chooses the appropriate
* generator function.
*
* @param $path
* path of the original page
* @param $cid
* comment ID of the individual comment to be rendered
* @param $format
* format of the page being generated
* @param $teaser
* if set to TRUE, outputs only the node's teaser
* @param $message
* optional sender's message (used by the send email module)
* @return
* array with the fields to be used in the template
* @see _print_generate_node()
* @see _print_generate_path()
* @see _print_generate_book()
*/
function print_controller($path, $cid = NULL, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) {
if (empty($path)) {
// If no path was provided, let's try to generate a page for the referer
global $base_url;
$ref = referer_uri();
$path = preg_replace("!^$base_url/!", '', $ref);
if (($path === $ref) || empty($path)) {
$path = variable_get('site_frontpage', 'node');
}
}
if ($alias = drupal_lookup_path('source', $path)) {
// Indirect call with print/alias
// If there is a path alias with these arguments, generate a printer-friendly version for it
$path = $alias;
}
$parts = explode('/', $path);
if (($parts[0] == 'node') && (count($parts) > 1) && ctype_digit($parts[1])) {
array_shift($parts);
$path = implode('/', $parts);
}
if (ctype_digit($parts[0]) && (count($parts) == 1)) {
$print = _print_generate_node($path, $cid, $format, $teaser, $message);
}
else {
$ret = preg_match('!^book/export/html/(.*)!i', $path, $matches);
if ($ret == 1) {
// This is a book PF page link, handle trough the book handling functions
$print = _print_generate_book($matches[1], $format, $teaser, $message);
}
else {
// If no content node was found, handle the page printing with the 'printable' engine
$print = _print_generate_path($path, $format, $teaser, $message);
}
}
return $print;
}
/**
* Generates a robots meta tag to tell them what they may index
*
* @return
* string with the meta robots tag
*/
function _print_robots_meta_generator() {
$print_robots_noindex = variable_get('print_robots_noindex', PRINT_ROBOTS_NOINDEX_DEFAULT);
$print_robots_nofollow = variable_get('print_robots_nofollow', PRINT_ROBOTS_NOFOLLOW_DEFAULT);
$print_robots_noarchive = variable_get('print_robots_noarchive', PRINT_ROBOTS_NOARCHIVE_DEFAULT);
$robots_meta = array();
if (!empty($print_robots_noindex)) {
$robots_meta[] = 'noindex';
}
if (!empty($print_robots_nofollow)) {
$robots_meta[] = 'nofollow';
}
if (!empty($print_robots_noarchive)) {
$robots_meta[] = 'noarchive';
}
if (count($robots_meta) > 0) {
$robots_meta = implode(', ', $robots_meta);
$robots_meta = "<meta name='robots' content='$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 $message
* optional sender's message (used by the send email module)
* @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, $message = NULL, $cid = NULL) {
global $base_url, $language, $_print_urls;
$path = empty($node->nid) ? $node->path : "node/$node->nid";
// Needed because of the theme_get_setting() calls below
init_theme();
// print module settings
$print_css = variable_get('print_css', PRINT_CSS_DEFAULT);
$print_keep_theme_css = variable_get('print_keep_theme_css', PRINT_KEEP_THEME_CSS_DEFAULT);
$print_logo_options = variable_get('print_logo_options', PRINT_LOGO_OPTIONS_DEFAULT);
$print_logo_url = variable_get('print_logo_url', PRINT_LOGO_URL_DEFAULT);
$print_html_new_window = variable_get('print_html_new_window', PRINT_HTML_NEW_WINDOW_DEFAULT);
$print_html_sendtoprinter = variable_get('print_html_sendtoprinter', PRINT_HTML_SENDTOPRINTER_DEFAULT);
$print_html_windowclose = variable_get('print_html_windowclose', PRINT_HTML_WINDOWCLOSE_DEFAULT);
$print_sourceurl_enabled = variable_get('print_sourceurl_enabled', PRINT_SOURCEURL_ENABLED_DEFAULT);
$print_sourceurl_forcenode = variable_get('print_sourceurl_forcenode', PRINT_SOURCEURL_FORCENODE_DEFAULT);
$print_sourceurl_date = variable_get('print_sourceurl_date', PRINT_SOURCEURL_DATE_DEFAULT);
$print_footer_options = variable_get('print_footer_options', PRINT_FOOTER_OPTIONS_DEFAULT);
$print_footer_user = variable_get('print_footer_user', PRINT_FOOTER_USER_DEFAULT);
$print['language'] = $language->language;
$print['title'] = check_plain($node->title);
$print['head'] = drupal_get_html_head();
if ($print_html_sendtoprinter) {
drupal_add_js('misc/drupal.js', 'core');
}
$print['scripts'] = drupal_get_js();
$print['footer_scripts'] = drupal_get_js('footer');
$print['robots_meta'] = _print_robots_meta_generator();
$print['url'] = url($path, array('absolute' => TRUE));
$print['base_href'] = "<base href='". $print['url'] ."' />\n";
$print['favicon'] = theme_get_setting('toggle_favicon') ? "<link rel='shortcut icon' href='". theme_get_setting('favicon') ."' type='image/x-icon' />\n" : '';
if (!empty($print_css)) {
drupal_add_css(strtr($print_css, array('%t' => drupal_get_path('theme', variable_get('theme_default')))));
}
else {
drupal_add_css(drupal_get_path('module', 'print') .'/css/print.css');
}
$drupal_css = drupal_add_css();
if (!$print_keep_theme_css) {
foreach ($drupal_css as $key => $types) {
// Unset the theme's CSS
$drupal_css[$key]['theme'] = array();
}
}
// If we are sending a message via email, the CSS must be embedded
if (!empty($message)) {
$style = '';
$css_files = array();
foreach ($drupal_css as $types) {
foreach ($types as $values) {
$css_files = array_merge($css_files, array_keys($values));
}
}
foreach ($css_files as $filename) {
$res = file_exists($filename) ? file_get_contents($filename, TRUE) : FALSE;
if ($res != FALSE) {
$style .= $res;
}
}
$print['css'] = "<style type='text/css' media='all'>$style</style>\n";
}
else {
$print['css'] = drupal_get_css($drupal_css);
}
$window_close = ($print_html_new_window && $print_html_windowclose) ? 'window.close();' : '';
$print['sendtoprinter'] = $print_html_sendtoprinter ? '<script type="text/javascript">Drupal.behaviors.print = function(context) {$(window).load(function() {window.print();' . $window_close . '})};</script>' : '';
switch ($print_logo_options) {
case 0: // none
$logo_url = 0;
break;
case 1: // theme's
$logo_url = theme_get_setting('logo');
break;
case 2: // user-specifed
$logo_url = strip_tags($print_logo_url);
break;
}
$logo_url = preg_replace('!^'. base_path() .'!', '', $logo_url);
$site_name = variable_get('site_name', 'Drupal');
$print['logo'] = $logo_url ? theme('image', $logo_url, $site_name, '', array('class' => 'print-logo', 'id' => 'logo'), FALSE) : '';
switch ($print_footer_options) {
case 0: // none
$footer = '';
break;
case 1: // theme's
$footer = variable_get('site_footer', FALSE) ."\n". theme('blocks', 'footer');
break;
case 2: // user-specifed
$footer = $print_footer_user;
break;
}
$print['footer_message'] = filter_xss_admin($footer);
$published_site = variable_get('site_name', 0);
if ($published_site) {
$print_text_published = filter_xss(variable_get('print_text_published', t('Published on %site_name')));
$published = t($print_text_published, array('%site_name' => $published_site));
$print['site_name'] = $published .' ('. l($base_url, $base_url) .')';
}
else {
$print['site_name'] = '';
}
if ($print_sourceurl_enabled == 1) {
/* Grab and format the src URL */
if (empty($print_sourceurl_forcenode)) {
$url = $print['url'];
}
else {
$url = $base_url .'/'. (((bool)variable_get('clean_url', '0')) ? '' : '?q=') . $path;
}
if (is_int($cid)) {
$url .= "#comment-$cid";
}
$retrieved_date = format_date(time(), 'small');
$print_text_retrieved = filter_xss(variable_get('print_text_retrieved', t('retrieved on %date')));
$retrieved = t($print_text_retrieved, array('%date' => $retrieved_date));
$print['printdate'] = $print_sourceurl_date ? " ($retrieved)" : '';
$source_url = filter_xss(variable_get('print_text_source_url', t('Source URL')));
$print['source_url'] = '<strong>'. $source_url . $print['printdate'] .':</strong> '. l($url, $url);
}
else {
$print['source_url'] = '';
}
$print['type'] = (isset($node->type)) ? $node->type : '';
menu_set_active_item($path);
$breadcrumb = drupal_get_breadcrumb();
if (!empty($breadcrumb)) {
$breadcrumb[] = menu_get_active_title();
$print['breadcrumb'] = filter_xss(implode(' > ', $breadcrumb));
}
else {
$print['breadcrumb'] = '';
}
// Display the collected links at the bottom of the page. Code once taken from Kjartan Mannes' project.module
$print['pfp_links'] = '';
if (!empty($_print_urls)) {
$urls = _print_friendly_urls();
$max = count($urls);
$pfp_links = '';
if ($max) {
for ($i = 0; $i < $max; $i++) {
$pfp_links .= '['. ($i + 1) .'] '. check_plain($urls[$i]) ."<br />\n";
}
$links = filter_xss(variable_get('print_text_links', t('Links')));
$print['pfp_links'] = "<p><strong>$links:</strong><br />$pfp_links</p>";
}
}
$print['node'] = $node;
$print['message'] = $message;
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 <a...>+text+</a>
* @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, $_print_urls;
$include_anchors = variable_get('print_urls_anchors', PRINT_URLS_ANCHORS_DEFAULT);
// first, split the html into the different tag attributes
$pattern = '!\s*(\w+\s*=\s*"(?:\\\"|[^"])*")\s*|\s*(\w+\s*=\s*\'(?:\\\\\'|[^\'])*\')\s*|\s*(\w+\s*=\s*\w+)\s*|\s+!';
$attribs = preg_split($pattern, $matches[1], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
foreach ($attribs as $key => $value) {
$attribs[$key] = preg_replace('!(\w)\s*=\s*(.*)!', '$1=$2', $value);
}
$size = count($attribs);
for ($i=1; $i < $size; $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], $urls) > 0) {
$url = trim($urls[1], " \t\n\r\0\x0B\"'");
if (empty($url)) {
// If URL is empty, use current_url
$path = explode('/', $_GET['q']);
unset($path[0]);
$path = implode('/', $path);
if (ctype_digit($path)) {
$path = "node/$path";
}
// Printer-friendly URLs is on, so we need to make it absolute
$newurl = url($path, array('fragment' => drupal_substr($url, 1), 'absolute' => TRUE));
}
elseif (strpos(html_entity_decode($url), '://') || preg_match('!^mailto:.*?@.*?\..*?$!iu', html_entity_decode($url))) {
// URL is absolute, do nothing
$newurl = $url;
}
elseif (strpos(html_entity_decode($url), '//') === 0) {
// URL is 'almost absolute', but it does not contain protocol; replace with base_path protocol
$newurl = (empty($_SERVER['HTTPS']) ? 'http' : 'https') . ":" . $url;
$matches[1] = str_replace($url, $newurl, $matches[1]);
}
else {
if ($url[0] == '#') {
// URL is an anchor tag
if ($include_anchors && (!empty($_print_urls))) {
$path = explode('/', $_GET['q']);
unset($path[0]);
$path = implode('/', $path);
if (ctype_digit($path)) {
$path = "node/$path";
}
// Printer-friendly URLs is on, so we need to make it absolute
$newurl = url($path, array('fragment' => drupal_substr($url, 1), 'absolute' => TRUE));
}
// Because base href is the original page, change the link to
// still be usable inside the print page
$matches[1] = str_replace($url, check_plain(base_path() . $_GET['q'] . $url), $matches[1]);
}
else {
// URL is relative, convert it into absolute URL
if ($url[0] == '/') {
// If it starts with '/' just append it to the server name
$newurl = $base_root .'/'. trim($url, '/');
}
elseif (preg_match('!^(?:index.php)?\?q=!i', $url)) {
// If it starts with ?q=, just prepend with the base URL
$newurl = $base_url .'/'. trim($url, '/');
}
else {
$newurl = rawurldecode(url(trim($url, '/'), array('absolute' => TRUE)));
}
$matches[1] = str_replace($url, $newurl, $matches[1]);
}
}
}
}
$ret = '<'. $matches[1] .'>';
if (count($matches) == 4) {
$ret .= $matches[2] . $matches[3];
if ((!empty($_print_urls)) && (isset($newurl))) {
$ret .= ' <span class="print-footnote">['. _print_friendly_urls(trim($newurl)) .']</span>';
}
}
return filter_xss_admin($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 !== 0) {
$url_idx = array_search($url, $urls);
if ($url_idx !== FALSE) {
return ($url_idx + 1);
}
else {
$urls[] = $url;
return count($urls);
}
}
$ret = $urls;
$urls = array();
return $ret;
}
/**
* Check URL list settings for this node
*
* @param node
* node object
* @param $format
* format of the page being generated
* @return
* TRUE if URL list should be displayed, FALSE otherwise
*/
function _print_url_list_enabled($node, $format = PRINT_HTML_FORMAT) {
if (!isset($node->type)) {
switch ($format) {
case PRINT_HTML_FORMAT:
$node_urllist = variable_get('print_display_sys_urllist', PRINT_TYPE_SYS_URLLIST_DEFAULT);
break;
case PRINT_MAIL_FORMAT:
$node_urllist = variable_get('print_mail_display_sys_urllist', PRINT_TYPE_SYS_URLLIST_DEFAULT);
break;
case PRINT_PDF_FORMAT:
$node_urllist = variable_get('print_pdf_display_sys_urllist', PRINT_TYPE_SYS_URLLIST_DEFAULT);
break;
default:
$node_urllist = PRINT_TYPE_SYS_URLLIST_DEFAULT;
}
}
else {
switch ($format) {
case PRINT_HTML_FORMAT:
$node_urllist = isset($node->print_display_urllist) ? $node->print_display_urllist : variable_get('print_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
break;
case PRINT_MAIL_FORMAT:
$node_urllist = isset($node->print_mail_display_urllist) ? $node->print_mail_display_urllist : variable_get('print_mail_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
break;
case PRINT_PDF_FORMAT:
$node_urllist = isset($node->print_pdf_display_urllist) ? $node->print_pdf_display_urllist : variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
break;
default:
$node_urllist = PRINT_TYPE_URLLIST_DEFAULT;
}
}
// Get value of Printer-friendly URLs setting
return (variable_get('print_urls', PRINT_URLS_DEFAULT) && ($node_urllist));
}
/**
* 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
* @param $format
* format of the page being generated
* @param $teaser
* if set to TRUE, outputs only the node's teaser
* @param $message
* optional sender's message (used by the send email module)
* @return
* filled array ready to be used in the template
*/
function _print_generate_node($nid, $cid = NULL, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) {
global $_print_urls;
// We can take a node id
$node = node_load($nid);
if (!$node) {
// Node not found
drupal_not_found();
return FALSE;
}
elseif (!node_access('view', $node)) {
// Access is denied
drupal_access_denied();
return FALSE;
}
drupal_set_title(check_plain($node->title));
// alert other modules that we are generating a printer-friendly page, so they can choose to show/hide info
$node->printing = TRUE;
// use the proper build_mode
$node->build_mode = NODE_BUILD_PRINT;
// Turn off Pagination by the Paging module
unset($node->pages);
unset($node->page_count);
// Make this page a member of the original page's organic group
if (function_exists('og_set_group_context') && isset($node->og_groups)) {
og_set_group_context($node->og_groups);
}
if ($cid === NULL) {
// Adapted (simplified) version of node_view
// Render the node content
$node = node_build_content($node, $teaser, TRUE);
// Disable fivestar widget output
unset($node->content['fivestar_widget']);
// Disable service links module output
unset($node->content['service_links']);
$content = drupal_render($node->content);
// Disable the AdSense module ads
$content = preg_replace('!<div class=[\'"]adsense[\'"].*?</div>!sim', '', $content);
if ($teaser) {
$node->teaser = $content;
unset($node->body);
}
else {
$node->body = $content;
unset($node->teaser);
}
}
$print_comments = variable_get('print_comments', PRINT_COMMENTS_DEFAULT);
if (function_exists('comment_render') && (($cid != NULL) || ($print_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.*?id="comment-.*?">.*?</form>!sim', '', $comments);
// Remove the 'Post new comment' title
$comments = preg_replace('!<h2.*?>'. t('Post new comment') .'</h2>!', '', $comments);
// Remove the comment title hyperlink
$comments = preg_replace('!(<h3.*?>.*?)<a.*?>(.*?)</a>(.*?</h3>)!i', '$1$2$3', $comments);
// Remove the comment author link
$pattern = '!(<(?:span|div) class="submitted">.*?)<a.*?>(.*?)</a>(.*?</(?:span|div)>)!sim';
if (preg_match($pattern, $comments)) {
$comments = preg_replace($pattern , '$1$2$3', $comments);
}
// Remove the comment links
$comments = preg_replace('!\s*<ul class="links">.*?</ul>!sim', '', $comments);
if ($cid != NULL) {
// Single comment requested, output only the comment
unset($node->body);
}
$node->body .= $comments;
}
node_invoke_nodeapi($node, 'alter', $teaser, TRUE);
$content = theme('print_node', $node, $teaser, TRUE, $format);
if ($teaser) {
$content = $node->teaser;
}
// Check URL list settings
$_print_urls = _print_url_list_enabled($node, $format);
// Convert the a href elements
$pattern = '!<(a\s[^>]*?)>(.*?)(</a>)!is';
$content = preg_replace_callback($pattern, '_print_rewrite_urls', $content);
$print = _print_var_generator($node, $message, $cid);
$print['content'] = $content;
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
* @param $format
* format of the page being generated
* @param $teaser
* if set to TRUE, outputs only the node's teaser
* @param $message
* optional sender's message (used by the send email module)
* @return
* filled array ready to be used in the template
*/
function _print_generate_path($path, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) {
global $_print_urls;
// Handle node tabs
$parts = explode('/', $path);
if (ctype_digit($parts[0]) && (count($parts) > 1)) {
$path = 'node/'. $path;
}
$path = drupal_get_normal_path($path);
menu_set_active_item($path);
// Adapted from index.php.
$node = new stdClass();
$node->body = menu_execute_active_handler($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 FALSE;
}
if (is_int($node->body)) {
switch ($node->body) {
case MENU_NOT_FOUND:
drupal_not_found();
return FALSE;
break;
case MENU_ACCESS_DENIED:
drupal_access_denied();
return FALSE;
break;
}
}
$node->title = drupal_get_title();
$node->path = $path;
// Delete any links area
$node->body = preg_replace('!\s*<div class="links">.*?</div>!sim', '', $node->body);
// Check URL list settings
$_print_urls = _print_url_list_enabled($node, $format);
// Convert the a href elements
$pattern = '!<(a\s[^>]*?)>(.*?)(</a>)!is';
$node->body = preg_replace_callback($pattern, '_print_rewrite_urls', $node->body);
$print = _print_var_generator($node, $message);
$print['content'] = $node->body;
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
* @param $format
* format of the page being generated
* @param $teaser
* if set to TRUE, outputs only the node's teaser
* @param $message
* optional sender's message (used by the send email module)
* @return
* filled array ready to be used in the template
*/
function _print_generate_book($nid, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) {
global $_print_urls;
$node = node_load($nid);
if (!$node) {
// Node not found
drupal_not_found();
return FALSE;
}
elseif (!node_access('view', $node) || (!user_access('access printer-friendly version'))) {
// Access is denied
drupal_access_denied();
return FALSE;
}
$tree = book_menu_subtree_data($node->book);
$node->body = book_export_traverse($tree, 'book_node_export');
// Check URL list settings
$_print_urls = _print_url_list_enabled($node, $format);
// Convert the a href elements
$pattern = '!<(a\s[^>]*?)>(.*?)(</a>)!is';
$node->body = preg_replace_callback($pattern, '_print_rewrite_urls', $node->body);
$print = _print_var_generator($node, $message);
$print['content'] = $node->body;
// The title is already displayed by the book_recurse, so avoid duplication
$print['title'] = '';
return $print;
}

View file

@ -0,0 +1,39 @@
<?php
/**
* @file
* Default print module template
*
* @ingroup print
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $print['language']; ?>" xml:lang="<?php print $print['language']; ?>">
<head>
<?php print $print['head']; ?>
<?php print $print['base_href']; ?>
<title><?php print $print['title']; ?></title>
<?php print $print['scripts']; ?>
<?php print $print['sendtoprinter']; ?>
<?php print $print['robots_meta']; ?>
<?php print $print['favicon']; ?>
<?php print $print['css']; ?>
</head>
<body>
<?php if (!empty($print['message'])) {
print '<div class="print-message">'. $print['message'] .'</div><p />';
} ?>
<div class="print-logo"><?php print $print['logo']; ?></div>
<div class="print-site_name"><?php print $print['site_name']; ?></div>
<p />
<div class="print-breadcrumb"><?php print $print['breadcrumb']; ?></div>
<hr class="print-hr" />
<h1 class="print-title"><?php print $print['title']; ?></h1>
<div class="print-content"><?php print $print['content']; ?></div>
<div class="print-footer"><?php print $print['footer_message']; ?></div>
<hr class="print-hr print-source-and-links" />
<div class="print-source_url"><?php print $print['source_url']; ?></div>
<div class="print-links"><?php print $print['pfp_links']; ?></div>
<?php print $print['footer_scripts']; ?>
</body>
</html>

View file

@ -0,0 +1,125 @@
<?php
/**
* @file
* Printer-friendly version Views integration
*
* @ingroup print
*/
// Views join handlers aren't truly handlers according to [#540128]
// so they need to be specifically included here.
module_load_include('inc', 'print', 'print_join_page_counter');
/**
* Implements hook_views_data().
*/
function print_views_data() {
// The 'group' index will be used as a prefix in the UI for any of this
// table's fields, sort criteria, etc. so it's easy to tell where they came
// from.
$data['print_node_conf']['table']['group'] = t('Printer-friendly version');
$data['print_page_counter']['table']['group'] = t('Printer-friendly version');
// This table references the {node} table. The declaration below creates an
// 'implicit' relationship to the node table, so that when 'node' is the base
// table, the fields are automatically available.
$data['print_node_conf']['table']['join']['node'] = array(
// 'left_field' is the primary key in the referenced table.
// 'field' is the foreign key in this table.
'left_field' => 'nid',
'field' => 'nid',
// 'type' => 'INNER',
);
$data['print_page_counter']['table']['join']['node'] = array(
// 'left_field' is the primary key in the referenced table.
// 'field' is the foreign key in this table.
'left_field' => 'nid',
'field' => 'path',
// 'type' => 'INNER',
'handler' => 'print_join_page_counter',
);
// print_node_conf fields
$data['print_node_conf']['link'] = array(
'title' => t('Web: Show link'),
'help' => t('Whether to show the printer-friendly version link.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
$data['print_node_conf']['comments'] = array(
'title' => t('Web: Show link in individual comments'),
'help' => t('Whether to show the printer-friendly version link in individual comments.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
$data['print_node_conf']['url_list'] = array(
'title' => t('Web: Show Printer-friendly URLs list'),
'help' => t('Whether to show the URL list.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
// print_page_counter fields
$data['print_page_counter']['totalcount'] = array(
'title' => t('Web: Number of page accesses'),
'help' => t('Counter of accesses to the printer-friendly version for this node.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
);
$data['print_page_counter']['timestamp'] = array(
'title' => t('Web: Last access'),
'help' => t("The date of the last access to the node's printer-friendly version."),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
return $data;
}

View file

@ -0,0 +1,23 @@
<?php
/**
* @file
* Custom Views integration join for the page counters
*
* @ingroup print
*/
class print_join_page_counter extends views_join {
// PHP 4 doesn't call constructors of the base class automatically from a
// constructor of a derived class. It is your responsibility to propagate
// the call to constructors upstream where appropriate.
function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT') {
parent::construct($table, $left_table, $left_field, $field, $extra, $type);
}
function join($table, &$query) {
$this->left_field = "CONCAT('node/', $this->left_table.$this->left_field)";
$this->left_table = NULL;
return parent::join($table, $query);
}
}

View file

@ -0,0 +1,249 @@
<?php
/**
* @file
* Contains the administrative functions of the send by email module.
*
* This file is included by the send by email module, and includes the
* settings form.
*
* @ingroup print
*/
// Include MIME library
@include_once('Mail/mime.php');
/**
* Menu callback for the send by email module settings form.
*
* @ingroup forms
*/
function print_mail_settings() {
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Send by email options'),
);
$form['settings']['print_mail_link_pos'] = array(
'#type' => 'checkboxes',
'#title' => t('Send by email link'),
'#default_value' => variable_get('print_mail_link_pos', unserialize(PRINT_MAIL_LINK_POS_DEFAULT)),
'#options' => array('link' => t('Links area'), 'corner' => t('Content corner'), 'block' => t('Block'), 'help' => t('Help area')),
'#description' => t('Choose the location of the link(s) to the send by email page. The Links area is usually below the node content, whereas the Content corner is placed in the upper-right corner of the node content. Unselect all options to disable the link. Even if the link is disabled, you can still send a node by email by going to !path/nid where nid is the numeric id of the node.', array('!path' => PRINTMAIL_PATH)),
);
$form['settings']['print_mail_link_teaser'] = array(
'#type' => 'checkbox',
'#title' => t('Display send by email link in teaser'),
'#default_value' => variable_get('print_mail_link_teaser', PRINT_MAIL_LINK_TEASER_DEFAULT),
'#description' => t('Enabling this will display the link in teaser mode.'),
);
$form['settings']['adv_link'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced link options'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['settings']['adv_link']['print_mail_show_link'] = array(
'#type' => 'radios',
'#title' => t('Link style'),
'#default_value' => variable_get('print_mail_show_link', PRINT_MAIL_SHOW_LINK_DEFAULT),
'#options' => array(1 => t('Text only'), 2 => t('Icon only'), 3 => t('Icon and Text')),
'#description' => t('Select the visual style of the link.'),
);
$form['settings']['adv_link']['print_mail_link_use_alias'] = array(
'#type' => 'checkbox',
'#title' => t('Use URL alias instead of node ID'),
'#default_value' => variable_get('print_mail_link_use_alias', PRINT_MAIL_LINK_USE_ALIAS_DEFAULT),
'#description' => t('Enabling this will create the link using the URL alias instead of the node ID.'),
);
$form['settings']['adv_link']['print_mail_link_class'] = array(
'#type' => 'textfield',
'#title' => t('Link class'),
'#default_value' => variable_get('print_mail_link_class', PRINT_MAIL_LINK_CLASS_DEFAULT),
'#size' => 60,
'#maxlength' => 250,
'#description' => t('This can be used by themers to change the link style or by jQuery modules to open in a new window (e.g. greybox or thickbox). Multiple classes can be specified, separated by spaces.'),
);
$form['settings']['adv_link']['print_mail_node_link_visibility'] = array(
'#type' => 'radios',
'#title' => t('Link visibility'),
'#default_value' => variable_get('print_mail_node_link_visibility', PRINT_MAIL_NODE_LINK_VISIBILITY_DEFAULT),
'#options' => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.')),
);
$form['settings']['adv_link']['print_mail_node_link_pages'] = array(
'#type' => 'textarea',
'#default_value' => variable_get('print_mail_node_link_pages', PRINT_MAIL_NODE_LINK_PAGES_DEFAULT),
'#rows' => 3,
'#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>')),
'#wysiwyg' => FALSE,
);
$access = user_access('use PHP for link visibility');
if ($form['settings']['adv_link']['print_mail_node_link_visibility']['#default_value'] == 2 && !$access) {
$form['settings']['adv_link']['print_mail_node_link_visibility'] = array('#type' => 'value', '#value' => 2);
$form['settings']['adv_link']['print_mail_node_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_mail_node_link_pages']['#default_value']);
}
elseif ($access) {
$form['settings']['adv_link']['print_mail_node_link_visibility']['#options'][] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$form['settings']['adv_link']['print_mail_node_link_pages']['#description'] .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
}
$form['settings']['adv_link']['print_mail_sys_link_visibility'] = array(
'#type' => 'radios',
'#title' => t('Show link in system (non-content) pages'),
'#description' => 'Any page that is not a Drupal node. Usually pages generated by Drupal or a module such as Views or Panels.',
'#default_value' => variable_get('print_mail_sys_link_visibility', PRINT_MAIL_SYS_LINK_VISIBILITY_DEFAULT),
'#options' => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.')),
);
$form['settings']['adv_link']['print_mail_sys_link_pages'] = array(
'#type' => 'textarea',
'#default_value' => variable_get('print_mail_sys_link_pages', PRINT_MAIL_SYS_LINK_PAGES_DEFAULT),
'#rows' => 3,
'#description' => t('Setting this option will add a send by email link on pages created by Drupal or the enabled modules.') .'<br />'.
t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>')),
'#wysiwyg' => FALSE,
);
if ($form['settings']['adv_link']['print_mail_sys_link_visibility']['#default_value'] == 2 && !$access) {
$form['settings']['adv_link']['print_mail_sys_link_visibility'] = array('#type' => 'value', '#value' => 2);
$form['settings']['adv_link']['print_mail_sys_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_mail_sys_link_pages']['#default_value']);
}
elseif ($access) {
$form['settings']['adv_link']['print_mail_sys_link_visibility']['#options'][] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$form['settings']['adv_link']['print_mail_sys_link_pages']['#description'] .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
}
$form['settings']['adv_link']['print_mail_book_link'] = array(
'#type' => 'radios',
'#title' => t('Link in book hierarchy nodes'),
'#default_value' => variable_get('print_mail_book_link', PRINT_MAIL_BOOK_LINK_DEFAULT),
'#options' => array(t('No link'), t('Current page and sub-pages'), t('Current page only')),
);
$form['settings']['print_mail_hourly_threshold'] = array(
'#type' => 'select',
'#title' => t('Hourly threshold'),
'#default_value' => variable_get('print_mail_hourly_threshold', PRINT_MAIL_HOURLY_THRESHOLD),
'#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50)),
'#description' => t('The maximum number of emails a user can send per hour.'),
);
$form['settings']['print_mail_use_reply_to'] = array(
'#type' => 'checkbox',
'#title' => t('Use Reply-To header'),
'#default_value' => variable_get('print_mail_use_reply_to', PRINT_MAIL_USE_REPLY_TO),
'#description' => t("When enabled, any email sent will use the provided user and username in the 'Reply-To' header, with the site's email address used in the 'From' header (configured in !link). Enabling this helps in preventing email being flagged as spam.", array('!link' => l(t('Site information'), 'admin/config/system/site-information'))),
);
$form['settings']['print_mail_teaser_default'] = array(
'#type' => 'checkbox',
'#title' => t('Send only the teaser'),
'#default_value' => variable_get('print_mail_teaser_default', PRINT_MAIL_TEASER_DEFAULT_DEFAULT),
'#description' => t("If selected, the default choice will be to send only the node's teaser instead of the full content."),
);
$form['settings']['print_mail_teaser_choice'] = array(
'#type' => 'checkbox',
'#title' => t('Enable teaser/full mode choice'),
'#default_value' => variable_get('print_mail_teaser_choice', PRINT_MAIL_TEASER_CHOICE_DEFAULT),
'#description' => t('If checked, the user will be able to choose between sending the full content or only the teaser at send time.'),
);
$form['settings']['print_mail_send_option_default'] = array(
'#type' => 'select',
'#title' => t('Default email sending format'),
'#default_value' => variable_get('print_mail_send_option_default', PRINT_MAIL_SEND_OPTION_DEFAULT),
'#options' => array(
'sendlink' => t('Link'),
'sendpage' => t('Inline HTML'),
),
);
if (class_exists('Mail_mime')) {
$form['settings']['print_mail_send_option_default']['#options']['inline-attachment'] = t('Inline HTML with Attachment');
$form['settings']['print_mail_send_option_default']['#options']['plain-attachment'] = t('Plain Text with Attachment');
}
if (module_exists('job_queue')) {
$form['settings']['print_mail_job_queue'] = array(
'#type' => 'checkbox',
'#title' => t('Send emails using Job Queue'),
'#default_value' => variable_get('print_mail_job_queue', PRINT_MAIL_JOB_QUEUE_DEFAULT),
'#description' => t("Selecting this option, email delivery will be performed by the Job Queue module during each cron run. Leaving this unselected, the email will be sent immediately, but the site will take slightly longer to reply to the user."),
);
}
$form['settings']['print_mail_display_sys_urllist'] = array(
'#type' => 'checkbox',
'#title' => t('Printer-friendly URLs list in system pages'),
'#default_value' => variable_get('print_mail_display_sys_urllist', PRINT_TYPE_SYS_URLLIST_DEFAULT),
'#description' => t('Enabling this option will display a list of printer-friendly destination URLs at the bottom of the page.'),
);
return system_settings_form($form);
}
/**
* Menu callback for the send by email module text strings settings form.
*
* @ingroup forms
*/
function print_mail_strings_settings() {
drupal_set_message(t("Saving these strings will disable their translation via Drupal's language system. Use the reset button to return them to the original state."), 'warning', FALSE);
$form['print_mail_text'] = array(
'#type' => 'fieldset',
'#title' => t('Text strings'),
);
$form['print_mail_text']['print_mail_link_text'] = array(
'#type' => 'textfield',
'#title' => t('Link text'),
'#default_value' => variable_get('print_mail_link_text', t('Send by email')),
'#description' => t('Text used in the link to the send by-email form.'),
);
$form['print_mail_text']['print_mail_text_title'] = array(
'#type' => 'textfield',
'#title' => t('Form page title'),
'#default_value' => variable_get('print_mail_text_title', t('Send page by email')),
'#description' => t("Text used as the page title of the mail submission form. Requires a menu rebuild to apply."),
);
$form['print_mail_text']['print_mail_text_subject'] = array(
'#type' => 'textfield',
'#title' => t('Message subject'),
'#default_value' => variable_get('print_mail_text_subject', t('!user has sent you a message from !site')),
'#description' => t("email subject line. The sender's name will appear in place of !user in the subject. The web site name will be inserted in place of !site. The page title replaces !title."),
);
$form['print_mail_text']['print_mail_text_message'] = array(
'#type' => 'textarea',
'#title' => t('Message preamble'),
'#default_value' => variable_get('print_mail_text_message', t('Message from sender')),
'#description' => t('email message preamble. The sender will be able to add their own message after this.'),
'#wysiwyg' => FALSE,
);
$form['print_mail_text']['print_mail_text_content'] = array(
'#type' => 'textarea',
'#title' => t('Message content'),
'#default_value' => variable_get('print_mail_text_content', ''),
'#description' => t('Set the default contents of the message.'),
'#wysiwyg' => FALSE,
);
$form['print_mail_text']['print_mail_text_confirmation'] = array(
'#type' => 'textfield',
'#title' => t('Thank you message'),
'#default_value' => variable_get('print_mail_text_confirmation', t('Thank you for spreading the word about !site.')),
'#description' => t('This message will be displayed after the user successfully submits the form.'),
'#wysiwyg' => FALSE,
);
return system_settings_form($form);
}

View file

@ -0,0 +1,426 @@
<?php
/**
* @file
* Displays and processes the mail send form.
*
* This file is included by the print_mail module and includes the
* mail form display, validation and submit hooks.
*
* @ingroup print
*/
require_once(drupal_get_path('module', 'print') .'/print.pages.inc');
// Include MIME library
@include_once('Mail/mime.php');
/**
* Menu callback for the send by email form.
*
* @ingroup forms
*/
function print_mail_form($form_state) {
global $user;
// Remove the printmail/ prefix
$path_arr = explode('/', $_GET['q']);
unset($path_arr[0]);
$path = filter_xss(implode('/', $path_arr));
if (empty($path)) {
// If no path was provided, let's try to generate a page for the referer
global $base_url;
$ref = referer_uri();
$path = preg_replace("!^$base_url/!", '', $ref);
if (($path === $ref) || empty($path)) {
$path = variable_get('site_frontpage', 'node');
}
drupal_goto(PRINTMAIL_PATH . '/' . $path);
}
elseif (ctype_digit($path_arr[1])) {
if (drupal_lookup_path('source', $path)) {
// This is a numeric alias
$path = drupal_get_normal_path($path);
}
else {
// normal nid
$path = 'node/' . $path;
}
}
else {
$path = drupal_get_normal_path($path);
}
$print_mail_hourly_threshold = variable_get('print_mail_hourly_threshold', PRINT_MAIL_HOURLY_THRESHOLD);
if ((!user_access('send unlimited emails')) && (!flood_is_allowed('print_mail', $print_mail_hourly_threshold))) {
$form['flood'] = array(
'#type' => 'markup',
'#value' => '<p>'. format_plural($print_mail_hourly_threshold, 'You cannot send more than 1 message per hour. Please try again later.', 'You cannot send more than @count messages per hour. Please try again later.') . '</p>',
);
return $form;
}
$print_mail_teaser_default = variable_get('print_mail_teaser_default', PRINT_MAIL_TEASER_DEFAULT_DEFAULT);
$print_mail_teaser_choice = variable_get('print_mail_teaser_choice', PRINT_MAIL_TEASER_CHOICE_DEFAULT);
$form = array();
$cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;
$title = _print_get_title($path);
if (count($form_state['post']) == 0) {
$nodepath = drupal_get_normal_path($path);
db_query("UPDATE {print_mail_page_counter} SET totalcount = totalcount + 1, timestamp = %d WHERE path = '%s'", time(), $nodepath);
// If we affected 0 rows, this is the first time viewing the node.
if (!db_affected_rows()) {
// We must create a new row to store counters for the new node.
db_query("INSERT INTO {print_mail_page_counter} (path, totalcount, timestamp) VALUES ('%s', 1, %d)", $nodepath, time());
}
}
$form['path'] = array('#type' => 'value', '#value' => $path);
$form['cid'] = array('#type' => 'value', '#value' => $cid);
$form['title'] = array('#type' => 'value', '#value' => $title);
$form['fld_from_addr'] = array(
'#type' => 'textfield',
'#title' => t('Your email'),
'#size' => 62,
'#required' => TRUE,
);
$form['fld_from_name'] = array(
'#type' => 'textfield',
'#title' => t('Your name'),
'#size' => 62,
);
$form['txt_to_addrs'] = array(
'#type' => 'textarea',
'#title' => t('Send to'),
'#rows' => 3,
'#resizable' => FALSE,
'#description' => t('Enter multiple addresses separated by commas and/or different lines.'),
'#required' => TRUE,
'#wysiwyg' => FALSE,
);
$form['fld_subject'] = array(
'#type' => 'textfield',
'#title' => t('Subject'),
'#size' => 62,
'#required' => TRUE,
);
if (!empty($title)) {
// To prevent useless translation strings, try to translate only non-node titles
if (drupal_substr($path, 0, 5) != 'node/') {
$title = t($title);
}
$form['fld_title'] = array(
'#type' => 'item',
'#title' => t('Page to be sent'),
'#value' => '<span id="sent-title">'. l($title, $path, array('attributes' => array('title' => t('View page')))) .'</span>',
'#id' => 'sent-title',
);
}
$form['txt_message'] = array(
'#type' => 'textarea',
'#title' => t('Your message'),
'#rows' => 6,
'#required' => TRUE,
'#wysiwyg' => FALSE,
);
if ($print_mail_teaser_choice) {
$form['chk_teaser'] = array(
'#type' => 'checkbox',
'#title' => t('Send only the teaser'),
'#default_value' => $print_mail_teaser_default,
);
}
else {
$form['chk_teaser'] = array('#type' => 'value', '#value' => $print_mail_teaser_default);
}
$form['btn_submit'] = array(
'#name' => 'submit',
'#type' => 'submit',
'#value' => t('Send email'),
);
$form['btn_cancel'] = array(
'#name' => 'cancel',
'#type' => 'submit',
'#value' => t('Cancel'),
);
if ($user->uid != 0) {
$user_name = check_plain(strip_tags(theme('username', $user)));
$form['fld_from_addr']['#default_value'] = $user->mail;
$form['fld_from_addr']['#disabled'] = TRUE;
$form['fld_from_addr']['#value'] = $user->mail;
$form['fld_from_name']['#default_value'] = $user_name;
}
else {
$user_name = t('Someone');
}
$site_name = variable_get('site_name', t('an interesting site'));
$print_mail_text_subject = filter_xss(variable_get('print_mail_text_subject', t('!user has sent you a message from !site')));
$form['fld_subject']['#default_value'] = t($print_mail_text_subject, array('!user' => $user_name, '!site' => $site_name, '!title' => $title));
$print_mail_text_content = filter_xss(variable_get('print_mail_text_content', ''));
$form['txt_message']['#default_value'] = t($print_mail_text_content);
return $form;
}
/**
* Theme function for the send by-email form submission.
*
* Adds a class to the form labels. This class is used to place the label on
* the left of the input fields.
*
* @ingroup forms
*/
function theme_print_mail_form($form) {
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$content = '';
foreach (element_children($form) as $key) {
$tmp = drupal_render($form[$key]);
switch ($key) {
case 'fld_from_addr':
case 'fld_from_name':
case 'txt_to_addrs':
case 'fld_subject':
case 'fld_title':
$tmp = str_replace('<label', '<label class ="printmail-label"', $tmp);
break;
}
$content .= $tmp;
}
return $content;
}
/**
* Validate the send by-email form submission.
*
* @ingroup forms
*/
function print_mail_form_validate($form, &$form_state) {
if (array_key_exists('cancel', $form['#post'])) {
form_set_error(NULL, '', TRUE);
drupal_get_messages('error');
return;
}
$from_addr = trim($form_state['values']['fld_from_addr']);
$test = user_validate_mail($from_addr);
if ($test) {
form_set_error('fld_from_addr', $test);
}
// All new-lines are replaced by commas
$to_addrs = preg_replace('![\r|\n|,]+!', ',', trim($form_state['values']['txt_to_addrs']));
// Create an array from the string
$to_array = explode(',', $to_addrs);
// Verify each element of the array
foreach ($to_array as $key => $address) {
$address = trim($address);
if (preg_match('/(.*?) <(.*)>/s', $address, $matches)) {
// Address is of the type User Name <user@domain.tld>
$test = user_validate_mail($matches[2]);
$to_array[$key] = trim($matches[1]) .' <'. $matches[2] .'>';
}
else {
// Address must be user@domain.tld
$test = user_validate_mail($address);
}
if ($test) {
form_set_error('txt_to_addrs', $test);
}
}
$print_mail_hourly_threshold = variable_get('print_mail_hourly_threshold', PRINT_MAIL_HOURLY_THRESHOLD);
if ((!user_access('send unlimited emails')) && (!flood_is_allowed('print_mail', $print_mail_hourly_threshold - count($to_array) + 1))) {
form_set_error('txt_to_addrs', t('You cannot send more than %number messages per hour. Please reduce the number of recipients.', array('%number' => $print_mail_hourly_threshold)));
}
// In all fields, prevent insertion of custom headers
foreach ($form_state['values'] as $key => $string) {
if ( (drupal_substr($key, 0, 4) == 'fld_') && ((strpos($string, "\n") !== FALSE) || (strpos($string, "\r") !== FALSE)) ) {
form_set_error($key, 'Found invalid character');
}
}
$form_state['values']['fld_from_addr'] = $from_addr;
$form_state['values']['fld_from_name'] = trim($form_state['values']['fld_from_name']);
// Re-create the string from the re-organized array
$form_state['values']['txt_to_addrs'] = implode(', ', $to_array);
}
/**
* Process the send by-email form submission.
*
* @ingroup forms
*/
function print_mail_form_submit($form, &$form_state) {
if (!array_key_exists('cancel', $form_state['values'])) {
$cid = isset($form_state['values']['cid']) ? $form_state['values']['cid'] : NULL;
$print_mail_text_message = filter_xss_admin(variable_get('print_mail_text_message', t('Message from sender')));
$sender_message = $print_mail_text_message .':<br /><br /><em>'. nl2br(check_plain($form_state['values']['txt_message'])) .'</em>';
$print = print_controller($form_state['values']['path'], $cid, PRINT_MAIL_FORMAT, $form_state['values']['chk_teaser'], $sender_message);
if ($print !== FALSE) {
$print_mail_send_option_default = variable_get('print_mail_send_option_default', PRINT_MAIL_SEND_OPTION_DEFAULT);
$params = array();
$params['subject'] = $form_state['values']['fld_subject'];
$params['message'] = $sender_message;
$params['link'] = $print['url'];
$params['title'] = $form_state['values']['title'];
// If a name is provided, make From: in the format Common Name <address>
if (!empty($form_state['values']['fld_from_name'])) {
$from = '"' . mime_header_encode($form_state['values']['fld_from_name']) . '" <' . $form_state['values']['fld_from_addr'] . '>';
}
else {
$from = $form_state['values']['fld_from_addr'];
}
// If using reply-to, move the From: info to the params array, so that it is passed to hook_mail later
if (variable_get('print_mail_use_reply_to', PRINT_MAIL_USE_REPLY_TO)) {
$params['from'] = $from;
$from = NULL;
}
// Spaces in img URLs must be replaced with %20
$pattern = '!<(img\s[^>]*?)>!is';
$print['content'] = preg_replace_callback($pattern, '_print_replace_spaces', $print['content']);
$node = $print['node'];
$params['body'] = theme('print_page', $print, PRINT_MAIL_FORMAT, $node);
$params['body'] = drupal_final_markup($params['body']);
// Img elements must be set to absolute
$pattern = '!<(img\s[^>]*?)>!is';
$params['body'] = preg_replace_callback($pattern, '_print_rewrite_urls', $params['body']);
// Convert the a href elements, to make sure no relative links remain
$pattern = '!<(a\s[^>]*?)>!is';
$params['body'] = preg_replace_callback($pattern, '_print_rewrite_urls', $params['body']);
$ok = FALSE;
if (function_exists('job_queue_add') && variable_get('print_mail_job_queue', PRINT_MAIL_JOB_QUEUE_DEFAULT)) {
$use_job_queue = TRUE;
$this_file = drupal_get_path('module', 'print_mail') .'/print_mail.inc';
}
else {
$use_job_queue = FALSE;
}
$addresses = explode(', ', $form_state['values']['txt_to_addrs']);
foreach ($addresses as $to) {
// Call to hook_print_mail_before_send in order to know if the mail can be sent
// Handlers must return TRUE or FALSE
$can_send = module_invoke_all('print_mail_before_send', $node, $to, $from, $params);
if (!in_array(FALSE, $can_send)) {
if ($use_job_queue) {
// Use job queue to send mails during cron runs
job_queue_add('drupal_mail', t('print_mail: From %from', array('%from' => $from)), array('print_mail', $print_mail_send_option_default, $to, language_default(), $params, $from, TRUE), $this_file, TRUE);
}
else {
// Send mail immediately using Drupal's mail handler
$ret = drupal_mail('print_mail', $print_mail_send_option_default, $to, language_default(), $params, $from, TRUE);
}
if ($ret['result'] || $use_job_queue) {
// Call to hook_print_mail_after_send in order to provide information to other modules.
module_invoke_all('print_mail_after_send', $node, $to, $from, $params);
flood_register_event('print_mail');
$ok = TRUE;
}
}
}
if ($ok) {
watchdog('print_mail', '%name [%from] sent %page to [%to]', array('%name' => $form_state['values']['fld_from_name'], '%from' => $form_state['values']['fld_from_addr'], '%page' => $form_state['values']['path'], '%to' => $form_state['values']['txt_to_addrs']));
$site_name = variable_get('site_name', t('us'));
$print_mail_text_confirmation = variable_get('print_mail_text_confirmation', t('Thank you for spreading the word about !site.'));
drupal_set_message(check_plain(t($print_mail_text_confirmation, array('!site' => $site_name))));
$nodepath = drupal_get_normal_path($form_state['values']['path']);
db_query("UPDATE {print_mail_page_counter} SET sentcount = sentcount + %d, sent_timestamp = %d WHERE path = '%s'", count($addresses), time(), $nodepath);
}
}
}
$form_state['redirect'] = preg_replace('!^book/export/html/!', 'node/', $form_state['values']['path']);
}
/**
* Implementation of hook_mail().
*/
function print_mail_mail($key, &$message, $params) {
$message['subject'] = $params['subject'];
if (isset($params['from'])) {
$message['headers']['Reply-To'] = $params['from'];
}
switch ($key) {
case 'sendpage':
$message['body'] = module_exists('mailsystem') ? check_plain($params['body']) : $params['body'];
$message['headers']['Content-Type'] = 'text/html; charset=utf-8';
break;
case 'sendlink':
// Generate plain-text and html versions of message with link
$sendlink_plain = $params['message'] .'\n\n'. $params['link'];
$sendlink_html = $params['message'] .'<br/><br/>'. l($params['title'], $params['link']);
// Send HTML-only version if MIME library not present
if (!class_exists('Mail_mime')) {
$message['body'] = module_exists('mailsystem') ? check_plain($sendlink_html) : $sendlink_html;
$message['headers']['Content-Type'] = 'text/html; charset=utf-8';
break;
}
// no break on purpose
case 'plain-attachment':
case 'inline-attachment':
// Configure new MIME object
$mime = new Mail_mime("\n");
$mime_params['html_encoding'] = '7bit';
$mime_params['html_charset'] = 'utf-8';
$mime_params['text_charset'] = 'utf-8';
// Pass message contents into MIME object
switch ($key) {
case 'sendlink':
$mime->setTXTBody($sendlink_plain);
$mime->setHTMLBody($sendlink_html);
break;
case 'inline-attachment':
$mime->setHTMLBody($params['body']);
// no break on purpose
case 'plain-attachment':
$mime->setTXTBody($params['message']);
$mime->addAttachment($params['body'], 'text/html', 'Attachment.html', FALSE);
break;
}
// Store MIME message output in message array
$message['body'] = $mime->get($mime_params);
$message['headers'] = $mime->headers($message['headers']);
// Strip special characters from Content-Type header
// Required to prevent mime_header_encode() from disrupting Content-Type header
$message['headers']['Content-Type'] = preg_replace('/[^\x20-\x7E]/', '', $message['headers']['Content-Type']);
break;
}
}
/**
* Process the send by-email form cancel submission.
*
* @ingroup forms
*/
function print_mail_form_cancel($form, &$form_state) {
$form_state['redirect'] = preg_replace('!^book/export/html/!', 'node/', $form_state['values']['path']);
}

View file

@ -0,0 +1,12 @@
name = "Send by email"
description = "Provides the capability to send the web page by email"
dependencies[] = print
core=6.x
package = "Printer, email and PDF versions"
; Information added by Drupal.org packaging script on 2014-04-02
version = "6.x-1.19"
core = "6.x"
project = "print"
datestamp = "1396426748"

View file

@ -0,0 +1,341 @@
<?php
/**
* @file
* Install file of the print_mail module
*
* @ingroup print
*/
/**
* Implementation of hook_install().
*/
function print_mail_install() {
drupal_install_schema('print_mail');
// Module weight
update_sql("UPDATE {system} SET weight = 1 WHERE name = 'print_mail'");
}
/**
* Implementation of hook_uninstall().
*/
function print_mail_uninstall() {
drupal_uninstall_schema('print_mail');
variable_del('print_mail_settings');
variable_del('print_mail_show_link');
variable_del('print_mail_link_pos');
variable_del('print_mail_link_teaser');
variable_del('print_mail_node_link_visibility');
variable_del('print_mail_node_link_pages');
variable_del('print_mail_link_class');
variable_del('print_mail_sys_link_visibility');
variable_del('print_mail_sys_link_pages');
variable_del('print_mail_book_link');
variable_del('print_mail_hourly_threshold');
variable_del('print_mail_use_reply_to');
variable_del('print_mail_teaser_default');
variable_del('print_mail_teaser_choice');
variable_del('print_mail_link_text');
variable_del('print_mail_link_use_alias');
variable_del('print_mail_text_title');
variable_del('print_mail_text_confirmation');
variable_del('print_mail_text_message');
variable_del('print_mail_text_subject');
variable_del('print_mail_text_content');
variable_del('print_mail_job_queue');
variable_del('print_mail_display_sys_urllist');
$settings = db_query("SELECT name FROM {variable} WHERE name LIKE 'print\_mail\_display\_%'");
while ($variable = db_fetch_object($settings)) {
variable_del($variable->name);
}
}
/**
* Implementation of hook_schema().
*/
function print_mail_schema() {
$schema['print_mail_node_conf'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'link' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
'comments' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
'url_list' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
),
'primary key' => array('nid'),
);
$schema['print_mail_page_counter'] = array(
'fields' => array(
'path' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
),
'totalcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'sentcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'sent_timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('path'),
);
return $schema;
}
/**
* Update to version 6.x-1.0
*/
function print_mail_update_6000() {
global $conf;
$ret = array();
if (isset($conf['print_mail_settings'])) {
$print_mail_settings = variable_get('print_mail_settings', '');
variable_set('print_mail_link_pos', array('link' => ($print_html_settings['show_link'] ? 'link' : 0) ));
variable_set('print_mail_show_link', max(1, $print_mail_settings['show_link']));
variable_set('print_mail_node_link_visibility', $print_mail_settings['node_link_visibility']);
variable_set('print_mail_node_link_pages', $print_mail_settings['node_link_pages']);
variable_set('print_mail_link_class', $print_mail_settings['link_class']);
variable_set('print_mail_sys_link_visibility', $print_mail_settings['sys_link_visibility']);
variable_set('print_mail_sys_link_pages', $print_mail_settings['sys_link_pages']);
variable_set('print_mail_book_link', $print_mail_settings['book_link']);
variable_set('print_mail_teaser_default', $print_mail_settings['teaser_default']);
variable_set('print_mail_teaser_choice', $print_mail_settings['teaser_choice']);
variable_del('print_mail_settings');
}
return $ret;
}
/**
* Update to version 6.x-1.1
*/
function print_mail_update_6001() {
$schema['print_mail_node_conf'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'link' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
'comments' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
'url_list' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
),
'primary key' => array('nid'),
);
$schema['print_mail_page_counter'] = array(
'fields' => array(
'path' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
),
'totalcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'sentcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'sent_timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('path'),
);
$ret = array();
db_create_table($ret, 'print_mail_node_conf', $schema['print_mail_node_conf']);
db_create_table($ret, 'print_mail_page_counter', $schema['print_mail_page_counter']);
return $ret;
}
/**
* Update to version 6.x-1.2
*/
function print_mail_update_6003() {
// Delete custom text strings set to the default
$ret = array();
$vars = array(
'print_mail_link_text' => 'Send by email',
'print_mail_text_subject' => '!user has sent you a message from !site',
'print_mail_text_message' => 'Message from sender',
'print_mail_text_content' => '',
'print_mail_text_confirmation' => 'Thank you for spreading the word about !site.',
);
$t = get_t();
foreach ($vars as $name => $default) {
if (variable_get($name, '') == $t($default)) {
variable_del($name);
}
}
menu_rebuild();
return $ret;
}
/**
* Update to version 6.x-1.8
*/
function print_mail_update_6004() {
// add new 'access send by email' permission to any role which has 'access print'
$ret = array();
$dbret = db_query('SELECT * FROM {permission}');
while ($role = db_fetch_object($dbret)) {
if ((strpos($role->perm, 'access print') !== FALSE)) {
$role->perm = db_escape_string('access send by email, '. $role->perm);
$ret[] = update_sql("UPDATE {permission} SET perm = '$role->perm' WHERE rid = $role->rid");
}
}
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_mail_update_6005() {
$ret = array();
// BLOCK_CACHE_GLOBAL -> 8
$ret[] = update_sql("UPDATE {blocks} SET cache = 8 WHERE module = 'print_mail' AND delta = '0'");
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_mail_update_6006() {
$ret = array();
// Module weight
$ret[] = update_sql("UPDATE {system} SET weight = 1 WHERE name = 'print_mail'");
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_mail_update_6007() {
$ret = array();
foreach (node_get_types() as $key => $value) {
$print_mail_display = variable_get('print_mail_display_'. $value->type, 1);
$print_mail_display_comment = variable_get('print_mail_display_comment_'. $value->type, 0);
$print_mail_display_urllist = variable_get('print_mail_display_urllist_'. $value->type, 1);
$ret[] = update_sql("UPDATE {print_mail_node_conf} SET link = (link AND $print_mail_display), comments = (comments OR $print_mail_display_comment), url_list = (url_list AND $print_mail_display_urllist) WHERE nid IN (SELECT nid FROM {node} WHERE type = '$value->type');");
}
return $ret;
}
/**
* Update permissions to new spellings
*/
function print_mail_update_6100() {
$ret = array();
$result = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
while ($role = db_fetch_object($result)) {
$renamed_permission = str_replace('access send to friend', 'access send by email', $role->perm);
$renamed_permission = str_replace('send unlimited e-mails', 'send unlimited emails', $renamed_permission);
$renamed_permission = db_escape_string($renamed_permission);
if ($renamed_permission != $role->perm) {
$ret[] = update_sql("UPDATE {permission} SET perm = '$renamed_permission' WHERE rid = $role->rid");
}
}
return $ret;
}
/**
* Enable block and help area links
*/
function print_mail_update_6118() {
$ret = array();
$link_pos = variable_get('print_mail_link_pos', array('link' => 'link', 'block' => 'block', 'help' => 'help'));
$link_pos['block'] = 'block';
$link_pos['help'] = 'help';
variable_set('print_mail_link_pos', $link_pos);
return $ret;
}

View file

@ -0,0 +1,649 @@
<?php
/**
* @file
* Displays Printer-friendly versions of Drupal pages.
*
* @ingroup print
*/
define('PRINTMAIL_PATH', 'printmail');
define('PRINT_MAIL_FORMAT', 'mail');
define('PRINT_MAIL_LINK_POS_DEFAULT', serialize(array('link' => 'link', 'block' => 'block', 'help' => 'help')));
define('PRINT_MAIL_LINK_TEASER_DEFAULT', 0);
define('PRINT_MAIL_SHOW_LINK_DEFAULT', 1);
define('PRINT_MAIL_NODE_LINK_VISIBILITY_DEFAULT', 0);
define('PRINT_MAIL_NODE_LINK_PAGES_DEFAULT', '');
define('PRINT_MAIL_LINK_CLASS_DEFAULT', 'print-mail');
define('PRINT_MAIL_SYS_LINK_VISIBILITY_DEFAULT', 1);
define('PRINT_MAIL_SYS_LINK_PAGES_DEFAULT', '');
define('PRINT_MAIL_LINK_USE_ALIAS_DEFAULT', 0);
define('PRINT_MAIL_BOOK_LINK_DEFAULT', 1);
define('PRINT_MAIL_HOURLY_THRESHOLD', 3);
define('PRINT_MAIL_USE_REPLY_TO', TRUE);
define('PRINT_MAIL_TEASER_DEFAULT_DEFAULT', 1);
define('PRINT_MAIL_TEASER_CHOICE_DEFAULT', 0);
define('PRINT_MAIL_SEND_OPTION_DEFAULT', 'sendpage');
define('PRINT_MAIL_JOB_QUEUE_DEFAULT', 0);
/**
* Implementation of hook_perm().
*/
function print_mail_perm() {
return array('access send by email', 'send unlimited emails');
}
/**
* Implementation of hook_theme().
*/
function print_mail_theme() {
return array(
'print_mail_format_link' => array(
'arguments' => array(),
),
'print_mail_form' => array(
'arguments' => array('form' => NULL),
'file' => 'print_mail.inc',
),
);
}
/**
* Implementation of hook_menu().
*/
function print_mail_menu() {
$items = array();
$items[PRINTMAIL_PATH] = array(
'title' => variable_get('print_mail_text_title', 'Send page by email'),
'page callback' => 'drupal_get_form',
'page arguments' => array('print_mail_form'),
'access callback' => '_print_mail_access',
'access arguments' => array('access send by email'),
'type' => MENU_CALLBACK,
'file' => 'print_mail.inc',
);
$items[PRINTMAIL_PATH .'/'. PRINTMAIL_PATH] = array(
'access callback' => FALSE,
);
$items['admin/settings/print/email'] = array(
'title' => 'email',
'description' => 'Configure the settings of the send by email functionality.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_mail_settings'),
'access arguments' => array('administer print'),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
'file' => 'print_mail.admin.inc',
);
$items['admin/settings/print/email/options'] = array(
'title' => 'Options',
'weight' => 1,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/print/email/strings'] = array(
'title' => 'Text strings',
'description' => 'Override the user-facing strings used in the send by email version.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_mail_strings_settings'),
'access arguments' => array('administer print'),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
'file' => 'print_mail.admin.inc',
);
return $items;
}
/**
* Implementation of hook_block().
*/
function print_mail_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$block[0]['info'] = t('Most emailed');
$block[0]['cache'] = BLOCK_CACHE_GLOBAL;
return $block;
break;
case 'configure':
return '';
case 'save':
return;
case 'view':
switch ($delta) {
case 0:
$block['subject'] = t('Most emailed');
$result = db_query_range("SELECT path FROM {print_mail_page_counter} LEFT JOIN {node} n ON path = CONCAT('node/', n.nid) WHERE status <> 0 OR status IS NULL ORDER BY sentcount DESC", 0, 3);
if (db_affected_rows()) {
$block['content'] = '<div class="item-list"><ul>';
while ($obj = db_fetch_object($result)) {
$block['content'] .= '<li>'. l(_print_get_title($obj->path), $obj->path) .'</li>';
}
$block['content'] .= '</ul></div>';
}
break;
}
return $block;
break;
}
}
/**
* Implementation of hook_link().
*/
function print_mail_link($type, $node = NULL, $teaser = FALSE) {
$print_mail_link_pos = variable_get('print_mail_link_pos', unserialize(PRINT_MAIL_LINK_POS_DEFAULT));
$print_mail_link_use_alias = variable_get('print_mail_link_use_alias', PRINT_MAIL_LINK_USE_ALIAS_DEFAULT);
$allowed_type = print_mail_link_allowed(array('type' => $type, 'node' => $node, 'teaser' => $teaser));
if (($allowed_type) && !empty($print_mail_link_pos['link'])) {
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$links = array();
$format = theme('print_mail_format_link');
// Show book link
if ($allowed_type === PRINT_ALLOW_BOOK_LINK) {
$links['book_mail'] = array('href' => PRINTMAIL_PATH .'/book/export/html/'. $node->nid,
'title' => $format['text'],
'attributes' => $format['attributes'],
'html' => $format['html'],
);
return $links;
}
elseif ($allowed_type === PRINT_ALLOW_NORMAL_LINK) {
$query_arr = $_GET;
if ($type == 'comment') {
$query_arr['comment'] = $node->cid;
}
$query = print_query_string_encode($query_arr, array('q'));
if (empty($query)) $query = NULL;
if (($print_mail_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/'. $node->nid))) {
$path = $alias;
}
else {
$path = $node->nid;
}
$links['print_mail'] = array('href' => PRINTMAIL_PATH .'/'. $path,
'title' => $format['text'],
'attributes' => $format['attributes'],
'html' => $format['html'],
'query' => $query,
);
return $links;
}
}
else {
return;
}
}
/**
* Implementation of hook_help().
*/
function print_mail_help($path, $arg) {
$print_mail_link_pos = variable_get('print_mail_link_pos', unserialize(PRINT_MAIL_LINK_POS_DEFAULT));
if (($path !== 'node/%') && !(empty($print_mail_link_pos['help']))) {
static $output = FALSE;
if ($output === FALSE) {
$output = TRUE;
$link = print_mail_insert_link();
if ($link) {
return "<span class='print-syslink'>$link</span>";
}
}
}
}
/**
* Implementation of hook_nodeapi().
*/
function print_mail_nodeapi(&$node, $op = 'view', $teaser, $page) {
switch ($op) {
case 'view':
// Insert content corner links
$print_mail_link_pos = variable_get('print_mail_link_pos', unserialize(PRINT_MAIL_LINK_POS_DEFAULT));
if (($teaser === FALSE) && !empty($print_mail_link_pos['corner']) &&
isset($node->build_mode) && ($node->build_mode === NODE_BUILD_NORMAL)) {
$node->content['print_links']['#value'] .= print_mail_insert_link(NULL, $node);
}
break;
case 'load':
$res = db_fetch_object(db_query("SELECT link, comments, url_list FROM {print_mail_node_conf} WHERE nid = %d", $node->nid));
$node->print_mail_display = $res ? intval($res->link) : variable_get('print_mail_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$node->print_mail_display_comment = $res ? intval($res->comments) : variable_get('print_mail_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$node->print_mail_display_urllist = $res ? intval($res->url_list) : variable_get('print_mail_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
break;
case 'insert':
case 'update':
if (user_access('administer print') || user_access('node-specific print configuration')) {
if (!isset($node->print_mail_display)) $node->print_mail_display = variable_get('print_mail_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
if (!isset($node->print_mail_display_comment)) $node->print_mail_display_comment = variable_get('print_mail_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
if (!isset($node->print_mail_display_urllist)) $node->print_mail_display_urllist = variable_get('print_mail_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
_print_mail_node_conf_modify($node->nid, $node->print_mail_display, $node->print_mail_display_comment, $node->print_mail_display_urllist);
}
break;
case 'delete':
db_query("DELETE FROM {print_mail_node_conf} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {print_mail_page_counter} WHERE path = 'node/%d'", $node->nid);
break;
}
}
/**
* Implementation of hook_form_alter().
*/
function print_mail_form_alter(&$form, $form_state, $form_id) {
// Add the node-type settings option to activate the mail version link
if ((user_access('administer print') || user_access('node-specific print configuration')) && (($form_id == 'node_type_form') ||
(isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id))) {
$form['print']['mail_label'] = array(
'#type' => 'markup',
'#value' => '<p><strong>'. t('Send by email') .'</strong></p>',
);
$form['print']['print_mail_display'] = array(
'#type' => 'checkbox',
'#title' => t('Show link'),
);
$form['print']['print_mail_display_comment'] = array(
'#type' => 'checkbox',
'#title' => t('Show link in individual comments'),
);
$form['print']['print_mail_display_urllist'] = array(
'#type' => 'checkbox',
'#title' => t('Show Printer-friendly URLs list'),
);
if ($form_id == 'node_type_form') {
$form['print']['print_mail_display']['#default_value'] = variable_get('print_mail_display_'. $form['#node_type']->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$form['print']['print_mail_display_comment']['#default_value'] = variable_get('print_mail_display_comment_'. $form['#node_type']->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$form['print']['print_mail_display_urllist']['#default_value'] = variable_get('print_mail_display_urllist_'. $form['#node_type']->type, PRINT_TYPE_URLLIST_DEFAULT);
}
else {
$node = $form['#node'];
$form['print']['print_mail_display']['#default_value'] = isset($node->print_mail_display) ? $node->print_mail_display : variable_get('print_mail_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$form['print']['print_mail_display_comment']['#default_value'] = isset($node->print_mail_display_comment) ? $node->print_mail_display_comment : variable_get('print_mail_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$form['print']['print_mail_display_urllist']['#default_value'] = isset($node->print_mail_display_urllist) ? $node->print_mail_display_urllist : variable_get('print_mail_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
}
}
}
/**
* Implementation of hook_job_queue_functions().
*/
function print_mail_job_queue_functions() {
$functions['print_mail'] = array(
'title' => t('Send by email'),
);
return $functions;
}
/**
* Access callback to check a combination of user_acess() and page access
*
* @param $permission
* permission required to view the page
* @return
* TRUE if the user has permission to view the page, FALSE otherwise
*/
function _print_mail_access($permission) {
$page_access = TRUE;
$parts = explode('/', $_GET['q']);
if ($parts[0] == PRINTMAIL_PATH) {
if (count($parts) > 1) {
unset($parts[0]);
$path = implode('/', $parts);
if (ctype_digit($parts[1])) {
if (drupal_lookup_path('source', $path)) {
// This is a numeric alias
$path = drupal_get_normal_path($path);
}
else {
// normal nid
$path = 'node/' . $path;
}
}
else {
$path = drupal_get_normal_path($path);
}
// If the destination page is not accessible, don't show the form
if (!($router_item = menu_get_item($path)) || (!$router_item['access'])) {
$page_access = FALSE;
}
}
}
return (user_access($permission) && $page_access);
}
/**
* Update the print_mail_node_conf table to reflect the given attributes
*
* If updating to the default values, delete the record.
*
* @param $nid
* value of the nid field (primary key)
* @param $link
* value of the link field (0 or 1)
* @param $comments
* value of the comments field (0 or 1)
* @param $url_list
* value of the url_list field (0 or 1)
*/
function _print_mail_node_conf_modify($nid, $link, $comments, $url_list) {
db_query("UPDATE {print_mail_node_conf} SET link = %d, comments = %d, url_list = %d WHERE nid = %d", $link, $comments, $url_list, $nid);
if (!db_affected_rows()) {
@db_query("INSERT INTO {print_mail_node_conf} (nid, link, comments, url_list) VALUES (%d, %d, %d, %d)", $nid, $link, $comments, $url_list);
}
}
/**
* Format the send by email link
*
* @return
* array of formatted attributes
* @ingroup themeable
*/
function theme_print_mail_format_link() {
$print_mail_link_class = variable_get('print_mail_link_class', PRINT_MAIL_LINK_CLASS_DEFAULT);
$print_mail_show_link = variable_get('print_mail_show_link', PRINT_MAIL_SHOW_LINK_DEFAULT);
$print_mail_link_text = filter_xss(variable_get('print_mail_link_text', t('Send by email')));
$img = drupal_get_path('module', 'print') .'/icons/mail_icon.gif';
$title = t('Send this page by email.');
$class = strip_tags($print_mail_link_class);
$new_window = FALSE;
$format = _print_format_link_aux($print_mail_show_link, $print_mail_link_text, $img);
return array('text' => $format['text'],
'html' => $format['html'],
'attributes' => print_fill_attributes($title, $class, $new_window),
);
}
/**
* Auxiliary function to display a formatted send by email link
*
* Function made available so that developers may call this function from
* their defined pages/blocks.
*
* @param $path
* path of the original page (optional). If not specified, the current URL
* is used
* @param $node
* an optional node object, to be used in defining the path, if used, the
* path argument is irrelevant
* @return
* string with the HTML link to the printer-friendly page
*/
function print_mail_insert_link($path = NULL, $node = NULL) {
if ($node !== NULL) {
$nid = $node->nid;
$path = 'node/'. $nid;
$allowed_type = print_mail_link_allowed(array('node' => $node));
}
else {
if ($path === NULL) {
$nid = preg_replace('!^node/([\d]+)!', '$1', $_GET['q']);
$path = $_GET['q'];
}
else {
$nid = NULL;
}
$allowed_type = print_mail_link_allowed(array('path' => $path));
}
if ($allowed_type) {
if ($nid !== NULL) {
if ($allowed_type === PRINT_ALLOW_BOOK_LINK) {
$path = 'book/export/html/'. $nid;
}
else {
if (variable_get('print_mail_link_use_alias', PRINT_MAIL_LINK_USE_ALIAS_DEFAULT) && ($alias = drupal_lookup_path('alias', $path))) {
$path = $alias;
}
else {
$path = $nid;
}
}
$path = PRINTMAIL_PATH .'/'. $path;
$query = print_query_string_encode($_GET, array('q'));
if (empty($query)) {
$query = NULL;
}
}
else {
$query = NULL;
}
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$format = theme('print_mail_format_link');
return '<span class="print_mail">'. l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) .'</span>';
}
else {
return FALSE;
}
}
/**
* Check if the link to send by email is allowed depending on the settings
*
* @param $args
* array containing the possible parameters:
* teaser, node, type, path
* @return
* FALSE if not allowed
* PRINT_ALLOW_NORMAL_LINK if a normal link is allowed
* PRINT_ALLOW_BOOK_LINK if a link is allowed in a book node
*/
function print_mail_link_allowed($args) {
if ((!empty($args['teaser']) && !variable_get('print_mail_link_teaser', PRINT_MAIL_LINK_TEASER_DEFAULT))
|| !user_access('access send by email')) {
// If the teaser link is disabled or the user is not allowed
return FALSE;
}
if (!empty($args['path'])) {
$nid = preg_replace('!^node/!', '', drupal_get_normal_path($args['path']));
if (ctype_digit($nid)) {
$args['node'] = node_load($nid);
}
}
if (!empty($args['node'])) {
static $node_type = FALSE;
$node = $args['node'];
if (isset($node->type)) {
$node_type = $node->type;
}
// Node
$print_mail_node_link_visibility = variable_get('print_mail_node_link_visibility', PRINT_MAIL_NODE_LINK_VISIBILITY_DEFAULT);
$print_mail_node_link_pages = variable_get('print_mail_node_link_pages', PRINT_MAIL_NODE_LINK_PAGES_DEFAULT);
if (!_print_page_match($print_mail_node_link_visibility, "node/". $node->nid, $print_mail_node_link_pages)) {
// Page not in visibility list
return FALSE;
}
elseif (isset($args['type']) && ($args['type'] == 'comment') && isset($node_type)) {
// Link is for a comment, return the configured setting
// Cache this statically to avoid duplicate queries for every comment.
static $res = array();
if (!isset($res[$node->nid])) {
$res[$node->nid] = db_fetch_object(db_query("SELECT comments FROM {print_mail_node_conf} WHERE nid = %d", $node->nid));
}
$print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? intval($res[$node->nid]->comments) : variable_get('print_mail_display_comment_'. $node_type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
if ($print_display_comment) {
return PRINT_ALLOW_NORMAL_LINK;
}
}
else {
// Node link
if (isset($node->print_mail_display) && !$node->print_mail_display) {
// Link for this node is disabled
return FALSE;
}
elseif (isset($node->book)) {
// Node is a book;
$print_mail_book_link = variable_get('print_mail_book_link', PRINT_MAIL_BOOK_LINK_DEFAULT);
switch ($print_mail_book_link) {
case 1:
if (user_access('access printer-friendly version')) {
return PRINT_ALLOW_BOOK_LINK;
}
break;
case 2:
return PRINT_ALLOW_NORMAL_LINK;
}
}
else {
return PRINT_ALLOW_NORMAL_LINK;
}
}
}
else {
// 'System' page
$print_mail_sys_link_visibility = variable_get('print_mail_sys_link_visibility', PRINT_MAIL_SYS_LINK_VISIBILITY_DEFAULT);
$print_mail_sys_link_pages = variable_get('print_mail_sys_link_pages', PRINT_MAIL_SYS_LINK_PAGES_DEFAULT);
return _print_page_match($print_mail_sys_link_visibility, $_GET['q'], $print_mail_sys_link_pages);
}
return FALSE;
}
/**
* Implementation of hook_nollom_form_list().
*/
function print_mail_mollom_form_list() {
$forms['print_mail_form'] = array(
'title' => t('Send page form'),
'entity' => 'print_mail',
);
return $forms;
}
/**
* Implementation of hook_mollom_form_info().
*/
function print_mail_mollom_form_info($form_id) {
switch ($form_id) {
case 'print_mail_form':
$form_info = array(
'elements' => array(
'fld_from_addr' => t('Sender email'),
'fld_from_name' => t('Sender name'),
'txt_to_addrs' => t('Recipients'),
'fld_subject' => t('Subject'),
'fld_title' => t('Page to be sent'),
'txt_message' => t('Your message'),
),
'mapping' => array(
'post_title' => 'fld_title',
'author_name' => 'fld_from_name',
'author_mail' => 'fld_from_addr',
),
);
break;
}
return $form_info;
}
/**
* Implements hook_views_api().
*/
function print_mail_views_api() {
return array(
'api' => 2.0,
'path' => drupal_get_path('module', 'print_mail'),
);
}
/**
* Implements hook_rules_action_info().
*
* @ingroup rules
*/
function print_mail_rules_action_info() {
return array(
'print_mail_action_submit' => array(
'label' => t('Send node as HTML formatted email'),
'module' => 'Node',
'eval input' => array('to', 'from', 'subject', 'message'),
'arguments' => array(
'node' => array('type' => 'node', 'label' => t('Content')),
),
),
);
}
function print_mail_action_submit_form($settings, &$form) {
$settings += array('from' => '', 'from_name' => '', 'to' => '', 'subject' => '', 'message' => '');
$form['settings']['from'] = array(
'#type' => 'textfield',
'#title' => t('From email adress'),
'#default_value' => $settings['from'],
'#size' => 60,
'#maxlength' => 128,
'#required' => TRUE,
);
$form['settings']['from_name'] = array(
'#type' => 'textfield',
'#title' => t('From name'),
'#default_value' => $settings['from_name'],
'#size' => 60,
'#maxlength' => 128,
'#required' => TRUE,
);
$form['settings']['to'] = array(
'#type' => 'textfield',
'#title' => t('Send email to'),
'#default_value' => $settings['to'],
'#size' => 60,
'#maxlength' => 128,
'#required' => TRUE,
);
$form['settings']['subject'] = array(
'#type' => 'textfield',
'#title' => t('Subject'),
'#default_value' => $settings['subject'],
'#size' => 60,
'#maxlength' => 128,
'#required' => TRUE,
);
$form['settings']['message'] = array(
'#type' => 'textarea',
'#title' => t('Message'),
'#default_value' => $settings['message'],
'#description' => t('The message that should be displayed (optional).'),
);
}
/**
* Action handler for the print_mail_action_submit
*
* @ingroup rules
*/
function print_mail_action_submit($node, $settings) {
require_once(drupal_get_path('module', 'print_mail') . '/print_mail.inc');
$form_state['values'] = array(
'path' => 'node/' . $node->nid,
'cid' => NULL,
'title' => $node->title,
'fld_from_addr' => $settings['from'],
'fld_from_name' => $settings['from_name'],
'txt_to_addrs' => $settings['to'],
'fld_subject' => $settings['subject'],
'txt_message' => $settings['message'],
'chk_teaser' => FALSE,
);
print_mail_form_submit(NULL, $form_state);
}

View file

@ -0,0 +1,153 @@
<?php
/**
* @file
* Send by email Views integration
*
* @ingroup print
*/
// Views join handlers aren't truly handlers according to [#540128]
// so they need to be specifically included here.
module_load_include('inc', 'print', 'print_join_page_counter');
/**
* Implements hook_views_data().
*/
function print_mail_views_data() {
// The 'group' index will be used as a prefix in the UI for any of this
// table's fields, sort criteria, etc. so it's easy to tell where they came
// from.
$data['print_mail_node_conf']['table']['group'] = t('Printer-friendly version');
$data['print_mail_page_counter']['table']['group'] = t('Printer-friendly version');
// This table references the {node} table. The declaration below creates an
// 'implicit' relationship to the node table, so that when 'node' is the base
// table, the fields are automatically available.
$data['print_mail_node_conf']['table']['join']['node'] = array(
// 'left_field' is the primary key in the referenced table.
// 'field' is the foreign key in this table.
'left_field' => 'nid',
'field' => 'nid',
// 'type' => 'INNER',
);
$data['print_mail_page_counter']['table']['join']['node'] = array(
// 'left_field' is the primary key in the referenced table.
// 'field' is the foreign key in this table.
'left_field' => 'nid',
'field' => 'path',
// 'type' => 'INNER',
'handler' => 'print_join_page_counter',
);
// print_mail_node_conf fields
$data['print_mail_node_conf']['link'] = array(
'title' => t('Email: Show link'),
'help' => t('Whether to show the send by email link.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
$data['print_mail_node_conf']['comments'] = array(
'title' => t('Email: Show link in individual comments'),
'help' => t('Whether to show the send by email link in individual comments.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
$data['print_mail_node_conf']['url_list'] = array(
'title' => t('Email: Show Printer-friendly URLs list'),
'help' => t('Whether to show the URL list.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
// print_mail_page_counter fields
$data['print_mail_page_counter']['totalcount'] = array(
'title' => t('Email: Number of page accesses'),
'help' => t('Counter of accesses to the send by email form for this node.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
);
$data['print_mail_page_counter']['timestamp'] = array(
'title' => t('Email: Last access'),
'help' => t("The date of the last access to the node's send by email form."),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
$data['print_mail_page_counter']['sentcount'] = array(
'title' => t('Email: Number of sent emails'),
'help' => t('Counter of emails sent for this node.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
);
$data['print_mail_page_counter']['sent_timestamp'] = array(
'title' => t('Email: Last email sent'),
'help' => t('The date when the node was last sent by email.'),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
return $data;
}

View file

@ -0,0 +1,336 @@
<?php
/**
* @file
* Contains the administrative functions of the PDF version module.
*
* This file is included by the PDF version module, and includes the
* settings form.
*
* @ingroup print
*/
/**
* Menu callback for the PDF version module settings form.
*
* @ingroup forms
* @see _print_pdf_tools()
*/
function print_pdf_settings() {
$pdf_tools = _print_pdf_tools();
if ($pdf_tools != -1) {
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('PDF options'),
);
$form['settings']['print_pdf_pdf_tool'] = array(
'#type' => 'radios',
'#title' => t('PDF generation tool'),
'#options' => $pdf_tools,
'#default_value' => variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT),
'#description' => t('This option selects the PDF generation tool being used by this module to create the PDF version.'),
);
$form['settings']['print_pdf_link_pos'] = array(
'#type' => 'checkboxes',
'#title' => t('PDF version link'),
'#default_value' => variable_get('print_pdf_link_pos', unserialize(PRINT_PDF_LINK_POS_DEFAULT)),
'#options' => array('link' => t('Links area'), 'corner' => t('Content corner'), 'block' => t('Block'), 'help' => t('Help area')),
'#description' => t('Choose the location of the link(s) to the PDF version. The Links area is usually below the node content, whereas the Content corner is placed in the upper-right corner of the node content. Unselect all options to disable the link. Even if the link is disabled, you can still view the PDF version of a node by going to !path/nid where nid is the numeric id of the node.', array('!path' => PRINTPDF_PATH)),
);
$form['settings']['print_pdf_link_teaser'] = array(
'#type' => 'checkbox',
'#title' => t('Display link to the PDF version in teaser'),
'#default_value' => variable_get('print_pdf_link_teaser', PRINT_PDF_LINK_TEASER_DEFAULT),
'#description' => t('Enabling this will display the link in teaser mode.'),
);
$form['settings']['adv_link'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced link options'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['settings']['adv_link']['print_pdf_show_link'] = array(
'#type' => 'radios',
'#title' => t('Link style'),
'#default_value' => variable_get('print_pdf_show_link', PRINT_PDF_SHOW_LINK_DEFAULT),
'#options' => array(1 => t('Text only'), 2 => t('Icon only'), 3 => t('Icon and Text')),
'#description' => t('Select the visual style of the link.'),
);
$form['settings']['adv_link']['print_pdf_link_use_alias'] = array(
'#type' => 'checkbox',
'#title' => t('Use URL alias instead of node ID'),
'#default_value' => variable_get('print_pdf_link_use_alias', PRINT_PDF_LINK_USE_ALIAS_DEFAULT),
'#description' => t('Enabling this will create the link using the URL alias instead of the node ID.'),
);
$form['settings']['adv_link']['print_pdf_link_class'] = array(
'#type' => 'textfield',
'#title' => t('Link class'),
'#default_value' => variable_get('print_pdf_link_class', PRINT_PDF_LINK_CLASS_DEFAULT),
'#size' => 60,
'#maxlength' => 250,
'#description' => t('This can be used by themers to change the link style or by jQuery modules to open in a new window (e.g. greybox or thickbox). Multiple classes can be specified, separated by spaces.'),
);
$form['settings']['adv_link']['print_pdf_node_link_visibility'] = array(
'#type' => 'radios',
'#title' => t('Link visibility'),
'#default_value' => variable_get('print_pdf_node_link_visibility', PRINT_PDF_NODE_LINK_VISIBILITY_DEFAULT),
'#options' => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.')),
);
$form['settings']['adv_link']['print_pdf_node_link_pages'] = array(
'#type' => 'textarea',
'#default_value' => variable_get('print_pdf_node_link_pages', PRINT_PDF_NODE_LINK_PAGES_DEFAULT),
'#rows' => 3,
'#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>')),
'#wysiwyg' => FALSE,
);
$access = user_access('use PHP for link visibility');
if ($form['settings']['adv_link']['print_pdf_node_link_visibility']['#default_value'] == 2 && !$access) {
$form['settings']['adv_link']['print_pdf_node_link_visibility'] = array('#type' => 'value', '#value' => 2);
$form['settings']['adv_link']['print_pdf_node_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_pdf_node_link_pages']['#default_value']);
}
elseif ($access) {
$form['settings']['adv_link']['print_pdf_node_link_visibility']['#options'][] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$form['settings']['adv_link']['print_pdf_node_link_pages']['#description'] .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
}
$form['settings']['adv_link']['print_pdf_sys_link_visibility'] = array(
'#type' => 'radios',
'#title' => t('Show link in system (non-content) pages'),
'#description' => 'Any page that is not a Drupal node. Usually pages generated by Drupal or a module such as Views or Panels.',
'#default_value' => variable_get('print_pdf_sys_link_visibility', PRINT_PDF_SYS_LINK_VISIBILITY_DEFAULT),
'#options' => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.')),
);
$form['settings']['adv_link']['print_pdf_sys_link_pages'] = array(
'#type' => 'textarea',
'#default_value' => variable_get('print_pdf_sys_link_pages', PRINT_PDF_SYS_LINK_PAGES_DEFAULT),
'#rows' => 3,
'#description' => t('Setting this option will add a PDF version page link on pages created by Drupal or the enabled modules.') .'<br />'.
t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>')),
'#wysiwyg' => FALSE,
);
if ($form['settings']['adv_link']['print_pdf_sys_link_visibility']['#default_value'] == 2 && !$access) {
$form['settings']['adv_link']['print_pdf_sys_link_visibility'] = array('#type' => 'value', '#value' => 2);
$form['settings']['adv_link']['print_pdf_sys_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_pdf_sys_link_pages']['#default_value']);
}
elseif ($access) {
$form['settings']['adv_link']['print_pdf_sys_link_visibility']['#options'][] = t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).');
$form['settings']['adv_link']['print_pdf_sys_link_pages']['#description'] .= ' '. t('If the PHP-mode is chosen, enter PHP code between %php. Note that executing incorrect PHP-code can break your Drupal site.', array('%php' => '<?php ?>'));
}
$form['settings']['adv_link']['print_pdf_book_link'] = array(
'#type' => 'radios',
'#title' => t('Link in book hierarchy nodes'),
'#default_value' => variable_get('print_pdf_book_link', PRINT_PDF_BOOK_LINK_DEFAULT),
'#options' => array(t('No link'), t('Current page and sub-pages'), t('Current page only')),
);
$form['settings']['print_pdf_content_disposition'] = array(
'#type' => 'radios',
'#title' => t('Open PDF in'),
'#options' => array(t('Same browser window'), t('New browser window'), t('Save dialog')),
'#default_value' => variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT),
'#description' => t("Select the desired method for opening the PDF in the user's browser."),
);
$form['settings']['print_pdf_paper_size'] = array(
'#type' => 'select',
'#title' => t('Paper size'),
'#options' => array('4A0' => '4A0', '2A0' => '2A0', 'A0' => 'A0',
'A1' => 'A1', 'A2' => 'A2', 'A3' => 'A3', 'A4' => 'A4',
'A5' => 'A5', 'A6' => 'A6', 'A7' => 'A7', 'A8' => 'A8',
'A9' => 'A9', 'A10' => 'A10', 'B0' => 'B0', 'B1' => 'B1',
'B2' => 'B2', 'B3' => 'B3', 'B4' => 'B4', 'B5' => 'B5',
'B6' => 'B6', 'B7' => 'B7', 'B8' => 'B8', 'B9' => 'B9',
'B10' => 'B10', 'C0' => 'C0', 'C1' => 'C1', 'C2' => 'C2',
'C3' => 'C3', 'C4' => 'C4', 'C5' => 'C5', 'C6' => 'C6',
'C7' => 'C7', 'C8' => 'C8', 'C9' => 'C9', 'C10' => 'C10',
'RA0' => 'RA0', 'RA1' => 'RA1', 'RA2' => 'RA2',
'RA3' => 'RA3', 'RA4' => 'RA4', 'SRA0' => 'SRA0',
'SRA1' => 'SRA1', 'SRA2' => 'SRA2', 'SRA3' => 'SRA3',
'SRA4' => 'SRA4', 'LETTER' => 'Letter', 'LEGAL' => 'Legal',
'EXECUTIVE' => 'Executive', 'FOLIO' => 'Folio',
),
'#default_value' => variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT),
'#description' => t('Choose the paper size of the generated PDF.'),
);
$form['settings']['print_pdf_page_orientation'] = array(
'#type' => 'select',
'#title' => t('Page orientation'),
'#options' => array('portrait' => t('Portrait'), 'landscape' => t('Landscape')),
'#default_value' => variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT),
'#description' => t('Choose the page orientation of the generated PDF.'),
);
$form['settings']['print_pdf_images_via_file'] = array(
'#type' => 'checkbox',
'#title' => t('Access images via local file access'),
'#default_value' => variable_get('print_pdf_images_via_file', PRINT_PDF_IMAGES_VIA_FILE_DEFAULT),
'#description' => t("Enabling this option will make the tool use local file access for image files. This option is not recommended to use in conjunction with modules like imagecache which generate the image after it's first accessed. However, it may be necessary in low-end hosting services where the web server is not allowed to open URLs and the user can't modify that configuration setting."),
);
$form['settings']['print_pdf_autoconfig'] = array(
'#type' => 'checkbox',
'#title' => t('Auto-configure the PDF tool settings'),
'#default_value' => variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT),
'#description' => t('If you disable this option, the pdf tool settings must be configured manually. For TCDPF, edit the tcpdf/config/tcpdf_config.php file. For dompdf, edit the dompdf/dompdf_config.inc.php file.'),
);
$form['settings']['print_pdf_font_family'] = array(
'#type' => 'textfield',
'#title' => t('Font family'),
'#default_value' => variable_get('print_pdf_font_family', PRINT_PDF_FONT_FAMILY_DEFAULT),
'#size' => 60,
'#maxlength' => 250,
'#description' => t('(TCPDF only) Set the font family to be used. Examples: %examples.', array('%examples' => 'helvetica, times, courier, dejavusans, dejavuserif, freesans, freeserif, freemono')) .'<br />'.
t("CAUTION: TCPDF embeds the complete font in the generated PDF. If you're not using Unicode, then helvetica or times are safe choices that will keep the PDF small. Unicode fonts can increase the size of the PDF to the 1MB region."),
);
$form['settings']['print_pdf_font_size'] = array(
'#type' => 'textfield',
'#title' => t('Font size'),
'#default_value' => variable_get('print_pdf_font_size', PRINT_PDF_FONT_SIZE_DEFAULT),
'#size' => 2,
'#maxlength' => 3,
'#description' => t('(TCPDF only) Set the font size to be used for normal text. This is the base value for the scaling applied to other text styles.'),
);
$form['settings']['print_pdf_font_subsetting'] = array(
'#type' => 'checkbox',
'#title' => t('Enable font subsetting'),
'#default_value' => variable_get('print_pdf_font_subsetting', PRINT_PDF_FONT_SUBSETTING_DEFAULT),
'#description' => t('(TCPDF only) Only embed those font characters that are actually used. This can generates smaller PDF files but may significantly slow down processing.'),
);
$form['settings']['print_pdf_dompdf_unicode'] = array(
'#type' => 'checkbox',
'#title' => t("Use dompdf's Unicode Mode"),
'#default_value' => variable_get('print_pdf_dompdf_unicode', PRINT_PDF_DOMPDF_UNICODE_DEFAULT),
'#description' => t("If enabled, dompdf's Unicode mode is used. If not, the module will attempt to convert some non-ASCII chars to ISO-8859-1."),
);
$form['settings']['print_pdf_wkhtmltopdf_options'] = array(
'#type' => 'textfield',
'#title' => t('wkhtmltopdf options'),
'#size' => 60,
'#maxlength' => 500,
'#default_value' => variable_get('print_pdf_wkhtmltopdf_options', PRINT_PDF_WKHTMLTOPDF_OPTIONS),
'#description' => t('(wkhtmltopdf only) Set any additional options to be passed to the wkhtmltopdf executable. Tokens may be used in these options (see list below).'),
);
if (module_exists('token')) {
$form['settings']['print_pdf_filename'] = array(
'#type' => 'textfield',
'#title' => t('PDF filename'),
'#default_value' => variable_get('print_pdf_filename', PRINT_PDF_FILENAME_DEFAULT),
'#description' => t("If left empty the generated filename defaults to the node's path. Tokens may be used to build the filename (see following list). The .pdf extension will be appended automatically."),
);
$form['settings']['print_pdf_filename_patterns'] = array(
'#type' => 'fieldset',
'#title' => t('Replacement patterns'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['settings']['print_pdf_filename_patterns']['descriptions'] = array(
'#type' => 'markup',
'#value' => theme('token_help', array('node', 'global')),
);
}
$form['settings']['print_pdf_display_sys_urllist'] = array(
'#type' => 'checkbox',
'#title' => t('Printer-friendly URLs list in system pages'),
'#default_value' => variable_get('print_pdf_display_sys_urllist', PRINT_TYPE_SYS_URLLIST_DEFAULT),
'#description' => t('Enabling this option will display a list of printer-friendly destination URLs at the bottom of the page.'),
);
$form['#validate'][] = '_print_pdf_settings_validate';
}
else {
$form['settings'] = array(
'#type' => 'markup',
'#value' => '<p>'. t("No PDF generation tool found! Please download a supported PHP PDF generation tool. Check this module's INSTALL.txt for more details.") .'</p>',
);
}
return system_settings_form($form);
}
/**
* Validate print_pdf_settings form.
*/
function _print_pdf_settings_validate($form, &$form_state) {
if (empty($form_state['values']['print_pdf_pdf_tool'])) {
form_set_error('print_pdf_pdf_tool', t("No PDF tool selected"));
}
if ($form_state['values']['print_pdf_font_size'] < 1) {
form_set_error('print_pdf_font_size', t("Font size must be at least 1."));
}
}
/**
* Auxiliary function to locate suitable PDF generation tools
*
* @return
* array of filenames with the include-able PHP file of the located tools
*/
function _print_pdf_tools() {
$tools = array_keys(file_scan_directory(drupal_get_path('module', 'print'), '^dompdf_config.inc.php$'));
$tools = array_merge($tools, array_keys(file_scan_directory(drupal_get_path('module', 'print'), '^tcpdf.php$')));
$tools = array_merge($tools, array_keys(file_scan_directory(drupal_get_path('module', 'print'), '^wkhtmltopdf')));
$tools = array_merge($tools, array_keys(file_scan_directory(PRINT_PDF_LIB_PATH, '^dompdf_config.inc.php$')));
$tools = array_merge($tools, array_keys(file_scan_directory(PRINT_PDF_LIB_PATH, '^tcpdf.php$')));
$tools = array_merge($tools, array_keys(file_scan_directory(PRINT_PDF_LIB_PATH, '^wkhtmltopdf')));
if (module_exists('libraries')) {
$tools = array_merge($tools, array_keys(file_scan_directory(libraries_get_path('dompdf'), '^dompdf_config.inc.php$')));
$tools = array_merge($tools, array_keys(file_scan_directory(libraries_get_path('tcpdf'), '^tcpdf.php$')));
$tools = array_merge($tools, array_keys(file_scan_directory(libraries_get_path('wkhtmltopdf'), '^wkhtmltopdf')));
}
$num_tools = count($tools);
if ($num_tools == 0) {
variable_set('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
return -1;
}
else {
// Instead of array_combine(), use this to maintain PHP4 compatibility
$tools2 = array();
foreach ($tools as $key => $val) {
$tools2[$val] = $val;
}
return $tools2;
}
}
/**
* Menu callback for the PDF version module text strings settings form.
*
* @ingroup forms
*/
function print_pdf_strings_settings() {
drupal_set_message(t("Saving these strings will disable their translation via Drupal's language system. Use the reset button to return them to the original state."), 'warning');
$form['print_pdf_text'] = array(
'#type' => 'fieldset',
'#title' => t('Text strings'),
);
$form['print_pdf_text']['print_pdf_link_text'] = array(
'#type' => 'textfield',
'#title' => t('Link text'),
'#default_value' => variable_get('print_pdf_link_text', t('PDF version')),
'#description' => t('Text used in the link to the PDF version.'),
);
return system_settings_form($form);
}

View file

@ -0,0 +1,29 @@
<?php
/**
* @file
* Extend the TCPDF class to be able to customize the Footer
*
* This file is included by the _print_pdf_tcpdf function
*
* @ingroup print
*/
class PrintTCPDF extends TCPDF {
public $footer;
// Display invisible link at the bottom of all pages.
public function setTcpdfLink($tcpdflink) {
$this->tcpdflink = $tcpdflink;
}
// Page footer data
public function setFooterContent($arg = '') {
$this->footer = $arg;
}
// Page footer
public function Footer() {
theme('print_pdf_tcpdf_footer2', $this);
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
* @file
* Extend the TCPDF class to be able to customize the Footer (PHP4 version)
*
* This file is included by the _print_pdf_tcpdf function when the current
* PHP_VERSION is less than 5.0.0
*
* @ingroup print
*/
class PrintTCPDF extends TCPDF {
var $footer;
// Page footer data
function SetFooterData($arg = '') {
$this->footer = $arg;
}
// Page footer
function Footer() {
$this = theme('print_pdf_tcpdf_footer2', $this);
}
}

View file

@ -0,0 +1,223 @@
<?php
/**
* @file
* drush integration for print_pdf module PDF libraries download.
*/
/**
* The PDF project download URL
*/
// TCPDF is in sourceforge, and nicely provides a link to the latest version
define('TCPDF_DOWNLOAD_URI', 'http://sourceforge.net/projects/tcpdf/files/latest');
// URI to the the latest dompdf version.. Hardcoded version unfortunately
define('DOMPDF_DOWNLOAD_URI', 'https://github.com/dompdf/dompdf/releases/download/v0.6.1/dompdf-0.6.1.zip');
// wkhtmltopdf is a binary, requiring a different download for each platform
define('WKHTMLTOPDF_AMD64_DOWNLOAD_URI', 'http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.0/wkhtmltox-linux-amd64_0.12.0-03c001d.tar.xz');
define('WKHTMLTOPDF_I386_DOWNLOAD_URI', 'http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.0/wkhtmltox-linux-i386_0.12.0-03c001d.tar.xz');
define('WKHTMLTOPDF_WIN64_DOWNLOAD_URI', 'http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.0/wkhtmltox-win64_0.12.0-03c001d.exe');
define('WKHTMLTOPDF_WIN_DOWNLOAD_URI', 'http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.0/wkhtmltox-win32_0.12.0-03c001d.exe');
define('WKHTMLTOPDF_OSX_DOWNLOAD_URI', 'http://wkhtmltopdf.googlecode.com/files/wkhtmltopdf-OSX-0.10.0_rc2-static.tar.bz2');
/**
* Implements hook_drush_command().
*/
function print_pdf_drush_command() {
$items = array();
$items['print-pdf-download'] = array(
'description' => 'Download a PDF library.',
'arguments' => array(
'library' => dt('The PDF library to download. Either tcpdf, dompdf or wkhtmltopdf.'),
),
'options' => array(
'path' => dt('A path to the download folder. If omitted Drush will use the default location (@path).', array('@path' => 'sites/all/libraries')),
),
'aliases' => array('pdfdl'),
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT, // No site or config needed.
);
return $items;
}
/**
* Download and extract PDF archive.
*/
function drush_print_pdf_download($library) {
if (isset($library)) {
$download_url = _drush_print_pdf_download_url($library);
if ($download_url) {
$path = drush_get_option('path');
if (empty($path)) {
$path = drush_get_context('DRUSH_DRUPAL_ROOT') . '/sites/all/libraries';
}
// Create the path if it does not exist.
if (!is_dir($path)) {
drush_op('mkdir', $path);
drush_log(dt('Directory @path was created', array('@path' => $path)), 'notice');
}
// Chdir to the download location.
$olddir = getcwd();
drush_op('chdir', $path);
// Warn about an existing dir
if (is_dir($library)) {
// drush_op('rmdir', $library); // Directory must be empty for the php rmdir to work..
drush_log(dt('An existing @library was overwritten at @path', array('@library' => $library, '@path' => $path . '/' . $library)), 'notice');
}
// Download the archive
$filename = _drush_print_pdf_download_file($download_url);
if ($filename) {
$extract_ret = _drush_print_pdf_download_extract($filename);
if ($extract_ret) {
// Remove the archive
drush_op('unlink', $filename);
drush_log(dt('@file has been downloaded and extracted in @path', array('@file' => $filename, '@path' => $path)), 'success');
}
else {
drush_log(dt('@file has been downloaded to @path, but extract failed. Check that you have the necessary program installed, and if necessary extract it manually.',
array('@file' => $filename, '@path' => $path)), 'warning');
}
}
else {
drush_log(dt('Drush was unable to download @library to @path', array('@library' => $library, '@path' => $path)), 'error');
}
// Set working directory back to the previous working directory.
drush_op('chdir', $olddir);
}
}
else {
drush_log(dt('Please specify a PDF library. Currently supported libraries are dompdf, tcpdf and wkhtmltopdf.'), 'error');
}
}
/**
* Discover the correct URL of the package to download
*/
function _drush_print_pdf_download_url($library) {
$ret = FALSE;
switch (drupal_strtolower($library)) {
case 'dompdf':
$ret = DOMPDF_DOWNLOAD_URI;
break;
case 'tcpdf':
$ret = TCPDF_DOWNLOAD_URI;
break;
case 'wkhtmltopdf':
switch (drupal_substr(php_uname('s'), 0, 3)) {
case 'Lin':
$ret = (php_uname('m') == 'x86_64') ? WKHTMLTOPDF_AMD64_DOWNLOAD_URI : WKHTMLTOPDF_I386_DOWNLOAD_URI;
break;
case 'Win':
$ret = WKHTMLTOPDF_WIN_DOWNLOAD_URI;
break;
case 'Dar':
$ret = WKHTMLTOPDF_OSX_DOWNLOAD_URI;
break;
default:
drush_log(dt('wkhtmltopdf is not supported in this system, please choose another library.'), 'error');
break;
}
break;
default:
drush_log(dt('Unknown PDF library specified, please use one of the supported PDF libraries.'), 'error');
break;
}
return $ret;
}
/**
* Helper to download and extract the zip/tar archive.
*/
function _drush_print_pdf_download_extract($filename) {
$arch_ret = FALSE;
if (drush_op('is_file', $filename)) {
switch (drush_op('mime_content_type', $filename)) {
case 1:
$arch_ret = TRUE;
break;
case 'application/zip':
// Decompress the zip archive
$arch_ret = drush_shell_exec('unzip -qq -o ' . $filename);
// ZIP archives usually get the access rights wrong
drush_log(dt('@filename is a Zip file. Check the access permissions of the extracted files.', array('@filename' => $filename)), 'warning');
break;
case 'application/x-gzip':
// Decompress the tar gz archive
$arch_ret = drush_shell_exec('tar xzf ' . $filename);
break;
case 'application/x-bzip2':
// Decompress the tar bz2 archive
$arch_ret = drush_shell_exec('tar xjf ' . $filename);
break;
case 'application/x-xz':
// Decompress the tar xz archive
$arch_ret = drush_shell_exec('tar xJf %s', $filename);
break;
}
}
else {
drush_log(dt('@filename not found.', array('@filename' => $filename)), 'error');
}
return $arch_ret;
}
/**
* Download a file using wget or curl
*
* Adapted from a function in drush/includes/drush.inc to support 302 redirects.
*
* @param string $download_url
* The path to the file to download
*
* @return string
* The filename that was downloaded, or NULL if the file could not be
* downloaded.
*/
function _drush_print_pdf_download_file($download_url) {
$wget_ret = drush_shell_exec("wget -nv --trust-server-names %s", $download_url);
if (!drush_get_context('DRUSH_SIMULATE')) {
if ($wget_ret) {
// Get the filename of the saved file from the output
$wget_out = explode('"', array_shift(drush_shell_exec_output()));
$filename = $wget_out[1];
}
else {
$tempnam = uniqid('drush_print_pdf_');
$curl_ret = drush_shell_exec("curl -s -L -o %s %s -w '%%{url_effective}'", $tempnam, $download_url);
if ($curl_ret) {
// File was donwloaded with the tempname
// Find the effective name
$filename = explode('/', array_shift(drush_shell_exec_output()));
$filename = array_pop($filename);
// Rename file from tempname to effective name
if (!drush_op('rename', $tempnam, './' . $filename)) {
$filename = $tempnam;
}
}
else {
$filename = FALSE;
}
}
}
else {
$filename = basename($download_url);
}
return $filename;
}

View file

@ -0,0 +1,12 @@
name = "PDF version"
description = "Adds the capability to export pages as PDF."
dependencies[] = print
core=6.x
package = "Printer, email and PDF versions"
; Information added by Drupal.org packaging script on 2014-04-02
version = "6.x-1.19"
core = "6.x"
project = "print"
datestamp = "1396426748"

View file

@ -0,0 +1,301 @@
<?php
/**
* @file
* Install file of the print_pdf module
*
* @ingroup print
*/
/**
* Implementation of hook_install().
*/
function print_pdf_install() {
drupal_install_schema('print_pdf');
// Module weight
update_sql("UPDATE {system} SET weight = 2 WHERE name = 'print_pdf'");
}
/**
* Implementation of hook_uninstall().
*/
function print_pdf_uninstall() {
drupal_uninstall_schema('print_pdf');
variable_del('print_pdf_settings');
variable_del('print_pdf_show_link');
variable_del('print_pdf_link_pos');
variable_del('print_pdf_link_teaser');
variable_del('print_pdf_node_link_visibility');
variable_del('print_pdf_node_link_pages');
variable_del('print_pdf_link_class');
variable_del('print_pdf_sys_link_visibility');
variable_del('print_pdf_sys_link_pages');
variable_del('print_pdf_book_link');
variable_del('print_pdf_pdf_tool');
variable_del('print_pdf_content_disposition');
variable_del('print_pdf_paper_size');
variable_del('print_pdf_page_orientation');
variable_del('print_pdf_images_via_file');
variable_del('print_pdf_font_family');
variable_del('print_pdf_font_size');
variable_del('print_pdf_link_text');
variable_del('print_pdf_link_use_alias');
variable_del('print_pdf_filename');
variable_del('print_pdf_autoconfig');
variable_del('print_pdf_dompdf_unicode');
variable_del('print_pdf_wkhtmltopdf_options');
variable_del('print_pdf_display_sys_urllist');
$settings = db_query("SELECT name FROM {variable} WHERE name LIKE 'print\_pdf\_display\_%'");
while ($variable = db_fetch_object($settings)) {
variable_del($variable->name);
}
}
/**
* Implementation of hook_schema().
*/
function print_pdf_schema() {
$schema['print_pdf_node_conf'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'link' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
'comments' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
'url_list' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
),
),
'primary key' => array('nid'),
);
$schema['print_pdf_page_counter'] = array(
'fields' => array(
'path' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
),
'totalcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('path'),
);
return $schema;
}
/**
* Update to version 6.x-1.0
*/
function print_pdf_update_6000() {
global $conf;
$ret = array();
if (isset($conf['print_pdf_settings'])) {
$print_pdf_settings = variable_get('print_pdf_settings', '');
variable_set('print_pdf_link_pos', array('link' => ($print_pdf_settings['show_link'] ? 'link' : 0) ));
variable_set('print_pdf_show_link', max(1, $print_pdf_settings['show_link']));
variable_set('print_pdf_node_link_visibility', $print_pdf_settings['node_link_visibility']);
variable_set('print_pdf_node_link_pages', $print_pdf_settings['node_link_pages']);
variable_set('print_pdf_link_class', $print_pdf_settings['link_class']);
variable_set('print_pdf_sys_link_visibility', $print_pdf_settings['sys_link_visibility']);
variable_set('print_pdf_sys_link_pages', $print_pdf_settings['sys_link_pages']);
variable_set('print_pdf_book_link', $print_pdf_settings['book_link']);
variable_set('print_pdf_pdf_tool', $print_pdf_settings['pdf_tool']);
variable_set('print_pdf_content_disposition', $print_pdf_settings['content_disposition']);
variable_set('print_pdf_paper_size', $print_pdf_settings['paper_size']);
variable_set('print_pdf_page_orientation', $print_pdf_settings['page_orientation']);
variable_del('print_pdf_settings');
}
return $ret;
}
/**
* Update to version 6.x-1.1
*/
function print_pdf_update_6001() {
$schema['print_pdf_node_conf'] = array(
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'link' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
'comments' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
'url_list' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '1',
'size' => 'tiny',
),
),
'primary key' => array('nid'),
);
$schema['print_pdf_page_counter'] = array(
'fields' => array(
'path' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
),
'totalcount' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'big',
),
'timestamp' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('path'),
);
$ret = array();
db_create_table($ret, 'print_pdf_node_conf', $schema['print_pdf_node_conf']);
db_create_table($ret, 'print_pdf_page_counter', $schema['print_pdf_page_counter']);
return $ret;
}
/**
* Update to version 6.x-1.2
*/
function print_pdf_update_6003() {
// Delete custom text strings set to the default
$ret = array();
$vars = array(
'print_pdf_link_text' => 'PDF version',
);
$t = get_t();
foreach ($vars as $name => $default) {
if (variable_get($name, '') == $t($default)) {
variable_del($name);
}
}
menu_rebuild();
return $ret;
}
/**
* Update to version 6.x-1.8
*/
function print_pdf_update_6004() {
// add new 'access PDF version' permission to any role which has 'access print'
$ret = array();
$dbret = db_query('SELECT * FROM {permission}');
while ($role = db_fetch_object($dbret)) {
if ((strpos($role->perm, 'access print') !== FALSE)) {
$role->perm = db_escape_string('access PDF version, '. $role->perm);
$ret[] = update_sql("UPDATE {permission} SET perm = '$role->perm' WHERE rid = $role->rid");
}
}
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_pdf_update_6005() {
$ret = array();
variable_del('print_pdf_wkhtmltopdf_xdisplay');
variable_del('print_pdf_xvfb_options');
// BLOCK_CACHE_GLOBAL -> 8
$ret[] = update_sql("UPDATE {blocks} SET cache = 8 WHERE module = 'print_pdf' AND delta = '0'");
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_pdf_update_6006() {
$ret = array();
// Module weight
$ret[] = update_sql("UPDATE {system} SET weight = 2 WHERE name = 'print_pdf'");
return $ret;
}
/**
* Update to version 6.x-1.11
*/
function print_pdf_update_6007() {
$ret = array();
foreach (node_get_types() as $key => $value) {
$print_pdf_display = variable_get('print_pdf_display_'. $value->type, 1);
$print_pdf_display_comment = variable_get('print_pdf_display_comment_'. $value->type, 0);
$print_pdf_display_urllist = variable_get('print_pdf_display_urllist_'. $value->type, 1);
$ret[] = update_sql("UPDATE {print_pdf_node_conf} SET link = (link AND $print_pdf_display), comments = (comments OR $print_pdf_display_comment), url_list = (url_list AND $print_pdf_display_urllist) WHERE nid IN (SELECT nid FROM {node} WHERE type = '$value->type');");
}
return $ret;
}
/**
* Enable block and help area links
*/
function print_pdf_update_6118() {
$ret = array();
$link_pos = variable_get('print_pdf_link_pos', array('link' => 'link', 'block' => 'block', 'help' => 'help'));
$link_pos['block'] = 'block';
$link_pos['help'] = 'help';
variable_set('print_pdf_link_pos', $link_pos);
return $ret;
}

View file

@ -0,0 +1,699 @@
<?php
/**
* @file
* Displays Printer-friendly versions of Drupal pages.
*
* @ingroup print
*/
define('PRINTPDF_PATH', 'printpdf');
define('PRINT_PDF_FORMAT', 'pdf');
define('PRINT_PDF_LIB_PATH', 'sites/all/libraries');
define('PRINT_PDF_LINK_POS_DEFAULT', serialize(array('link' => 'link', 'block' => 'block', 'help' => 'help')));
define('PRINT_PDF_LINK_TEASER_DEFAULT', 0);
define('PRINT_PDF_SHOW_LINK_DEFAULT', 1);
define('PRINT_PDF_NODE_LINK_VISIBILITY_DEFAULT', 0);
define('PRINT_PDF_NODE_LINK_PAGES_DEFAULT', '');
define('PRINT_PDF_LINK_CLASS_DEFAULT', 'print-pdf');
define('PRINT_PDF_SYS_LINK_VISIBILITY_DEFAULT', 1);
define('PRINT_PDF_SYS_LINK_PAGES_DEFAULT', '');
define('PRINT_PDF_LINK_USE_ALIAS_DEFAULT', 0);
define('PRINT_PDF_BOOK_LINK_DEFAULT', 1);
define('PRINT_PDF_PDF_TOOL_DEFAULT', 0);
define('PRINT_PDF_CONTENT_DISPOSITION_DEFAULT', 2);
define('PRINT_PDF_PAPER_SIZE_DEFAULT', 'A4');
define('PRINT_PDF_PAGE_ORIENTATION_DEFAULT', 'portrait');
define('PRINT_PDF_IMAGES_VIA_FILE_DEFAULT', 0);
define('PRINT_PDF_AUTOCONFIG_DEFAULT', 1);
define('PRINT_PDF_FONT_FAMILY_DEFAULT', 'dejavusans');
define('PRINT_PDF_FONT_SIZE_DEFAULT', 10);
define('PRINT_PDF_FONT_SUBSETTING_DEFAULT', FALSE);
define('PRINT_PDF_FILENAME_DEFAULT', '[site-name] - [title] - [mod-yyyy]-[mod-mm]-[mod-dd]');
define('PRINT_PDF_DOMPDF_UNICODE_DEFAULT', 0);
define('PRINT_PDF_WKHTMLTOPDF_OPTIONS', "--footer-font-size 7 --footer-right '[page]'");
define('PRINT_PDF_DOMPDF_CACHE_DIR_DEFAULT', 'print_pdf/dompdf');
define('PRINT_PDF_TCPDF_CACHE_DIR_DEFAULT', 'print_pdf/tcpdf');
/**
* Implementation of hook_perm().
*/
function print_pdf_perm() {
return array('access PDF version');
}
/**
* Implementation of hook_theme().
*/
function print_pdf_theme() {
return array(
'print_pdf_format_link' => array(
'arguments' => array(),
),
'print_pdf_dompdf_footer' => array(
'arguments' => array('html' => ''),
'file' => 'print_pdf.pages.inc',
),
'print_pdf_tcpdf_header' => array(
'arguments' => array('pdf' => NULL, 'html' => '', 'font' => array()),
'file' => 'print_pdf.pages.inc',
),
'print_pdf_tcpdf_page' => array(
'arguments' => array('pdf' => NULL),
'file' => 'print_pdf.pages.inc',
),
'print_pdf_tcpdf_content' => array(
'arguments' => array('pdf' => NULL, 'html' => '', 'font' => array()),
'file' => 'print_pdf.pages.inc',
),
'print_pdf_tcpdf_footer' => array(
'arguments' => array('pdf' => NULL, 'html' => '', 'font' => array()),
'file' => 'print_pdf.pages.inc',
),
'print_pdf_tcpdf_footer2' => array(
'arguments' => array('pdf' => NULL),
'file' => 'print_pdf.pages.inc',
),
);
}
/**
* Implementation of hook_init().
*/
function print_pdf_init() {
if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
$pdf_dirs = array();
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
if (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') {
$pdf_dirs[] = PRINT_PDF_DOMPDF_CACHE_DIR_DEFAULT . '/fonts';
}
elseif (basename($print_pdf_pdf_tool) == 'tcpdf.php') {
foreach (array('cache', 'images') as $dir) {
$pdf_dirs[] = PRINT_PDF_TCPDF_CACHE_DIR_DEFAULT . '/' . $dir;
}
}
if (!empty($pdf_dirs)) {
foreach ($pdf_dirs as $pdf_dir) {
$directory = file_directory_path() . '/' . $pdf_dir;
if (!is_dir($directory)) {
$dir_tmp = '';
foreach (explode('/', $pdf_dir) as $dir) {
$dir_tmp .= $dir . '/';
$directory = file_directory_path() . '/' . $dir_tmp;
file_check_directory($directory, FILE_CREATE_DIRECTORY);
}
}
}
}
}
}
/**
* Implementation of hook_menu().
*/
function print_pdf_menu() {
$items = array();
$items[PRINTPDF_PATH] = array(
'title' => 'Printer-friendly PDF',
'page callback' => 'print_pdf_controller',
'access arguments' => array('access PDF version'),
'type' => MENU_CALLBACK,
'file' => 'print_pdf.pages.inc',
);
$items[PRINTPDF_PATH .'/'. PRINTPDF_PATH] = array(
'access callback' => FALSE,
);
$items['admin/settings/print/pdf'] = array(
'title' => 'PDF',
'description' => 'Configure the settings of the PDF generation functionality.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_pdf_settings'),
'access arguments' => array('administer print'),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
'file' => 'print_pdf.admin.inc',
);
$items['admin/settings/print/pdf/options'] = array(
'title' => 'Options',
'weight' => 1,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/print/pdf/strings'] = array(
'title' => 'Text strings',
'description' => 'Override the user-facing strings used in the PDF version.',
'page callback' => 'drupal_get_form',
'page arguments' => array('print_pdf_strings_settings'),
'access arguments' => array('administer print'),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
'file' => 'print_pdf.admin.inc',
);
return $items;
}
/**
* Implementation of hook_block().
*/
function print_pdf_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$block[0]['info'] = t('Most PDFd');
$block[0]['cache'] = BLOCK_CACHE_GLOBAL;
return $block;
break;
case 'configure':
return '';
case 'save':
return;
case 'view':
switch ($delta) {
case 0:
$block['subject'] = t('Most PDFd');
$result = db_query_range("SELECT path FROM {print_pdf_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);
if (db_affected_rows()) {
$block['content'] = '<div class="item-list"><ul>';
while ($obj = db_fetch_object($result)) {
$block['content'] .= '<li>'. l(_print_get_title($obj->path), $obj->path) .'</li>';
}
$block['content'] .= '</ul></div>';
}
break;
}
return $block;
break;
}
}
/**
* Implementation of hook_requirements().
*/
function print_pdf_requirements($phase) {
$requirements = array();
$t = get_t();
switch ($phase) {
// At runtime, make sure that a PDF generation tool is selected
case 'runtime':
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
if (empty($print_pdf_pdf_tool)) {
$requirements['print_pdf_tool'] = array(
'title' => $t('Printer, email and PDF versions - PDF generation library'),
'value' => $t('No PDF tool selected'),
'description' => $t('Please configure it in the !url.', array('!url' => l($t('PDF settings page'), 'admin/settings/print/pdf'))),
'severity' => REQUIREMENT_ERROR,
);
}
else {
if (!is_file($print_pdf_pdf_tool) || !is_readable($print_pdf_pdf_tool)) {
$requirements['print_pdf_tool'] = array(
'title' => $t('Printer, email and PDF versions - PDF generation library'),
'value' => $t('File not found'),
'description' => $t('The currently selected PDF generation library (%file) is no longer accessible.', array('%file' => $print_pdf_pdf_tool)),
'severity' => REQUIREMENT_ERROR,
);
}
elseif (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') {
if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
$directory = file_directory_path() . '/' . PRINT_PDF_DOMPDF_CACHE_DIR_DEFAULT . '/fonts';
if (!is_dir($directory) || !is_writable($directory)) {
$requirements['print_pdf_tool'] = array(
'title' => $t('DOMPDF font cache directory'),
'value' => $t('Non-writable permissions'),
'description' => $t('You must change the %fontdir permissions to be writable, as dompdf requires write-access to that directory.', array('%fontdir' => $directory)),
'severity' => REQUIREMENT_ERROR,
);
}
}
}
elseif (basename($print_pdf_pdf_tool) == 'tcpdf.php') {
$version = _print_pdf_tcpdf_version();
if (version_compare($version, '5.9.001', '<')) {
$requirements['print_pdf_tool'] = array(
'title' => $t('Printer, email and PDF versions - PDF generation library'),
'value' => $t('Unsupported TCPDF version'),
'description' => $t('The currently selected version of TCPDF (@version) is not supported. Please update to a !url.', array('@version' => $version, '!url' => l($t('newer version'), 'http://sourceforge.net/projects/tcpdf/files/latest'))),
'severity' => REQUIREMENT_ERROR,
);
}
else {
$requirements['print_pdf_tool'] = array(
'title' => $t('Printer, email and PDF versions - PDF generation library'),
'value' => $t('TCPDF') . ' ' . $version,
);
}
if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
foreach (array('cache', 'images') as $dir) {
$directory = file_directory_path() . '/' . PRINT_PDF_TCPDF_CACHE_DIR_DEFAULT . '/' . $dir;
if (!is_dir($directory) || !is_writable($directory)) {
$requirements['print_pdf_tool_'. $dir] = array(
'title' => $t('TCPDF directory'),
'value' => $t('Non-writable permissions'),
'description' => $t('You must change the %fontdir permissions to be writable, as TCPDF requires write-access to that directory.', array('%fontdir' => $directory)),
'severity' => REQUIREMENT_ERROR,
);
}
}
}
}
elseif (drupal_substr(basename($print_pdf_pdf_tool, '.exe'), 0, 11) == 'wkhtmltopdf') {
if (function_exists('is_executable') && !is_executable($print_pdf_pdf_tool)) {
$requirements['print_pdf_tool'] = array(
'title' => $t('wkhtmltopdf library'),
'value' => $t('Non-executable permissions'),
'description' => $t('You must modify the permissions of the wkhtmltopdf file (%file) to make it executable.', array('%file' => $print_pdf_pdf_tool)),
'severity' => REQUIREMENT_ERROR,
);
}
else {
$version = _print_pdf_wkhtmltopdf_version();
if (version_compare($version, '0.9.6', '<')) {
$requirements['print_pdf_tool'] = array(
'title' => $t('Printer, email and PDF versions - PDF generation library'),
'value' => $t('Unsupported wkhtmltopdf version'),
'description' => $t('The currently selected version of wkhtmltopdf (@version) is not supported. Please update to a !url.', array('@version' => $version, '!url' => l($t('newer version'), 'http://code.google.com/p/wkhtmltopdf/'))),
'severity' => REQUIREMENT_ERROR,
);
}
else {
$requirements['print_pdf_tool'] = array(
'title' => $t('Printer, email and PDF versions - PDF generation library'),
'value' => $t('wkhtmltopdf') . ' ' . $version,
);
}
}
}
}
break;
}
return $requirements;
}
/**
* Implementation of hook_link().
*/
function print_pdf_link($type, $node = NULL, $teaser = FALSE) {
$print_pdf_link_pos = variable_get('print_pdf_link_pos', unserialize(PRINT_PDF_LINK_POS_DEFAULT));
$print_pdf_link_use_alias = variable_get('print_pdf_link_use_alias', PRINT_PDF_LINK_USE_ALIAS_DEFAULT);
$allowed_type = print_pdf_link_allowed(array('type' => $type, 'node' => $node, 'teaser' => $teaser));
if (($allowed_type) && !empty($print_pdf_link_pos['link'])) {
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$links = array();
$format = theme('print_pdf_format_link');
// Show book link
if ($allowed_type === PRINT_ALLOW_BOOK_LINK) {
$links['book_pdf'] = array('href' => PRINTPDF_PATH .'/book/export/html/'. $node->nid,
'title' => $format['text'],
'attributes' => $format['attributes'],
'html' => $format['html'],
);
return $links;
}
elseif ($allowed_type === PRINT_ALLOW_NORMAL_LINK) {
$query_arr = $_GET;
if ($type == 'comment') {
$query_arr['comment'] = $node->cid;
}
$query = print_query_string_encode($query_arr, array('q'));
if (empty($query)) $query = NULL;
if (($print_pdf_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/'. $node->nid))) {
$path = $alias;
}
else {
$path = $node->nid;
}
$links['print_pdf'] = array('href' => PRINTPDF_PATH .'/'. $path,
'title' => $format['text'],
'attributes' => $format['attributes'],
'html' => $format['html'],
'query' => $query,
);
return $links;
}
}
else {
return;
}
}
/**
* Implementation of hook_help().
*/
function print_pdf_help($path, $arg) {
$print_pdf_link_pos = variable_get('print_pdf_link_pos', unserialize(PRINT_PDF_LINK_POS_DEFAULT));
if (($path !== 'node/%') && !(empty($print_pdf_link_pos['help']))) {
static $output = FALSE;
if ($output === FALSE) {
$output = TRUE;
$link = print_pdf_insert_link();
if ($link) {
return "<span class='print-syslink'>$link</span>";
}
}
}
}
/**
* Implementation of hook_nodeapi().
*/
function print_pdf_nodeapi(&$node, $op = 'view', $teaser, $page) {
switch ($op) {
case 'view':
// Insert content corner links
$print_pdf_link_pos = variable_get('print_pdf_link_pos', unserialize(PRINT_PDF_LINK_POS_DEFAULT));
if (($teaser === FALSE) && !empty($print_pdf_link_pos['corner']) &&
isset($node->build_mode) && ($node->build_mode === NODE_BUILD_NORMAL)) {
$node->content['print_links']['#value'] .= print_pdf_insert_link(NULL, $node);
}
break;
case 'load':
$res = db_fetch_object(db_query("SELECT link, comments, url_list FROM {print_pdf_node_conf} WHERE nid = %d", $node->nid));
$node->print_pdf_display = $res ? intval($res->link) : variable_get('print_pdf_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$node->print_pdf_display_comment = $res ? intval($res->comments) : variable_get('print_pdf_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$node->print_pdf_display_urllist = $res ? intval($res->url_list) : variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
break;
case 'insert':
case 'update':
if (user_access('administer print') || user_access('node-specific print configuration')) {
if (!isset($node->print_pdf_display)) $node->print_pdf_display = variable_get('print_pdf_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
if (!isset($node->print_pdf_display_comment)) $node->print_pdf_display_comment = variable_get('print_pdf_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
if (!isset($node->print_pdf_display_urllist)) $node->print_pdf_display_urllist = variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
_print_pdf_node_conf_modify($node->nid, $node->print_pdf_display, $node->print_pdf_display_comment, $node->print_pdf_display_urllist);
}
break;
case 'delete':
db_query("DELETE FROM {print_pdf_node_conf} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {print_pdf_page_counter} WHERE path = 'node/%d'", $node->nid);
break;
}
}
/**
* Implementation of hook_form_alter().
*/
function print_pdf_form_alter(&$form, $form_state, $form_id) {
// Add the node-type settings option to activate the PDF version link
if ((user_access('administer print') || user_access('node-specific print configuration')) && (($form_id == 'node_type_form') ||
(isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id))) {
$form['print']['pdf_label'] = array(
'#type' => 'markup',
'#value' => '<p><strong>'. t('PDF version') .'</strong></p>',
);
$form['print']['print_pdf_display'] = array(
'#type' => 'checkbox',
'#title' => t('Show link'),
);
$form['print']['print_pdf_display_comment'] = array(
'#type' => 'checkbox',
'#title' => t('Show link in individual comments'),
);
$form['print']['print_pdf_display_urllist'] = array(
'#type' => 'checkbox',
'#title' => t('Show Printer-friendly URLs list'),
);
if ($form_id == 'node_type_form') {
$form['print']['print_pdf_display']['#default_value'] = variable_get('print_pdf_display_'. $form['#node_type']->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$form['print']['print_pdf_display_comment']['#default_value'] = variable_get('print_pdf_display_comment_'. $form['#node_type']->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$form['print']['print_pdf_display_urllist']['#default_value'] = variable_get('print_pdf_display_urllist_'. $form['#node_type']->type, PRINT_TYPE_URLLIST_DEFAULT);
}
else {
$node = $form['#node'];
$form['print']['print_pdf_display']['#default_value'] = isset($node->print_pdf_display) ? $node->print_pdf_display : variable_get('print_pdf_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
$form['print']['print_pdf_display_comment']['#default_value'] = isset($node->print_pdf_display_comment) ? $node->print_pdf_display_comment : variable_get('print_pdf_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
$form['print']['print_pdf_display_urllist']['#default_value'] = isset($node->print_pdf_display_urllist) ? $node->print_pdf_display_urllist : variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
}
}
}
/**
* Update the print_pdf_node_conf table to reflect the given attributes
*
* If updating to the default values, delete the record.
*
* @param $nid
* value of the nid field (primary key)
* @param $link
* value of the link field (0 or 1)
* @param $comments
* value of the comments field (0 or 1)
* @param $url_list
* value of the url_list field (0 or 1)
*/
function _print_pdf_node_conf_modify($nid, $link, $comments, $url_list) {
db_query("UPDATE {print_pdf_node_conf} SET link = %d, comments = %d, url_list = %d WHERE nid = %d", $link, $comments, $url_list, $nid);
if (!db_affected_rows()) {
@db_query("INSERT INTO {print_pdf_node_conf} (nid, link, comments, url_list) VALUES (%d, %d, %d, %d)", $nid, $link, $comments, $url_list);
}
}
/**
* Format the PDF version link
*
* @return
* array of formatted attributes
* @ingroup themeable
*/
function theme_print_pdf_format_link() {
$print_pdf_link_class = variable_get('print_pdf_link_class', PRINT_PDF_LINK_CLASS_DEFAULT);
$print_pdf_content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT);
$print_pdf_show_link = variable_get('print_pdf_show_link', PRINT_PDF_SHOW_LINK_DEFAULT);
$print_pdf_link_text = filter_xss(variable_get('print_pdf_link_text', t('PDF version')));
$img = drupal_get_path('module', 'print') .'/icons/pdf_icon.gif';
$title = t('Display a PDF version of this page.');
$class = strip_tags($print_pdf_link_class);
$new_window = ($print_pdf_content_disposition == 1);
$format = _print_format_link_aux($print_pdf_show_link, $print_pdf_link_text, $img);
return array('text' => $format['text'],
'html' => $format['html'],
'attributes' => print_fill_attributes($title, $class, $new_window),
);
}
/**
* Auxiliary function to display a formatted PDF version link
*
* Function made available so that developers may call this function from
* their defined pages/blocks.
*
* @param $path
* path of the original page (optional). If not specified, the current URL
* is used
* @param $node
* an optional node object, to be used in defining the path, if used, the
* path argument is irrelevant
* @return
* string with the HTML link to the printer-friendly page
*/
function print_pdf_insert_link($path = NULL, $node = NULL) {
if ($node !== NULL) {
$nid = $node->nid;
$path = 'node/'. $nid;
$allowed_type = print_pdf_link_allowed(array('node' => $node));
}
else {
if ($path === NULL) {
$nid = preg_replace('!^node/([\d]+)!', '$1', $_GET['q']);
$path = $_GET['q'];
}
else {
$nid = NULL;
}
$allowed_type = print_pdf_link_allowed(array('path' => $path));
}
if ($allowed_type) {
if ($nid !== NULL) {
if ($allowed_type === PRINT_ALLOW_BOOK_LINK) {
$path = 'book/export/html/'. $nid;
}
else {
if (variable_get('print_pdf_link_use_alias', PRINT_PDF_LINK_USE_ALIAS_DEFAULT) && ($alias = drupal_lookup_path('alias', $path))) {
$path = $alias;
}
else {
$path = $nid;
}
}
$path = PRINTPDF_PATH .'/'. $path;
$query = print_query_string_encode($_GET, array('q'));
if (empty($query)) {
$query = NULL;
}
}
else {
$query = NULL;
}
drupal_add_css(drupal_get_path('module', 'print') .'/css/printlinks.css');
$format = theme('print_pdf_format_link');
return '<span class="print_pdf">'. l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) .'</span>';
}
else {
return FALSE;
}
}
/**
* Check if the link to the PDF version is allowed depending on the settings
*
* @param $args
* array containing the possible parameters:
* teaser, node, type, path
* @return
* FALSE if not allowed
* PRINT_ALLOW_NORMAL_LINK if a normal link is allowed
* PRINT_ALLOW_BOOK_LINK if a link is allowed in a book node
*/
function print_pdf_link_allowed($args) {
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
if ((!empty($args['teaser']) && !variable_get('print_pdf_link_teaser', PRINT_PDF_LINK_TEASER_DEFAULT))
|| !user_access('access PDF version') || (empty($print_pdf_pdf_tool))) {
// If the teaser link is disabled or the user is not allowed
return FALSE;
}
if (!empty($args['path'])) {
$nid = preg_replace('!^node/!', '', drupal_get_normal_path($args['path']));
if (ctype_digit($nid)) {
$args['node'] = node_load($nid);
}
}
if (!empty($args['node'])) {
static $node_type = FALSE;
$node = $args['node'];
if (isset($node->type)) {
$node_type = $node->type;
}
// Node
$print_pdf_node_link_visibility = variable_get('print_pdf_node_link_visibility', PRINT_PDF_NODE_LINK_VISIBILITY_DEFAULT);
$print_pdf_node_link_pages = variable_get('print_pdf_node_link_pages', PRINT_PDF_NODE_LINK_PAGES_DEFAULT);
if (!_print_page_match($print_pdf_node_link_visibility, "node/". $node->nid, $print_pdf_node_link_pages)) {
// Page not in visibility list
return FALSE;
}
elseif (isset($args['type']) && ($args['type'] == 'comment') && isset($node_type)) {
// Link is for a comment, return the configured setting
// Cache this statically to avoid duplicate queries for every comment.
static $res = array();
if (!isset($res[$node->nid])) {
$res[$node->nid] = db_fetch_object(db_query("SELECT comments FROM {print_pdf_node_conf} WHERE nid = %d", $node->nid));
}
$print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? intval($res[$node->nid]->comments) : variable_get('print_pdf_display_comment_'. $node_type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
if ($print_display_comment) {
return PRINT_ALLOW_NORMAL_LINK;
}
}
else {
// Node link
if (isset($node->print_pdf_display) && !$node->print_pdf_display) {
// Link for this node is disabled
return FALSE;
}
elseif (isset($node->book)) {
// Node is a book;
$print_pdf_book_link = variable_get('print_pdf_book_link', PRINT_PDF_BOOK_LINK_DEFAULT);
switch ($print_pdf_book_link) {
case 1:
if (user_access('access printer-friendly version')) {
return PRINT_ALLOW_BOOK_LINK;
}
break;
case 2:
return PRINT_ALLOW_NORMAL_LINK;
}
}
else {
return PRINT_ALLOW_NORMAL_LINK;
}
}
}
else {
// 'System' page
$print_pdf_sys_link_visibility = variable_get('print_pdf_sys_link_visibility', PRINT_PDF_SYS_LINK_VISIBILITY_DEFAULT);
$print_pdf_sys_link_pages = variable_get('print_pdf_sys_link_pages', PRINT_PDF_SYS_LINK_PAGES_DEFAULT);
return _print_page_match($print_pdf_sys_link_visibility, $_GET['q'], $print_pdf_sys_link_pages);
}
return FALSE;
}
/**
* Find out the version of the TCPDF library
*/
function _print_pdf_tcpdf_version() {
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
// prevent TCPDF default configs
define('K_TCPDF_EXTERNAL_CONFIG', TRUE);
}
require_once($print_pdf_pdf_tool);
// Hide warnings, as some TCPDF constants may still be undefined
if (class_exists('TCPDF')) {
@$pdf = new TCPDF();
if (class_exists('TCPDF_STATIC')) {
return TCPDF_STATIC::getTCPDFVersion();
}
elseif (method_exists($pdf, 'getTCPDFVersion')) {
return $pdf->getTCPDFVersion();
}
elseif (defined('PDF_PRODUCER')) {
sscanf(PDF_PRODUCER, "TCPDF %s", $version);
return $version;
}
}
return 'unknown';
}
/**
* Find out the version of the wkhtmltopdf library
*/
function _print_pdf_wkhtmltopdf_version() {
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
$descriptor = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
$cmd = '"'. realpath($print_pdf_pdf_tool) .'" --version';
$process = proc_open($cmd, $descriptor, $pipes, NULL, NULL);
if (is_resource($process)) {
$content = stream_get_contents($pipes[1]);
$out = preg_match('!.*?(\d+\.\d+\.\d+).*$!m', $content, $matches);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$retval = proc_close($process);
}
return ($matches[1]);
}
/**
* Implements hook_views_api().
*/
function print_pdf_views_api() {
return array(
'api' => 2.0,
'path' => drupal_get_path('module', 'print_pdf'),
);
}

View file

@ -0,0 +1,653 @@
<?php
/**
* @file
* Generates the PDF versions of the pages
*
* This file is included by the print_pdf module and includes the
* functions that interface with the PDF generation packages.
*
* @ingroup print
*/
module_load_include('inc', 'print', 'print.pages');
/**
* Generate a PDF version of the printer-friendly page
*
* @see print_controller()
* @see _print_pdf_dompdf()
* @see _print_pdf_tcpdf()
*/
function print_pdf_controller() {
// Disable caching for generated PDFs, as Drupal doesn't ouput the proper headers from the cache
$GLOBALS['conf']['cache'] = FALSE;
$args = func_get_args();
$path = filter_xss(implode('/', $args));
$cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;
if (!empty($path)) {
if ($alias = drupal_lookup_path('source', $path)) {
// Alias
$path_arr = explode('/', $alias);
$node = node_load($path_arr[1]);
}
elseif (ctype_digit($args[0])) {
// normal nid
$node = node_load($args[0]);
}
$pdf_filename = variable_get('print_pdf_filename', PRINT_PDF_FILENAME_DEFAULT);
if (module_exists('token')) {
if (!empty($pdf_filename) && !empty($node)) {
$pdf_filename = token_replace($pdf_filename, 'node', $node, TOKEN_PREFIX, TOKEN_SUFFIX, array('clear' => TRUE));
}
else {
$pdf_filename = token_replace($pdf_filename, 'global', NULL, TOKEN_PREFIX, TOKEN_SUFFIX, array('clear' => TRUE));
if (empty($pdf_filename)) {
// If empty, use a fallback solution
$pdf_filename = str_replace('/', '_', $path);
}
}
}
}
else {
$pdf_filename = 'page';
}
if (function_exists('transliteration_clean_filename')) {
$pdf_filename = transliteration_clean_filename($pdf_filename, language_default('language'));
}
drupal_alter('print_pdf_filename', $pdf_filename, $path);
$pdf = print_pdf_generate_path($path, $cid, $pdf_filename . '.pdf');
if ($pdf == NULL) {
drupal_goto($path);
exit;
}
$nodepath = (isset($node->path) && is_string($node->path)) ? drupal_get_normal_path($node->path) : 'node/'. $path;
db_query("UPDATE {print_pdf_page_counter} SET totalcount = totalcount + 1, timestamp = %d WHERE path = '%s'", time(), $nodepath);
// If we affected 0 rows, this is the first time viewing the node.
if (!db_affected_rows()) {
// We must create a new row to store counters for the new node.
db_query("INSERT INTO {print_pdf_page_counter} (path, totalcount, timestamp) VALUES ('%s', 1, %d)", $nodepath, time());
}
}
function print_pdf_generate_path($path, $cid = NULL, $pdf_filename = NULL) {
global $base_url;
$print = print_controller($path, $cid, PRINT_PDF_FORMAT);
if ($print === FALSE) {
return;
}
// Img elements must be set to absolute
$pattern = '!<(img\s[^>]*?)>!is';
$print['content'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['content']);
$print['logo'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['logo']);
$print['footer_message'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['footer_message']);
// Send to printer option causes problems with PDF
$print['sendtoprinter'] = '';
$node = $print['node'];
$html = theme('print_page', $print, PRINT_PDF_FORMAT, $node);
$html = drupal_final_markup($html);
// Convert the a href elements, to make sure no relative links remain
$pattern = '!<(a\s[^>]*?)>!is';
$html = preg_replace_callback($pattern, '_print_rewrite_urls', $html);
// And make anchor links relative again, to permit in-PDF navigation
$html = preg_replace("!${base_url}/". PRINTPDF_PATH .'/.*?#!', '#', $html);
return print_pdf_generate_html($print, $html, $pdf_filename);
}
function print_pdf_generate_html($print, $html, $filename = NULL) {
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
if (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') {
return _print_pdf_dompdf($print, $html, $filename);
}
elseif (basename($print_pdf_pdf_tool) == 'tcpdf.php') {
return _print_pdf_tcpdf($print, $html, $filename);
}
elseif (drupal_substr(basename($print_pdf_pdf_tool, '.exe'), 0, 11) == 'wkhtmltopdf') {
return _print_pdf_wkhtmltopdf($print, $html, $filename);
}
elseif ($filename) {
return drupal_not_found();
}
return NULL;
}
/**
* Convert image paths to the file:// protocol
*
* In some Drupal setups, the use of the 'private' filesystem or Apache's
* configuration prevent access to the images of the page. This function
* tries to circumnvent those problems by accessing files in the local
* filesystem.
*
* @param $html
* contents of the post-processed template already with the node data
* @see print_pdf_controller()
*/
function _print_pdf_file_access_images($html) {
global $base_url, $language;
$print_pdf_images_via_file = variable_get('print_pdf_images_via_file', PRINT_PDF_IMAGES_VIA_FILE_DEFAULT);
switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
case LANGUAGE_NEGOTIATION_PATH:
$lang = $language->language;
break;
default:
$lang = '';
break;
}
// Always convert private to local paths
$file_downloads = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC);
if ($file_downloads == FILE_DOWNLOADS_PRIVATE) {
$pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?system/files/([^>]*?>)!is";
$replacement = '$1file://'. realpath(file_directory_path()) .'/$2';
$html = preg_replace($pattern, $replacement, $html);
}
elseif ($print_pdf_images_via_file) {
$pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?([^>]*?>)!is";
$replacement = '$1file://'. dirname($_SERVER['SCRIPT_FILENAME']) .'/$2';
$html = preg_replace($pattern, $replacement, $html);
}
return $html;
}
/**
* Generate the PDF file using the dompdf library
*
* @param $print
* array containing the configured data
* @param $html
* contents of the post-processed template already with the node data
* @param $filename
* name of the PDF file to be generated
* @see print_pdf_controller()
*/
function _print_pdf_dompdf($print, $html, $filename = NULL) {
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
$print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
$print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
$print_pdf_content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT);
if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
if (!defined('DOMPDF_ENABLE_PHP')) define("DOMPDF_ENABLE_PHP", FALSE);
if (!defined('DOMPDF_ENABLE_REMOTE')) define("DOMPDF_ENABLE_REMOTE", TRUE);
if (!defined('DOMPDF_TEMP_DIR')) define("DOMPDF_TEMP_DIR", file_directory_temp());
if (!defined('DOMPDF_UNICODE_ENABLED')) define("DOMPDF_UNICODE_ENABLED", variable_get('print_pdf_dompdf_unicode', PRINT_PDF_DOMPDF_UNICODE_DEFAULT));
if (!defined('DOMPDF_FONT_CACHE')) define("DOMPDF_FONT_CACHE", file_directory_path() . '/' . PRINT_PDF_DOMPDF_CACHE_DIR_DEFAULT . '/fonts/');
}
require_once($print_pdf_pdf_tool);
if (function_exists('spl_autoload_register')) {
spl_autoload_register('DOMPDF_autoload');
}
// Try to use local file access for image files
$html = _print_pdf_file_access_images($html);
// Spaces in img URLs must be replaced with %20
$pattern = '!<(img\s[^>]*?)>!is';
$html = preg_replace_callback($pattern, '_print_replace_spaces', $html);
// dompdf seems to have problems with something in system.css so let's not use it
$html = preg_replace('!<link.*?modules/system/system.css.*?/>!', '', $html);
$url_array = parse_url($print['url']);
$protocol = $url_array['scheme'] .'://';
$host = $url_array['host'];
$path = dirname($url_array['path']) .'/';
$dompdf = new DOMPDF();
$dompdf->set_base_path($path);
$dompdf->set_host($host);
$dompdf->set_paper(drupal_strtolower($print_pdf_paper_size), $print_pdf_page_orientation);
$dompdf->set_protocol($protocol);
// dompdf can't handle footers cleanly, so disable the following
// $html = theme('print_pdf_dompdf_footer', $html);
// If dompdf Unicode support is disabled, try to convert to ISO-8859-1 and then to HTML entities
if (!variable_get('print_pdf_dompdf_unicode', PRINT_PDF_DOMPDF_UNICODE_DEFAULT)) {
// Convert the euro sign to an HTML entity
$html = str_replace('€', '&#0128;', $html);
// Convert from UTF-8 to ISO 8859-1 and then to HTML entities
if (function_exists('utf8_decode')) {
$html = utf8_decode($html);
}
// iconv fails silently when it encounters something that it doesn't know, so don't use it
// else if (function_exists('iconv')) {
// $html = iconv('UTF-8', 'ISO-8859-1', $html);
// }
elseif (function_exists('mb_convert_encoding')) {
$html = mb_convert_encoding($html, 'ISO-8859-1', 'UTF-8');
}
elseif (function_exists('recode_string')) {
$html = recode_string('UTF-8..ISO_8859-1', $html);
}
$html = htmlspecialchars_decode(htmlentities($html, ENT_NOQUOTES, 'ISO-8859-1'), ENT_NOQUOTES);
}
else {
// Otherwise, ensure the content is properly formatted Unicode.
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
}
// Must get rid of tbody (dompdf goes into recursion)
$html = preg_replace('!<tbody[^>]*?>|</tbody>!i', '', $html);
$dompdf->load_html($html);
$dompdf->render();
if ($filename) {
$dompdf->stream($filename, array('Attachment' => ($print_pdf_content_disposition == 2)));
return TRUE;
}
else {
return $dompdf->output();
}
}
/**
* Generate the PDF file using the TCPDF library
*
* @param $print
* array containing the configured data
* @param $html
* contents of the post-processed template already with the node data
* @param $filename
* name of the PDF file to be generated
* @see print_pdf_controller()
*/
function _print_pdf_tcpdf($print, $html, $filename = NULL) {
global $base_url, $language;
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
$print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
$print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
$print_pdf_content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT);
$pdf_tool_path = realpath(dirname($print_pdf_pdf_tool));
if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
if (!defined('K_TCPDF_EXTERNAL_CONFIG')) define('K_TCPDF_EXTERNAL_CONFIG', TRUE);
if (!defined('K_PATH_MAIN')) define('K_PATH_MAIN', dirname($_SERVER['SCRIPT_FILENAME']));
if (!defined('K_PATH_URL')) define('K_PATH_URL', $base_url);
if (!defined('K_PATH_FONTS')) define('K_PATH_FONTS', $pdf_tool_path .'/fonts/');
if (!defined('K_PATH_CACHE')) define('K_PATH_CACHE', file_directory_path() . '/' . PRINT_PDF_TCPDF_CACHE_DIR_DEFAULT . '/cache/');
if (!defined('K_PATH_IMAGES')) define('K_PATH_IMAGES', '');
if (!defined('K_BLANK_IMAGE')) define('K_BLANK_IMAGE', $pdf_tool_path .'/images/_blank.png');
if (!defined('K_CELL_HEIGHT_RATIO')) define('K_CELL_HEIGHT_RATIO', 1.25);
if (!defined('K_SMALL_RATIO')) define('K_SMALL_RATIO', 2/3);
}
// Try to use local file access for image files
$html = _print_pdf_file_access_images($html);
// Decode HTML entities in image filenames
$pattern = "!<img\s[^>]*?src\s*?=\s*?['\"]?{$base_url}[^>]*?>!is";
$html = preg_replace_callback($pattern, create_function('$matches', 'return html_entity_decode($matches[0], ENT_QUOTES);'), $html);
// Remove queries from the image URL
$pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?{$base_url}[^>]*?)(?:%3F|\?)[^\s'\"]+([^>]*?>)!is";
$html = preg_replace($pattern, '$1$2', $html);
require_once($print_pdf_pdf_tool);
if (defined('PDF_PRODUCER') && (strpos(PDF_PRODUCER, 'PHP4') !== FALSE)) {
module_load_include('inc', 'print_pdf', 'print_pdf.class_php4');
}
else {
module_load_include('inc', 'print_pdf', 'print_pdf.class');
}
$font = Array(
check_plain(variable_get('print_pdf_font_family', PRINT_PDF_FONT_FAMILY_DEFAULT)),
'',
check_plain(variable_get('print_pdf_font_size', PRINT_PDF_FONT_SIZE_DEFAULT)),
);
$orientation = drupal_strtoupper($print_pdf_page_orientation[0]);
// create new PDF document
$pdf = new PrintTCPDF($orientation , 'mm', $print_pdf_paper_size, TRUE);
// set document information
if (isset($print['submitted'])) {
$pdf->SetAuthor(strip_tags($print['submitted']));
}
$pdf->SetCreator(variable_get('site_name', 'Drupal'));
$pdf->SetTitle(html_entity_decode($print['title'], ENT_QUOTES, 'UTF-8'));
if (isset($print['taxonomy'])) {
$keys = implode(' ', explode("\n", trim(strip_tags($print['taxonomy']))));
$pdf->SetKeywords($keys);
}
$pdf->setPDFVersion('1.6');
$pdf->setFontSubsetting(variable_get('print_pdf_font_subsetting', PRINT_PDF_FONT_SUBSETTING_DEFAULT));
$pdf->setTcpdfLink(false);
if ($language->direction == LANGUAGE_RTL) {
$pdf->setRTL(TRUE);
}
$pdf = theme('print_pdf_tcpdf_header', $pdf, $html, $font);
$pdf = theme('print_pdf_tcpdf_footer', $pdf, $html, $font);
$pdf = theme('print_pdf_tcpdf_page', $pdf);
// add a page
$pdf->AddPage();
$pdf = theme('print_pdf_tcpdf_content', $pdf, $html, $font);
// reset pointer to the last page
$pdf->lastPage();
// try to recover from any warning/error
ob_clean();
if ($filename) {
// Close and output PDF document
$output_dest = ($print_pdf_content_disposition == 2) ? 'D' : 'I';
$pdf->Output($filename, $output_dest);
return TRUE;
}
else {
return $pdf = $pdf->Output('', 'S');
}
}
/**
* Generate the PDF file using wkhtmltopdf
*
* @param $print
* array containing the configured data
* @param $html
* contents of the post-processed template already with the node data
* @param $filename
* name of the PDF file to be generated
* @see print_pdf_controller()
*/
function _print_pdf_wkhtmltopdf($print, $html, $filename = NULL) {
$print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
$print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
$print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
$print_pdf_content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT);
$print_pdf_wkhtmltopdf_options = variable_get('print_pdf_wkhtmltopdf_options', PRINT_PDF_WKHTMLTOPDF_OPTIONS);
$dpi = 96;
if (function_exists('token_eplace') && !empty($print_pdf_wkhtmltopdf_options)) {
$print_pdf_wkhtmltopdf_options = token_replace($print_pdf_wkhtmltopdf_options, 'node', $print['node'], TOKEN_PREFIX, TOKEN_SUFFIX, array('clear' => TRUE));
}
$version = _print_pdf_wkhtmltopdf_version();
// 0.10.0 beta2 identifies itself as 0.9.9
if (version_compare($version, '0.9.9', '>=')) {
$print_pdf_wkhtmltopdf_options = '--disable-local-file-access '. $print_pdf_wkhtmltopdf_options;
}
elseif (version_compare($version, '0.9.6', '>=')) {
$print_pdf_wkhtmltopdf_options = '--disallow-local-file-access '. $print_pdf_wkhtmltopdf_options;
}
else {
drupal_goto($print['url']);
exit;
}
$descriptor = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'a'));
$cmd = '"'. realpath($print_pdf_pdf_tool) ."\" --page-size $print_pdf_paper_size --orientation $print_pdf_page_orientation --dpi $dpi $print_pdf_wkhtmltopdf_options - -";
$process = proc_open($cmd, $descriptor, $pipes, NULL, NULL);
if (is_resource($process)) {
fwrite($pipes[0], $html);
fclose($pipes[0]);
$pdf = stream_get_contents($pipes[1]);
fclose($pipes[1]);
stream_set_blocking($pipes[2], 0);
$error = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$retval = proc_close($process);
if (!empty($error) || ($retval != 0)) {
if (empty($error)) {
$error = 'No stderr output available.';
}
watchdog('print_pdf', 'wkhtmltopdf [%cmd] (returned %ret): %error', array('%cmd' => $cmd, '%ret' => $retval, '%error' => $error));
}
}
if (!empty($pdf)) {
if ($filename) {
if (headers_sent()) {
exit("Unable to stream pdf: headers already sent");
}
header("Cache-Control: private");
header("Content-Type: application/pdf");
$attachment = ($print_pdf_content_disposition == 2) ? "attachment" : "inline";
header("Content-Disposition: $attachment; filename=\"$filename\"");
echo $pdf;
flush();
return TRUE;
}
else {
return $pdf;
}
}
else {
drupal_set_message('Unable to generate PDF file.', 'error');
drupal_goto($meta['url']);
return NULL;
}
}
/**
* Format the dompdf footer contents
*
* @param $html
* contents of the body of the HTML from the original node
* @see theme_print_pdf_tcpdf_footer()
*/
function theme_print_pdf_dompdf_footer($html) {
preg_match('!<div class="print-footer">(.*?)</div>!si', $html, $tpl_footer);
if (isset($tpl_footer[1])) {
$html = str_replace($tpl_footer[0], '', $html);
$text = '<script type="text/php">
if (isset($pdf)) {
$font = Font_Metrics::get_font("verdana");;
$size = 10;
$color = array(0,0,0);
$text_height = Font_Metrics::get_font_height($font, $size);
$w = $pdf->get_width();
$h = $pdf->get_height();
$footer = $pdf->open_object();
// Draw a line along the bottom
$y = $h - 25;
$pdf->line(15, $y, $w - 15, $y, $color, 1);
$y += $text_height / 2;
$pdf->page_text(15, $y, \''. addslashes(strip_tags($tpl_footer[1])) .'\', $font, $size, $color);
$pdf->close_object();
$pdf->add_object($footer, "all");
// Center the text
$width = Font_Metrics::get_text_width("Page 1 of 2", $font, $size);
$pagenumtxt = t("Page !n of !total", array("!n" => "{PAGE_NUM}", "!total" => "{PAGE_COUNT}"));
$pdf->page_text($w - 15 - $width, $y, $pagenumtxt, $font, $size, $color);
}
</script>';
return str_replace("<body>", "<body>" . $text, $html);
} else {
return $html;
}
}
/**
* Format the TCPDF header
*
* @param $pdf
* current TCPDF object
* @param $html
* contents of the body of the HTML from the original node
* @param $font
* array with the font definition (font name, styles and size)
* @see theme_print_pdf_tcpdf_header()
*/
function theme_print_pdf_tcpdf_header($pdf, $html, $font) {
preg_match('!<div class="print-logo">(.*?)</div>!si', $html, $tpl_logo);
preg_match('!<h1 class="print-title">(.*?)</h1>!si', $html, $tpl_title);
preg_match('!<div class="print-site_name">(.*?)</div>!si', $html, $tpl_site_name);
$ratio = 0;
$logo = '';
if (isset($tpl_logo[1]) && preg_match('!src\s*=\s*(?:"(.*?)"|\'(.*?)\'|([^\s]*))!i', $tpl_logo[1], $logo_url)) {
$logo = $logo_url[1];
if (!empty($logo)) {
$size = getimagesize($logo);
$ratio = $size ? ($size[0] / $size[1]) : 0;
}
}
// set header font
$pdf->setHeaderFont($font);
// set header margin
$pdf->setHeaderMargin(5);
// set header data
$pdf->setHeaderData($logo, 10 * $ratio, html_entity_decode($tpl_title[1], ENT_QUOTES, 'UTF-8'), html_entity_decode(strip_tags($tpl_site_name[1]), ENT_QUOTES, 'UTF-8'));
return $pdf;
}
/**
* Format the TCPDF page settings (margins, etc)
*
* @param $pdf
* current TCPDF object
* @see theme_print_pdf_tcpdf_page()
*/
function theme_print_pdf_tcpdf_page($pdf) {
// set margins
$pdf->SetMargins(15, 20, 15);
// set auto page breaks
$pdf->SetAutoPageBreak(TRUE, 15);
// set image scale factor
$pdf->setImageScale(1);
// set image compression quality
$pdf->setJPEGQuality(100);
return $pdf;
}
/**
* Format the TCPDF page content
*
* @param $pdf
* current TCPDF object
* @param $html
* contents of the body of the HTML from the original node
* @param $font
* array with the font definition (font name, styles and size)
* @see theme_print_pdf_tcpdf_content()
*/
function theme_print_pdf_tcpdf_content($pdf, $html, $font) {
// set content font
$pdf->setFont($font[0], $font[1], $font[2]);
preg_match('!<body.*?>(.*)</body>!sim', $html, $matches);
$pattern = '!(?:<div class="print-(?:logo|site_name|breadcrumb|footer)">.*?</div>|<hr class="print-hr" />)!si';
$matches[1] = preg_replace($pattern, '', $matches[1]);
// Make CCK fields look better
$matches[1] = preg_replace('!(<div class="field.*?>)\s*!sm', '$1', $matches[1]);
$matches[1] = preg_replace('!(<div class="field.*?>.*?</div>)\s*!sm', '$1', $matches[1]);
$matches[1] = preg_replace('!<div( class="field-label.*?>.*?)</div>!sm', '<strong$1</strong>', $matches[1]);
// Since TCPDF's writeHTML is so bad with <p>, do everything possible to make it look nice
$matches[1] = preg_replace('!<(?:p(|\s+.*?)/?|/p)>!i', '<br$1 />', $matches[1]);
$matches[1] = str_replace(array('<div', 'div>'), array('<span', 'span><br />'), $matches[1]);
do {
$prev = $matches[1];
$matches[1] = preg_replace('!(</span>)<br />(\s*?</span><br />)!s', '$1$2', $matches[1]);
} while ($prev != $matches[1]);
@$pdf->writeHTML($matches[1]);
return $pdf;
}
/**
* Format the TCPDF footer contents
*
* @param $pdf
* current TCPDF object
* @param $html
* contents of the body of the HTML from the original node
* @param $font
* array with the font definition (font name, styles and size)
* @see theme_print_pdf_tcpdf_footer()
*/
function theme_print_pdf_tcpdf_footer($pdf, $html, $font) {
preg_match('!<div class="print-footer">(.*?)</div>!si', $html, $tpl_footer);
if (isset($tpl_footer[1])) {
$footer = trim(preg_replace('!</?div[^>]*?>!i', '', $tpl_footer[1]));
// set footer font
$font[2] *= 0.8;
$pdf->setFooterFont($font);
// set footer margin
$pdf->SetFooterMargin(10);
// set footer data
$pdf->setFooterContent($footer);
}
return $pdf;
}
/**
* Format the TCPDF footer layout
*
* @param $pdf
* current TCPDF object
* @see theme_print_pdf_tcpdf_footer2()
*/
function theme_print_pdf_tcpdf_footer2($pdf) {
// Position at 1.5 cm from bottom
$pdf->writeHTMLCell(0, 15, 15, $pdf->getPageHeight()-15, $pdf->footer);
$ormargins = $pdf->getOriginalMargins();
$pagenumtxt = t('Page !n of !total', array('!n' => $pdf->PageNo(), '!total' => $pdf->getAliasNbPages()));
// Print page number
if ($pdf->getRTL()) {
$pdf->SetX($ormargins['right']);
$pdf->Cell(0, 10, $pagenumtxt, 'T', 0, 'L');
}
else {
$pdf->SetX($ormargins['left']);
$pdf->Cell(0, 10, $pagenumtxt, 'T', 0, 'R');
}
return $pdf;
}

View file

@ -0,0 +1,125 @@
<?php
/**
* @file
* PDF Version Views integration
*
* @ingroup print
*/
// Views join handlers aren't truly handlers according to [#540128]
// so they need to be specifically included here.
module_load_include('inc', 'print', 'print_join_page_counter');
/**
* Implements hook_views_data().
*/
function print_pdf_views_data() {
// The 'group' index will be used as a prefix in the UI for any of this
// table's fields, sort criteria, etc. so it's easy to tell where they came
// from.
$data['print_pdf_node_conf']['table']['group'] = t('Printer-friendly version');
$data['print_pdf_page_counter']['table']['group'] = t('Printer-friendly version');
// This table references the {node} table. The declaration below creates an
// 'implicit' relationship to the node table, so that when 'node' is the base
// table, the fields are automatically available.
$data['print_pdf_node_conf']['table']['join']['node'] = array(
// 'left_field' is the primary key in the referenced table.
// 'field' is the foreign key in this table.
'left_field' => 'nid',
'field' => 'nid',
// 'type' => 'INNER',
);
$data['print_pdf_page_counter']['table']['join']['node'] = array(
// 'left_field' is the primary key in the referenced table.
// 'field' is the foreign key in this table.
'left_field' => 'nid',
'field' => 'path',
// 'type' => 'INNER',
'handler' => 'print_join_page_counter',
);
// print_pdf_node_conf fields
$data['print_pdf_node_conf']['link'] = array(
'title' => t('PDF: Show link'),
'help' => t('Whether to show the PDF version link.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
$data['print_pdf_node_conf']['comments'] = array(
'title' => t('PDF: Show link in individual comments'),
'help' => t('Whether to show the PDF version link in individual comments.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
$data['print_pdf_node_conf']['url_list'] = array(
'title' => t('PDF: Show Printer-friendly URLs list'),
'help' => t('Whether to show the URL list.'),
'field' => array(
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'views_handler_filter_boolean_operator',
'label' => t('Active'),
'type' => 'yes-no',
),
'sort' => array(
'handler' => 'views_handler_sort',
),
);
// print_pdf_page_counter fields
$data['print_pdf_page_counter']['totalcount'] = array(
'title' => t('PDF: Number of page accesses'),
'help' => t('Counter of accesses to the PDF version for this node.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
);
$data['print_pdf_page_counter']['timestamp'] = array(
'title' => t('PDF: Last access'),
'help' => t("The date of the last access to the node's PDF version."),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
return $data;
}

View file

@ -0,0 +1,113 @@
<?php
/**
* @file
* print module simpletest tests
*
* This file includes the defined tests for the print module.
*
* @ingroup print
*/
class PrintBasicTest extends DrupalWebTestCase {
protected $web_user;
protected $getq;
/**
* Implementation of getInfo().
*/
function getInfo() {
return array(
'name' => t('Printer, email and PDF versions tests'),
'description' => t('Unit tests for the print, print_mail and print_pdf modules.'),
'group' => t('Printer, email and PDF versions'),
);
}
/**
* Implementation of setUp().
*/
function setUp() {
parent::setUp();
// User to set up print.
// $this->web_user = $this->drupalCreateUserRolePerm(array('administer print'));
// $this->drupalGet('logout');
// $this->drupalLoginUser($this->web_user);
$this->getq = $_GET['q'];
$_GET['q'] = 'print/'. $_GET['q'];
}
/**
* Implementation of tearDown().
*/
function tearDown() {
$_GET['q'] = $this->getq;
parent::tearDown();
}
function testPrintRewriteUrls() {
global $base_url, $base_root, $_print_urls;
// Must require it, since this function gets called via Drupal's dynamic loading
require_once(drupal_get_path('module', 'print') .'/print.pages.inc');
variable_set('print_urls_anchors', 1);
$_print_urls = TRUE;
$pattern = '!<(a\s[^>]*?)>(.*?)(</a>)!is';
$footnote = ' <span class="print-footnote">[1]</span>';
$part1 = '<a class=\'class1 class2\' target=_blank hreflang="en" id="some complicated \"href=lala.com\" text" href="';
$part2 = '">Example</a>';
$url[0] = 'http://www.example.com';
$url[1] = '#here';
$url[2] = '/relative/to/host';
$url[3] = 'relative/to/base';
$url[4] = 'index.php?q=sample/path';
$rel_url[0] = $url[0];
$rel_url[1] = base_path() . $_GET['q'] . $url[1];
$rel_url[2] = $base_root . $url[2];
$rel_url[3] = $base_url .'/'. $url[3];
$rel_url[4] = $base_url .'/'. $url[4];
$abs_url[0] = $url[0];
$abs_url[1] = $base_url .'/'. $this->getq . $url[1];
$abs_url[2] = $base_root . $url[2];
$abs_url[3] = $base_url .'/'. $url[3];
$abs_url[4] = $base_url .'/'. $url[4];
$url[5] = '#here with spaces';
$url[6] = '/relative/to/host with spaces';
$url[7] = 'relative/to/base with spaces';
$url[8] = 'index.php?q=sample/path with spaces';
$rel_url[5] = base_path() . $_GET['q'] . $url[5];
$rel_url[6] = $base_root . $url[6];
$rel_url[7] = $base_url .'/'. $url[7];
$rel_url[8] = $base_url .'/'. $url[8];
$abs_url[5] = $base_url .'/'. $this->getq . $url[5];
$abs_url[6] = $base_root . $url[6];
$abs_url[7] = $base_url .'/'. $url[7];
$abs_url[8] = $base_url .'/'. $url[8];
$url[9] = '&#109;&#97;&#x69;&#x6c;&#x74;&#111;&#58;&#115;&#x75;&#x70;p&#111;&#114;&#x74;&#x40;e&#120;&#97;&#x6d;&#x70;&#x6c;&#101;&#46;&#x63;&#x6f;&#x6d;';
$rel_url[9] = $url[9];
$abs_url[9] = $url[9];
$url[10] = '';
$rel_url[10] = '';
$abs_url[10] = $base_url .'/'. $this->getq;
$size = count($url);
for ($i = 0; $i < $size; $i++) {
preg_match($pattern, $part1 . $url[$i] . $part2, $matches);
$ret = _print_rewrite_urls($matches);
$urls = _print_friendly_urls();
$this->assertEqual($ret, $part1 . $rel_url[$i] . $part2 . $footnote, t('Original URL (!url)', array('!url' => $rel_url[$i])));
$this->assertEqual($urls[0], $abs_url[$i], t('Absolute URL (!url)', array('!url' => $abs_url[$i])));
}
}
}