From b3221c71e208fafdc8a5ae45f54caf1e6ea4d110 Mon Sep 17 00:00:00 2001 From: Bachir Soussi Chiadmi Date: Sun, 19 Apr 2015 20:45:16 +0200 Subject: [PATCH] security updates have to check views and entityreference for custom patches --- .../modules/contrib/admin/context/README.txt | 2 +- .../contrib/admin/context/context.api.php | 11 + .../contrib/admin/context/context.core.inc | 41 +- .../contrib/admin/context/context.info | 6 +- .../contrib/admin/context/context.install | 1 + .../contrib/admin/context/context.module | 8 +- .../contrib/admin/context/context.plugins.inc | 56 +- .../context_layouts/context_layouts.info | 6 +- .../context_layouts/context_layouts.module | 4 +- .../admin/context/context_ui/context_ui.info | 6 +- .../context/context_ui/context_ui.module | 16 +- .../export_ui/context_export_ui.class.php | 1 + .../context/context_ui/tests/context_ui.test | 1 + .../plugins/context_condition_context.inc | 44 +- .../plugins/context_condition_context_all.inc | 29 + .../plugins/context_condition_default.inc | 35 + .../context_condition_query_string.inc | 28 + .../plugins/context_reaction_block.css | 2 +- .../plugins/context_reaction_block.inc | 142 +-- .../context/plugins/context_reaction_block.js | 7 +- .../plugins/context_reaction_breadcrumb.inc | 52 +- .../plugins/context_reaction_debug.inc | 16 +- .../context/plugins/context_reaction_menu.inc | 189 ++-- .../context_reaction_template_suggestions.inc | 47 + .../context/tests/context.reactions.test | 37 +- .../theme/context_reaction_block.theme.inc | 15 +- .../modules/contrib/admin/print/INSTALL.txt | 57 +- .../contrib/admin/print/css/print-rtl.css | 9 +- .../modules/contrib/admin/print/css/print.css | 25 +- .../contrib/admin/print/icons/mail_icon.gif | Bin 919 -> 0 bytes .../contrib/admin/print/icons/pdf_icon.gif | Bin 985 -> 0 bytes .../contrib/admin/print/icons/print_icon.gif | Bin 917 -> 0 bytes .../contrib/admin/print/icons/print_icon.png | Bin 0 -> 252 bytes .../admin/print/includes/print.drush.inc | 151 ++++ .../contrib/admin/print/includes/print.inc | 100 +++ .../contrib/admin/print/print.admin.inc | 219 +---- .../modules/contrib/admin/print/print.api.php | 122 +++ .../modules/contrib/admin/print/print.info | 16 +- .../modules/contrib/admin/print/print.install | 108 ++- .../modules/contrib/admin/print/print.module | 837 +++-------------- .../contrib/admin/print/print.pages.inc | 653 +++++++------- .../modules/contrib/admin/print/print.tpl.php | 117 ++- .../print/print_epub/icons/epub_icon.png | Bin 0 -> 500 bytes .../print_epub_phpepub.drush.inc | 32 + .../print_epub_phpepub.info | 12 + .../print_epub_phpepub.module | 65 ++ .../print_epub_phpepub.pages.inc | 48 + .../print/print_epub/print_epub.admin.inc | 115 +++ .../admin/print/print_epub/print_epub.api.php | 96 ++ .../print/print_epub/print_epub.drush.inc | 65 ++ .../admin/print/print_epub/print_epub.info | 13 + .../admin/print/print_epub/print_epub.install | 159 ++++ .../admin/print/print_epub/print_epub.module | 254 ++++++ .../print/print_epub/print_epub.pages.inc | 126 +++ .../print/print_epub/print_epub.views.inc | 121 +++ .../admin/print/print_join_page_counter.inc | 8 +- .../print_mail/css/print_mail.theme-rtl.css | 3 + .../print/print_mail/css/print_mail.theme.css | 8 + .../print/print_mail/icons/mail_icon.png | Bin 0 -> 283 bytes .../print/print_mail/print_mail.admin.inc | 198 +--- .../admin/print/print_mail/print_mail.inc | 175 +++- .../admin/print/print_mail/print_mail.info | 13 +- .../admin/print/print_mail/print_mail.install | 67 +- .../admin/print/print_mail/print_mail.module | 502 +++-------- .../admin/print/print_pdf/icons/pdf_icon.png | Bin 0 -> 518 bytes .../lib_handlers/print_pdf_dompdf/INSTALL.txt | 18 + .../print_pdf_dompdf.admin.inc | 38 + .../print_pdf_dompdf.drush.inc | 32 + .../print_pdf_dompdf/print_pdf_dompdf.info | 13 + .../print_pdf_dompdf/print_pdf_dompdf.install | 16 + .../print_pdf_dompdf/print_pdf_dompdf.module | 95 ++ .../print_pdf_dompdf.pages.inc | 158 ++++ .../print_pdf_mpdf/print_pdf_mpdf.drush.inc | 32 + .../print_pdf_mpdf/print_pdf_mpdf.info | 12 + .../print_pdf_mpdf/print_pdf_mpdf.module | 52 ++ .../print_pdf_mpdf/print_pdf_mpdf.pages.inc | 65 ++ .../lib_handlers/print_pdf_tcpdf/INSTALL.txt | 12 + .../print_pdf_tcpdf/print_pdf_tcpdf.admin.inc | 63 ++ .../print_pdf_tcpdf.class.inc} | 7 +- .../print_pdf_tcpdf/print_pdf_tcpdf.drush.inc | 32 + .../print_pdf_tcpdf/print_pdf_tcpdf.info | 14 + .../print_pdf_tcpdf/print_pdf_tcpdf.install | 17 + .../print_pdf_tcpdf/print_pdf_tcpdf.module | 118 +++ .../print_pdf_tcpdf/print_pdf_tcpdf.pages.inc | 285 ++++++ .../print_pdf_wkhtmltopdf/INSTALL.txt | 17 + .../print_pdf_wkhtmltopdf.admin.inc | 47 + .../print_pdf_wkhtmltopdf.drush.inc | 53 ++ .../print_pdf_wkhtmltopdf.info | 13 + .../print_pdf_wkhtmltopdf.install | 15 + .../print_pdf_wkhtmltopdf.module | 106 +++ .../print_pdf_wkhtmltopdf.pages.inc | 85 ++ .../admin/print/print_pdf/print_pdf.admin.inc | 310 ++----- .../admin/print/print_pdf/print_pdf.api.php | 144 +++ .../admin/print/print_pdf/print_pdf.drush.inc | 211 +---- .../admin/print/print_pdf/print_pdf.info | 15 +- .../admin/print/print_pdf/print_pdf.install | 130 ++- .../admin/print/print_pdf/print_pdf.module | 848 ++++++++---------- .../admin/print/print_pdf/print_pdf.pages.inc | 614 ++----------- .../admin/print/print_pdf/print_pdf.views.inc | 30 +- .../css/print_ui.theme-rtl.css} | 9 +- .../css/print_ui.theme.css} | 14 +- .../admin/print/print_ui/print_ui.admin.inc | 191 ++++ .../admin/print/print_ui/print_ui.api.php | 101 +++ .../admin/print/print_ui/print_ui.info | 13 + .../admin/print/print_ui/print_ui.install | 22 + .../admin/print/print_ui/print_ui.module | 770 ++++++++++++++++ .../admin/print/tests/print_basic.test | 2 +- .../admin/rules_link/rules_link.admin.inc | 18 +- .../contrib/admin/rules_link/rules_link.info | 6 +- .../admin/rules_link/rules_link.module | 7 +- .../admin/rules_link/rules_link_i18n.info | 6 +- sites/all/modules/contrib/dev/ctools/API.txt | 3 + .../dev/ctools/bulk_export/bulk_export.info | 8 +- .../modules/contrib/dev/ctools/css/modal.css | 4 + .../modules/contrib/dev/ctools/ctools.info | 9 +- .../modules/contrib/dev/ctools/ctools.install | 50 +- .../modules/contrib/dev/ctools/ctools.module | 149 ++- .../ctools_access_ruleset.info | 7 +- .../ctools_ajax_sample.info | 7 +- .../ctools_custom_content.info | 7 +- .../ctools_custom_content.module | 20 + .../ctools_plugin_example.info | 7 +- .../dev/ctools/help/context-content.html | 4 + .../contrib/dev/ctools/help/export.html | 3 + .../dev/ctools/help/plugins-creating.html | 11 + .../contrib/dev/ctools/includes/ajax.inc | 28 + .../contrib/dev/ctools/includes/content.inc | 28 +- .../dev/ctools/includes/content.menu.inc | 187 +++- .../dev/ctools/includes/context-admin.inc | 30 +- .../ctools/includes/context-task-handler.inc | 2 +- .../contrib/dev/ctools/includes/context.inc | 18 +- .../contrib/dev/ctools/includes/css-cache.inc | 52 ++ .../contrib/dev/ctools/includes/css.inc | 4 +- .../dev/ctools/includes/entity-access.inc | 150 ++++ .../contrib/dev/ctools/includes/export.inc | 16 +- .../contrib/dev/ctools/includes/fields.inc | 13 + .../contrib/dev/ctools/includes/modal.inc | 26 +- .../contrib/dev/ctools/includes/plugins.inc | 42 +- .../contrib/dev/ctools/includes/utility.inc | 13 - .../contrib/dev/ctools/includes/uuid.inc | 67 ++ .../contrib/dev/ctools/includes/wizard.inc | 2 +- .../dev/ctools/includes/wizard.theme.inc | 11 +- .../contrib/dev/ctools/js/collapsible-div.js | 1 + .../contrib/dev/ctools/js/dependent.js | 8 +- .../modules/contrib/dev/ctools/js/modal.js | 49 +- .../page_manager/page_manager.admin.inc | 60 +- .../dev/ctools/page_manager/page_manager.info | 7 +- .../ctools/page_manager/page_manager.module | 43 +- .../plugins/cache/page_manager_context.inc | 70 ++ .../plugins/task_handlers/http_response.inc | 46 + .../plugins/tasks/comment_reply.inc | 2 +- .../page_manager/plugins/tasks/node_edit.inc | 2 +- .../page_manager/plugins/tasks/node_view.inc | 24 +- .../page_manager/plugins/tasks/page.admin.inc | 12 +- .../page_manager/plugins/tasks/page.inc | 2 +- .../page_manager/plugins/tasks/term_view.inc | 4 +- .../page_manager/plugins/tasks/user_edit.inc | 6 +- .../page_manager/plugins/tasks/user_view.inc | 2 +- .../dev/ctools/plugins/access/book.inc | 94 ++ .../plugins/access/entity_field_value.inc | 289 ++++-- .../ctools/plugins/access/node_comment.inc | 31 + .../ctools/plugins/access/string_length.inc | 4 +- .../ctools/plugins/access/term_vocabulary.inc | 60 +- .../ctools/plugins/arguments/entity_id.inc | 85 +- .../dev/ctools/plugins/arguments/rid.inc | 2 +- .../dev/ctools/plugins/cache/export_ui.inc | 39 + .../dev/ctools/plugins/cache/simple.inc | 51 ++ .../plugins/content_types/block/block.inc | 47 +- .../content_types/comment/comment_links.inc | 80 ++ .../comment/comment_reply_form.inc | 2 +- .../plugins/content_types/custom/custom.inc | 5 + .../entity_context/entity_field.inc | 61 +- .../entity_context/entity_field_extra.inc | 22 +- .../content_types/form/entity_form_field.inc | 5 + .../plugins/content_types/node/node.inc | 3 +- .../node_context/node_comment_wrapper.inc | 117 +++ .../node_context/node_updated.inc | 2 +- .../content_types/page/page_site_name.inc | 42 +- .../content_types/page/page_slogan.inc | 4 +- .../content_types/term_context/term_list.inc | 28 +- .../content_types/term_context/term_name.inc | 121 +++ .../plugins/content_types/token/token.inc | 11 +- .../user_context/profile_fields.inc | 2 +- .../content_types/user_context/user_links.inc | 84 ++ .../dev/ctools/plugins/contexts/string.inc | 28 +- .../dev/ctools/plugins/contexts/token.inc | 3 +- .../dev/ctools/plugins/contexts/user.inc | 2 +- .../plugins/contexts/user_edit_form.inc | 6 +- .../export_ui/ctools_export_ui.class.php | 26 +- .../plugins/relationships/book_parent.inc | 4 +- .../relationships/entity_from_field.inc | 18 +- .../plugins/relationships/terms_from_node.inc | 2 +- .../contrib/dev/ctools/stylizer/stylizer.info | 7 +- .../term_depth/plugins/access/term_depth.inc | 128 +++ .../dev/ctools/term_depth/term_depth.info | 13 + .../dev/ctools/term_depth/term_depth.module | 7 + .../contrib/dev/ctools/tests/css_cache.test | 48 + .../ctools_export_test.info | 7 +- .../dev/ctools/tests/ctools_plugin_test.info | 7 +- .../cached/ctoolsCachedPluginArray.class.php | 7 + .../cached/ctoolsCachedPluginArray2.class.php | 7 + .../tests/plugins/cached/plugin_array.inc | 20 + .../tests/plugins/cached/plugin_array2.inc | 20 + .../tests/plugins/cached/plugin_array_dne.inc | 15 + .../plugins/content_types/views.inc | 12 - .../plugins/content_types/views_panes.inc | 27 +- .../plugins/relationships/term_from_view.inc | 10 +- .../plugins/views/views_content.views.inc | 1 + .../ctools/views_content/views_content.info | 7 +- .../ctools/views_content/views_content.module | 14 + .../modules/contrib/dev/entity/entity.api.php | 9 +- .../contrib/dev/entity/entity.features.inc | 6 +- .../modules/contrib/dev/entity/entity.info | 6 +- .../contrib/dev/entity/entity.info.inc | 5 +- .../modules/contrib/dev/entity/entity.install | 106 +++ .../modules/contrib/dev/entity/entity.module | 132 ++- .../modules/contrib/dev/entity/entity.test | 396 +++++++- .../contrib/dev/entity/entity_token.info | 6 +- .../dev/entity/entity_token.tokens.inc | 10 +- .../dev/entity/includes/entity.controller.inc | 21 +- .../contrib/dev/entity/includes/entity.inc | 20 +- .../dev/entity/includes/entity.property.inc | 9 +- .../contrib/dev/entity/includes/entity.ui.inc | 67 -- .../dev/entity/includes/entity.wrapper.inc | 60 +- .../contrib/dev/entity/modules/book.info.inc | 9 +- .../contrib/dev/entity/modules/callbacks.inc | 148 ++- .../dev/entity/modules/comment.info.inc | 14 +- .../contrib/dev/entity/modules/field.info.inc | 7 +- .../contrib/dev/entity/modules/node.info.inc | 1 + .../dev/entity/modules/statistics.info.inc | 3 + .../contrib/dev/entity/modules/user.info.inc | 6 +- .../dev/entity/tests/entity_feature.info | 6 +- .../contrib/dev/entity/tests/entity_test.info | 6 +- .../dev/entity/tests/entity_test.install | 10 +- .../dev/entity/tests/entity_test.module | 9 +- .../dev/entity/tests/entity_test_i18n.info | 6 +- .../contrib/dev/entity/theme/entity.theme.inc | 4 +- .../contrib/dev/entity/views/entity.views.inc | 65 ++ .../entity_views_field_handler_helper.inc | 12 +- .../entity_views_handler_field_duration.inc | 4 +- .../entity_views_handler_field_options.inc | 5 +- .../entity_views_handler_field_text.inc | 4 +- ...y_views_handler_relationship_by_bundle.inc | 2 +- .../payment/uc_2checkout/uc_2checkout.info | 6 +- .../uc_authorizenet/uc_authorizenet.admin.inc | 113 --- .../uc_authorizenet/uc_authorizenet.info | 6 +- .../uc_authorizenet/uc_authorizenet.module | 285 +----- .../uc_authorizenet/uc_authorizenet.pages.inc | 116 +-- .../payment/uc_credit/tests/test_gateway.info | 6 +- .../ubercart/payment/uc_credit/uc_credit.info | 6 +- .../uc_cybersource/uc_cybersource.info | 6 +- .../uc_google_checkout.info | 6 +- .../payment/uc_payment/uc_payment.info | 6 +- .../uc_payment_pack/uc_payment_pack.info | 6 +- .../ubercart/payment/uc_paypal/uc_paypal.info | 6 +- .../shipping/uc_flatrate/uc_flatrate.info | 6 +- .../ubercart/shipping/uc_quote/uc_quote.info | 6 +- .../shipping/uc_quote/uc_quote.install | 1 + .../shipping/uc_quote/uc_quote.module | 5 + .../shipping/uc_shipping/uc_shipping.info | 6 +- .../uc_shipping/uc_shipping.rules.inc | 22 +- .../ubercart/shipping/uc_ups/uc_ups.info | 6 +- .../shipping/uc_usps/uc_usps.countries.inc | 1 - .../ubercart/shipping/uc_usps/uc_usps.info | 6 +- .../uc_weightquote/uc_weightquote.info | 6 +- .../uc_weightquote/uc_weightquote.module | 2 +- .../ubercart/uc_ajax_admin/uc_ajax_admin.info | 6 +- .../ubercart/uc_attribute/uc_attribute.info | 6 +- .../uc_cart/tests/uc_cart_entity_test.info | 6 +- .../ecommerce/ubercart/uc_cart/uc_cart.info | 6 +- .../uc_cart/uc_cart_checkout_pane.inc | 11 +- .../ubercart/uc_cart_links/uc_cart_links.info | 6 +- .../ubercart/uc_catalog/uc_catalog.info | 6 +- .../ecommerce/ubercart/uc_file/uc_file.info | 6 +- .../uc_googleanalytics.info | 6 +- .../uc_googleanalytics.module | 84 +- .../ubercart/uc_order/uc_order.admin.inc | 6 - .../ecommerce/ubercart/uc_order/uc_order.info | 8 +- .../ubercart/uc_order/uc_order.module | 30 + .../ubercart/uc_order/uc_order.order_pane.inc | 22 +- .../views/uc-order-view-row-invoice.tpl.php | 12 + .../uc_order/views/uc_order.views.inc | 38 + .../uc_order/views/uc_order.views_default.inc | 1 + ...ew.inc => uc_order_plugin_row_invoice.inc} | 2 +- .../ubercart/uc_product/uc_product.info | 6 +- .../ubercart/uc_product/uc_product.module | 11 +- .../uc_product_kit/uc_product_kit.info | 6 +- .../ubercart/uc_reports/uc_reports.info | 6 +- .../ubercart/uc_roles/uc_roles.admin.inc | 2 +- .../ecommerce/ubercart/uc_roles/uc_roles.info | 6 +- .../ecommerce/ubercart/uc_stock/uc_stock.info | 6 +- .../ubercart/uc_store/classes/mail.inc | 33 +- .../uc_store/countries/canada_124_2.cif | 4 +- .../{iran_364_2.cif => iran_364_3.cif} | 14 +- .../uc_store/countries/iso3166-1.sql_.txt | 246 ----- .../ubercart/uc_store/uc_store.countries.inc | 26 +- .../ecommerce/ubercart/uc_store/uc_store.info | 6 +- .../ubercart/uc_store/uc_store.module | 12 +- .../ubercart/uc_tax_report/uc_tax_report.info | 6 +- .../ecommerce/ubercart/uc_taxes/uc_taxes.info | 6 +- .../modules/contrib/fields/date/CHANGELOG.txt | 86 +- .../modules/contrib/fields/date/date.api.php | 3 - .../modules/contrib/fields/date/date.diff.inc | 79 ++ .../contrib/fields/date/date.field.inc | 8 + .../all/modules/contrib/fields/date/date.info | 8 +- .../date/{date_migrate => }/date.migrate.inc | 89 +- .../modules/contrib/fields/date/date.module | 30 +- .../modules/contrib/fields/date/date.theme | 68 +- .../contrib/fields/date/date_admin.inc | 9 +- .../date/date_all_day/date_all_day.info | 6 +- .../fields/date/date_api/date_api.info | 6 +- .../fields/date/date_api/date_api.module | 127 ++- .../date/date_api/date_api_elements.inc | 23 +- .../fields/date/date_api/date_api_sql.inc | 32 +- .../date/date_context/date_context.info | 6 +- .../plugins/date_context_date_condition.inc | 2 +- .../contrib/fields/date/date_elements.inc | 15 +- .../date/date_migrate/date_migrate.info | 14 +- .../date/date_migrate/date_migrate.module | 12 +- .../date_migrate_example.info | 7 +- .../date_migrate_example.install | 9 + .../date_migrate_example.migrate.inc | 51 +- .../date_migrate_example.module | 3 + .../contrib/fields/date/date_popup/README.txt | 6 +- .../fields/date/date_popup/date_popup.info | 6 +- .../fields/date/date_popup/date_popup.module | 8 +- .../fields/date/date_repeat/date_repeat.info | 6 +- .../date/date_repeat/date_repeat_calc.inc | 84 +- .../date/date_repeat/date_repeat_form.inc | 6 +- .../date/date_repeat/tests/date_repeat.test | 13 + .../date_repeat/tests/date_repeat_form.test | 19 +- .../date_repeat_field/date_repeat_field.info | 6 +- .../date_repeat_field.module | 61 +- .../fields/date/date_tools/date_tools.info | 6 +- .../fields/date/date_views/date_views.info | 7 +- .../fields/date/date_views/date_views.install | 30 + .../fields/date/date_views/date_views.module | 75 ++ .../date_views/includes/date_views.views.inc | 2 +- .../date_views_argument_handler_simple.inc | 4 +- .../includes/date_views_filter_handler.inc | 4 + .../date_views_filter_handler_simple.inc | 52 +- .../date_views/theme/date-views-pager.tpl.php | 4 +- .../fields/date/date_views/theme/theme.inc | 12 +- .../contrib/fields/date/tests/date.test | 143 +-- .../{date_migrate => tests}/date_migrate.test | 18 +- .../1354482-er-user-roles-19.patch | 93 -- .../entityreference.devel_generate.inc | 4 +- .../entityreference/entityreference.feeds.inc | 78 +- .../entityreference/entityreference.info | 7 +- .../entityreference.migrate.inc | 2 +- .../entityreference/entityreference.module | 50 +- .../entityreference_behavior_example.info | 6 +- .../fields/entityreference/patch url.txt | 5 - .../patch-entityreference-7.x.patch | 18 - ...ference_SelectionHandler_Generic.class.php | 67 +- ...ce_SelectionHandler_Generic.class.php.orig | 553 ------------ .../tests/entityreference.feeds.test | 248 +++++ .../tests/entityreference.handlers.test | 24 +- .../entityreference/tests/feeds_test.csv | 3 + .../entityreference_feeds_test.info | 16 + .../entityreference_feeds_test.module | 104 +++ .../views/entityreference.views.inc | 11 + .../views/entityreference_plugin_display.inc | 6 +- .../views/entityreference_plugin_style.inc | 6 +- .../contrib/form/webform/components/date.inc | 12 +- .../form/webform/components/fieldset.inc | 4 +- .../contrib/form/webform/components/file.inc | 2 +- .../contrib/form/webform/components/grid.inc | 1 + .../form/webform/components/markup.inc | 3 - .../form/webform/components/number.inc | 171 +++- .../form/webform/components/select.inc | 88 +- .../contrib/form/webform/components/time.inc | 8 +- .../form/webform/includes/webform.admin.inc | 18 +- .../webform/includes/webform.components.inc | 23 +- .../form/webform/includes/webform.emails.inc | 18 +- .../form/webform/includes/webform.pages.inc | 10 +- .../form/webform/includes/webform.report.inc | 16 +- .../webform/includes/webform.submissions.inc | 14 +- .../contrib/form/webform/js/select-admin.js | 2 +- .../contrib/form/webform/js/webform.js | 6 +- .../views/webform_handler_field_form_body.inc | 2 +- ...webform_handler_field_submission_count.inc | 2 +- .../contrib/form/webform/webform.api.php | 79 +- .../modules/contrib/form/webform/webform.info | 6 +- .../contrib/form/webform/webform.install | 18 +- .../contrib/form/webform/webform.module | 272 +++--- .../contrib/localisation/i18n/i18n.info | 6 +- .../contrib/localisation/i18n/i18n.install | 17 +- .../contrib/localisation/i18n/i18n.module | 40 +- .../i18n/i18n_block/i18n_block.info | 6 +- .../i18n/i18n_block/i18n_block.module | 2 +- .../i18n/i18n_contact/i18n_contact.info | 6 +- .../i18n/i18n_field/i18n_field.i18n.inc | 1 + .../i18n/i18n_field/i18n_field.info | 6 +- .../i18n/i18n_field/i18n_field.module | 8 +- .../i18n/i18n_forum/i18n_forum.info | 6 +- .../i18n/i18n_forum/i18n_forum.module | 2 +- .../i18n/i18n_menu/i18n_menu.admin.inc | 12 +- .../i18n/i18n_menu/i18n_menu.i18n.inc | 6 +- .../i18n/i18n_menu/i18n_menu.info | 6 +- .../i18n/i18n_menu/i18n_menu.module | 4 + .../i18n/i18n_menu/i18n_menu.test | 2 + .../i18n/i18n_node/i18n_node.info | 6 +- .../i18n/i18n_node/i18n_node.module | 32 +- .../i18n/i18n_node/i18n_node.pages.inc | 2 +- .../i18n/i18n_node/i18n_node.tokens.inc | 61 ++ .../i18n/i18n_path/i18n_path.info | 6 +- .../i18n/i18n_redirect/i18n_redirect.info | 6 +- .../i18n/i18n_select/i18n_select.info | 6 +- .../i18n/i18n_select/i18n_select.module | 11 +- .../i18n/i18n_string/i18n_string.inc | 234 ++++- .../i18n/i18n_string/i18n_string.info | 6 +- .../i18n/i18n_string/i18n_string.install | 12 + .../i18n/i18n_string/i18n_string.pages.inc | 3 + .../i18n/i18n_string/i18n_string.test | 104 ++- .../i18n/i18n_sync/i18n_sync.info | 6 +- .../i18n/i18n_sync/i18n_sync.module | 57 -- .../i18n/i18n_sync/i18n_sync.node.inc | 1 + .../i18n_taxonomy/i18n_taxonomy.admin.inc | 26 +- .../i18n/i18n_taxonomy/i18n_taxonomy.info | 6 +- .../i18n/i18n_taxonomy/i18n_taxonomy.install | 2 +- .../i18n/i18n_taxonomy/i18n_taxonomy.module | 14 +- .../i18n_taxonomy/i18n_taxonomy.pages.inc | 31 - .../i18n_translation/i18n_translation.info | 6 +- .../i18n/i18n_user/i18n_user.info | 6 +- .../i18n/i18n_variable/i18n_variable.info | 6 +- .../localisation/i18n/tests/i18n_test.info | 6 +- .../localisation/i18n/tests/i18n_test.module | 55 ++ .../contrib/mail/mimemail/CHANGELOG.txt | 21 + .../modules/contrib/mail/mimemail/README.txt | 4 + .../mail/mimemail/includes/mimemail.admin.inc | 2 +- .../mimemail/includes/mimemail.incoming.inc | 22 +- .../contrib/mail/mimemail/mimemail.inc | 70 +- .../contrib/mail/mimemail/mimemail.info | 7 +- .../contrib/mail/mimemail/mimemail.install | 7 + .../contrib/mail/mimemail/mimemail.module | 19 +- .../mimemail_action/mimemail_action.info | 6 +- .../mimemail_compress/mimemail_compress.inc | 8 + .../mimemail_compress/mimemail_compress.info | 6 +- .../contrib/mail/mimemail/tests/mimemail.test | 49 + .../mail/mimemail/tests/mimemail_rules.test | 41 +- .../mail/mimemail/theme/mimemail.theme.inc | 56 +- .../simplenews/includes/simplenews.admin.inc | 4 +- .../includes/simplenews.subscription.inc | 8 +- .../includes/views/simplenews.views.inc | 6 +- .../contrib/mail/simplenews/simplenews.info | 6 +- .../simplenews_rules/simplenews_rules.info | 6 +- .../mail/simplenews/tests/simplenews.test | 32 +- ...intoboggan_content_access_integration.info | 6 +- .../logintoboggan_rules.info | 6 +- .../logintoboggan_variable.info | 6 +- .../users/logintoboggan/logintoboggan.info | 6 +- .../users/logintoboggan/logintoboggan.install | 2 +- .../users/logintoboggan/logintoboggan.module | 27 +- .../users/user_import/supported/user.inc | 2 +- .../users/user_import/user_import.admin.inc | 62 ++ .../users/user_import/user_import.info | 6 +- .../users/user_import/user_import.module | 48 +- .../handlers/views_handler_area_messages.inc | 34 + .../views/handlers/views_handler_argument.inc | 30 +- .../handlers/views_handler_field_counter.inc | 22 +- .../handlers/views_handler_field_date.inc | 53 +- .../views/handlers/views_handler_filter.inc | 23 +- ...handler_filter_boolean_operator_string.inc | 2 +- .../views_handler_filter_fields_compare.inc | 142 +++ .../contrib/views/views/includes/admin.inc | 7 +- .../contrib/views/views/includes/ajax.inc | 6 +- .../contrib/views/views/includes/base.inc | 2 +- .../contrib/views/views/includes/cache.inc | 28 +- .../contrib/views/views/includes/handlers.inc | 5 +- .../contrib/views/views/includes/view.inc | 2 +- .../modules/contrib/views/views/js/ajax.js | 4 +- .../contrib/views/views/js/ajax_view.js | 13 +- .../views/views/js/jquery.ui.dialog.patch.js | 2 +- .../views/views/js/views-contextual.js | 2 +- .../views/modules/comment.views_default.inc | 6 +- .../views/views/modules/field.views.inc | 8 +- .../field/views_handler_field_field.inc | 5 +- ...iews_handler_filter_field_list_boolean.inc | 33 + .../views/modules/node.views_default.inc | 9 +- .../views/modules/node.views_template.inc | 1 + .../views_handler_field_profile_date.inc | 9 +- .../views/modules/search.views_default.inc | 3 +- .../modules/statistics.views_default.inc | 3 +- .../views_handler_field_file_extension.inc | 34 +- .../views/modules/taxonomy.views_default.inc | 3 +- .../views_handler_filter_term_node_tid.inc | 33 +- ...ws_handler_relationship_node_term_data.inc | 4 +- .../views_handler_field_user_link_cancel.inc | 2 +- .../views/views/modules/views.views.inc | 17 + .../views/plugins/views_plugin_cache.inc | 89 +- .../views/plugins/views_plugin_display.inc | 2 +- .../plugins/views_plugin_display_feed.inc | 2 +- .../plugins/views_plugin_display_page.inc | 4 +- .../plugins/views_plugin_exposed_form.inc | 2 +- ...ews_plugin_exposed_form_input_required.inc | 1 + .../views/plugins/views_plugin_pager.inc | 2 +- .../views/plugins/views_plugin_pager_full.inc | 20 +- .../views/plugins/views_plugin_pager_mini.inc | 2 +- .../plugins/views_plugin_query_default.inc | 18 +- .../plugins/views_plugin_style_jump_menu.inc | 13 +- .../views_ui_comment_views_wizard.class.php | 1 + .../views_ui_node_views_wizard.class.php | 1 + ...ws_ui_taxonomy_term_views_wizard.class.php | 1 + .../handlers/views_handler_field_date.test | 32 +- .../views_handler_field_file_extension.test | 66 ++ .../views/tests/handlers/views_handlers.test | 81 ++ .../test_handlers/views_test_area_access.inc | 28 + .../views/views/tests/views_cache.test | 64 ++ .../views/views/tests/views_module.test | 54 ++ .../contrib/views/views/tests/views_test.info | 6 +- .../views/views/tests/views_test.module | 4 + .../modules/contrib/views/views/views.api.php | 76 +- .../modules/contrib/views/views/views.info | 12 +- .../modules/contrib/views/views/views.module | 57 +- .../modules/contrib/views/views/views_ui.info | 6 +- 516 files changed, 14267 insertions(+), 7349 deletions(-) create mode 100644 sites/all/modules/contrib/admin/context/plugins/context_condition_context_all.inc create mode 100644 sites/all/modules/contrib/admin/context/plugins/context_condition_default.inc create mode 100644 sites/all/modules/contrib/admin/context/plugins/context_condition_query_string.inc create mode 100644 sites/all/modules/contrib/admin/context/plugins/context_reaction_template_suggestions.inc delete mode 100644 sites/all/modules/contrib/admin/print/icons/mail_icon.gif delete mode 100644 sites/all/modules/contrib/admin/print/icons/pdf_icon.gif delete mode 100644 sites/all/modules/contrib/admin/print/icons/print_icon.gif create mode 100644 sites/all/modules/contrib/admin/print/icons/print_icon.png create mode 100644 sites/all/modules/contrib/admin/print/includes/print.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/includes/print.inc create mode 100644 sites/all/modules/contrib/admin/print/print.api.php create mode 100644 sites/all/modules/contrib/admin/print/print_epub/icons/epub_icon.png create mode 100644 sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.info create mode 100644 sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.module create mode 100644 sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.pages.inc create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.admin.inc create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.api.php create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.info create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.install create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.module create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.pages.inc create mode 100644 sites/all/modules/contrib/admin/print/print_epub/print_epub.views.inc create mode 100644 sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme-rtl.css create mode 100644 sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme.css create mode 100644 sites/all/modules/contrib/admin/print/print_mail/icons/mail_icon.png create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/icons/pdf_icon.png create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/INSTALL.txt create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.admin.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.info create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.install create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.module create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.pages.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.info create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.module create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.pages.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/INSTALL.txt create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.admin.inc rename sites/all/modules/contrib/admin/print/print_pdf/{print_pdf.class.inc => lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.class.inc} (67%) create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.info create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.install create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.module create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.pages.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/INSTALL.txt create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.admin.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.drush.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.info create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.install create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.module create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.pages.inc create mode 100644 sites/all/modules/contrib/admin/print/print_pdf/print_pdf.api.php rename sites/all/modules/contrib/admin/print/{css/printlinks-rtl.css => print_ui/css/print_ui.theme-rtl.css} (75%) rename sites/all/modules/contrib/admin/print/{css/printlinks.css => print_ui/css/print_ui.theme.css} (69%) create mode 100644 sites/all/modules/contrib/admin/print/print_ui/print_ui.admin.inc create mode 100644 sites/all/modules/contrib/admin/print/print_ui/print_ui.api.php create mode 100644 sites/all/modules/contrib/admin/print/print_ui/print_ui.info create mode 100644 sites/all/modules/contrib/admin/print/print_ui/print_ui.install create mode 100644 sites/all/modules/contrib/admin/print/print_ui/print_ui.module create mode 100644 sites/all/modules/contrib/dev/ctools/includes/css-cache.inc create mode 100644 sites/all/modules/contrib/dev/ctools/includes/entity-access.inc create mode 100644 sites/all/modules/contrib/dev/ctools/includes/uuid.inc create mode 100644 sites/all/modules/contrib/dev/ctools/page_manager/plugins/cache/page_manager_context.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/access/book.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/access/node_comment.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/cache/export_ui.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/cache/simple.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/content_types/comment/comment_links.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/content_types/node_context/node_comment_wrapper.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/content_types/term_context/term_name.inc create mode 100644 sites/all/modules/contrib/dev/ctools/plugins/content_types/user_context/user_links.inc create mode 100644 sites/all/modules/contrib/dev/ctools/term_depth/plugins/access/term_depth.inc create mode 100644 sites/all/modules/contrib/dev/ctools/term_depth/term_depth.info create mode 100644 sites/all/modules/contrib/dev/ctools/term_depth/term_depth.module create mode 100644 sites/all/modules/contrib/dev/ctools/tests/css_cache.test create mode 100644 sites/all/modules/contrib/dev/ctools/tests/plugins/cached/ctoolsCachedPluginArray.class.php create mode 100644 sites/all/modules/contrib/dev/ctools/tests/plugins/cached/ctoolsCachedPluginArray2.class.php create mode 100644 sites/all/modules/contrib/dev/ctools/tests/plugins/cached/plugin_array.inc create mode 100644 sites/all/modules/contrib/dev/ctools/tests/plugins/cached/plugin_array2.inc create mode 100644 sites/all/modules/contrib/dev/ctools/tests/plugins/cached/plugin_array_dne.inc delete mode 100644 sites/all/modules/contrib/ecommerce/ubercart/payment/uc_authorizenet/uc_authorizenet.admin.inc create mode 100644 sites/all/modules/contrib/ecommerce/ubercart/uc_order/views/uc-order-view-row-invoice.tpl.php rename sites/all/modules/contrib/ecommerce/ubercart/uc_order/views/{uc_order_plugin_row_invoice_view.inc => uc_order_plugin_row_invoice.inc} (83%) rename sites/all/modules/contrib/ecommerce/ubercart/uc_store/countries/{iran_364_2.cif => iran_364_3.cif} (89%) delete mode 100644 sites/all/modules/contrib/ecommerce/ubercart/uc_store/countries/iso3166-1.sql_.txt create mode 100644 sites/all/modules/contrib/fields/date/date.diff.inc rename sites/all/modules/contrib/fields/date/{date_migrate => }/date.migrate.inc (77%) create mode 100644 sites/all/modules/contrib/fields/date/date_views/date_views.install rename sites/all/modules/contrib/fields/date/{date_migrate => tests}/date_migrate.test (85%) delete mode 100644 sites/all/modules/contrib/fields/entityreference/1354482-er-user-roles-19.patch delete mode 100644 sites/all/modules/contrib/fields/entityreference/patch url.txt delete mode 100644 sites/all/modules/contrib/fields/entityreference/patch-entityreference-7.x.patch delete mode 100644 sites/all/modules/contrib/fields/entityreference/plugins/selection/EntityReference_SelectionHandler_Generic.class.php.orig create mode 100644 sites/all/modules/contrib/fields/entityreference/tests/entityreference.feeds.test create mode 100644 sites/all/modules/contrib/fields/entityreference/tests/feeds_test.csv create mode 100644 sites/all/modules/contrib/fields/entityreference/tests/modules/entityreference_feeds_test/entityreference_feeds_test.info create mode 100644 sites/all/modules/contrib/fields/entityreference/tests/modules/entityreference_feeds_test/entityreference_feeds_test.module create mode 100644 sites/all/modules/contrib/localisation/i18n/i18n_node/i18n_node.tokens.inc create mode 100644 sites/all/modules/contrib/views/views/handlers/views_handler_area_messages.inc create mode 100644 sites/all/modules/contrib/views/views/handlers/views_handler_filter_fields_compare.inc create mode 100644 sites/all/modules/contrib/views/views/modules/field/views_handler_filter_field_list_boolean.inc create mode 100644 sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_file_extension.test create mode 100644 sites/all/modules/contrib/views/views/tests/handlers/views_handlers.test create mode 100644 sites/all/modules/contrib/views/views/tests/test_handlers/views_test_area_access.inc diff --git a/sites/all/modules/contrib/admin/context/README.txt b/sites/all/modules/contrib/admin/context/README.txt index 460c947d..994ddab6 100644 --- a/sites/all/modules/contrib/admin/context/README.txt +++ b/sites/all/modules/contrib/admin/context/README.txt @@ -13,7 +13,7 @@ version. You will need the latest CTools (as of Sept. 16 2010) from here: - all reactions - context UI - context layouts -- inline editor (with Admin 2.x for D7) +- inline editor (see the context_ui README file for info on enabling) ### Expect API changes diff --git a/sites/all/modules/contrib/admin/context/context.api.php b/sites/all/modules/contrib/admin/context/context.api.php index 5755edf3..30cff799 100644 --- a/sites/all/modules/contrib/admin/context/context.api.php +++ b/sites/all/modules/contrib/admin/context/context.api.php @@ -128,3 +128,14 @@ function hook_context_load_alter(&$context) { ); } } + +/** + * Allows for finer grained access mechanisms to using the json + * rendering capabilities of the block reaction when a user isn't + * granted the administer contexts or context ajax block access + * permission + * @param $block_id + * ID of block in module-delta format + */ +function hook_context_allow_ajax_block_access($block_id) { +} diff --git a/sites/all/modules/contrib/admin/context/context.core.inc b/sites/all/modules/contrib/admin/context/context.core.inc index cff0aec3..41ed93a5 100644 --- a/sites/all/modules/contrib/admin/context/context.core.inc +++ b/sites/all/modules/contrib/admin/context/context.core.inc @@ -57,6 +57,11 @@ function context_theme() { 'path' => drupal_get_path('module', 'context') . '/theme', 'file' => 'context_reaction_block.theme.inc', ); + $items['context_block_edit_wrap'] = array( + 'render element' => 'element', + 'path' => drupal_get_path('module', 'context') . '/theme', + 'file' => 'context_reaction_block.theme.inc', + ); return $items; } @@ -105,7 +110,8 @@ function context_ctools_render_alter($info, $page, $data) { function context_entity_prepare_view($prepare, $entity_type) { if ($entity_type === 'taxonomy_term' && count($prepare) === 1) { $term = reset($prepare); - if ($term === menu_get_object('taxonomy_term', 2) && $plugin = context_get_plugin('condition', 'taxonomy_term')) { + $menu = menu_get_object('taxonomy_term', 2); + if ($menu && $term->tid == $menu->tid && $plugin = context_get_plugin('condition', 'taxonomy_term')) { $plugin->execute($term, 'view'); } } @@ -115,11 +121,9 @@ function context_entity_prepare_view($prepare, $entity_type) { * Implementation of hook_node_view(). */ function context_node_view($node, $view_mode) { - if ($view_mode === 'full') { - $object = menu_get_object(); - if (isset($object->nid) && $object->nid === $node->nid) { - context_node_condition($node, 'view'); - } + $object = menu_get_object(); + if (isset($object->nid) && $object->nid === $node->nid) { + context_node_condition($node, 'view'); } } @@ -315,21 +319,21 @@ function context_context_page_condition() { if ($plugin = context_get_plugin('condition', 'menu')) { $plugin->execute(); } - if ($plugin = context_get_plugin('condition', 'sitewide')) { + if ($plugin = context_get_plugin('condition', 'default')) { $plugin->execute(1); } if ($plugin = context_get_plugin('condition', 'context')) { $plugin->execute(); } + if ($plugin = context_get_plugin('condition', 'context_all')) { + $plugin->execute(); + } } /** * Implementation of hook_context_page_reaction(). */ function context_context_page_reaction() { - if ($plugin = context_get_plugin('reaction', 'breadcrumb')) { - $plugin->execute(); - } if ($plugin = context_get_plugin('reaction', 'css_injector')) { $plugin->execute(); } @@ -342,10 +346,10 @@ function context_context_page_reaction() { * Implementation of hook_preprocess_page(). */ function context_preprocess_page(&$vars) { - if ($plugin = context_get_plugin('reaction', 'menu')) { + if ($plugin = context_get_plugin('reaction', 'theme')) { $plugin->execute($vars); } - if ($plugin = context_get_plugin('reaction', 'theme')) { + if ($plugin = context_get_plugin('reaction', 'template_suggestions')) { $plugin->execute($vars); } /* @@ -358,6 +362,19 @@ function context_preprocess_page(&$vars) { */ } +/** +* Implementation of hook_delivery_callback_alter(). +* Based on menu_position's and menu_trail_by_path's implementations. +*/ +function context_page_delivery_callback_alter() { + if ($plugin = context_get_plugin('reaction', 'menu')) { + $plugin->execute(); + } + if ($plugin = context_get_plugin('reaction', 'breadcrumb')) { + $plugin->execute(); + } +} + /** * Implementation of hook_preprocess_html(). */ diff --git a/sites/all/modules/contrib/admin/context/context.info b/sites/all/modules/contrib/admin/context/context.info index e7a335c1..a980c87d 100644 --- a/sites/all/modules/contrib/admin/context/context.info +++ b/sites/all/modules/contrib/admin/context/context.info @@ -8,9 +8,9 @@ files[] = tests/context.test files[] = tests/context.conditions.test files[] = tests/context.reactions.test -; Information added by drupal.org packaging script on 2013-07-29 -version = "7.x-3.0-beta7" +; Information added by Drupal.org packaging script on 2015-01-06 +version = "7.x-3.6" core = "7.x" project = "context" -datestamp = "1375065368" +datestamp = "1420573188" diff --git a/sites/all/modules/contrib/admin/context/context.install b/sites/all/modules/contrib/admin/context/context.install index 72197331..0a5a145c 100644 --- a/sites/all/modules/contrib/admin/context/context.install +++ b/sites/all/modules/contrib/admin/context/context.install @@ -1,5 +1,6 @@ execute(1); + } if ($plugin = context_get_plugin('condition', 'path')) { $plugin->execute(); } + if ($plugin = context_get_plugin('condition', 'query_string')) { + $plugin->execute(); + } if ($plugin = context_get_plugin('condition', 'language')) { global $language; $plugin->execute($language->language); @@ -458,7 +464,7 @@ function context_empty($element) { } } else { - $empty = $empty && empty($element); + $empty = $empty && !isset($element); } return $empty; } diff --git a/sites/all/modules/contrib/admin/context/context.plugins.inc b/sites/all/modules/contrib/admin/context/context.plugins.inc index 6f865598..a0849bb3 100644 --- a/sites/all/modules/contrib/admin/context/context.plugins.inc +++ b/sites/all/modules/contrib/admin/context/context.plugins.inc @@ -7,10 +7,15 @@ function _context_context_registry() { $registry = array(); $registry['conditions'] = array( 'context' => array( - 'title' => t('Context'), - 'description' => t('Set this context on the basis of other active contexts. Put each context on a separate line. You can use the * character (asterisk) as a wildcard and the ~ character (tilde) to prevent this context from activating if the listed context is active. Other contexts which use context conditions can not be used to exclude this context from activating.'), + 'title' => t('Context (any)'), + 'description' => t('Set this context on the basis of other active contexts. Put each context on a separate line. The condition will pass if any of the contexts are active. You can use the * character (asterisk) as a wildcard and the ~ character (tilde) to prevent this context from activating if the listed context is active. Other contexts which use context conditions can not be used to exclude this context from activating.'), 'plugin' => 'context_condition_context', ), + 'context_all' => array( + 'title' => t('Context (all)'), + 'description' => t('Set this context on the basis of other active contexts. Put each context on a separate line. The condition will pass only if all of the contexts are active. You can use the * character (asterisk) as a wildcard and the ~ character (tilde) to prevent this context from activating if the listed context is active. Other contexts which use context conditions can not be used to exclude this context from activating.'), + 'plugin' => 'context_condition_context_all', + ), 'node' => array( 'title' => t('Node type'), 'description' => t('Set this context when viewing a node page or using the add/edit form of one of these content types.'), @@ -21,11 +26,21 @@ function _context_context_registry() { 'description' => t('Should this context always be set? If true, this context will be active across your entire site.'), 'plugin' => 'context_condition_sitewide', ), + 'default' => array( + 'title' => t('Default context'), + 'description' => t('This context will be set if no other context is active except sitewide contexts.'), + 'plugin' => 'context_condition_default', + ), 'path' => array( 'title' => t('Path'), 'description' => t('Set this context when any of the paths above match the page path. Put each path on a separate line. You can use the * character (asterisk) as a wildcard and the ~ character (tilde) to exclude one or more paths. Use <front> for the site front page.'), 'plugin' => 'context_condition_path', ), + 'query_string' => array( + 'title' => t('Query String'), + 'description' => t('Set this context when any of the query strings above match the page query string. Put each query string on a separate line. You can use the "*" character as a wildcard and ~ to exclude one or more query strings.'), + 'plugin' => 'context_condition_query_string', + ), 'user' => array( 'title' => t('User role'), 'description' => t('Set this context when the current user has one of the selected role(s).'), @@ -98,6 +113,11 @@ function _context_context_registry() { 'description' => t('Set the breadcrumb trail to the selected menu item.'), 'plugin' => 'context_reaction_breadcrumb', ), + 'template_suggestions' => array( + 'title' => t('Template suggestions'), + 'description' => t('Add template suggestions using context.'), + 'plugin' => 'context_reaction_template_suggestions', + ), 'theme' => array( 'title' => t('Theme Page'), 'description' => t('Control page theme variables using context.'), @@ -155,6 +175,14 @@ function _context_context_plugins() { 'parent' => 'context_condition_path', ), ); + $plugins['context_condition_context_all'] = array( + 'handler' => array( + 'path' => drupal_get_path('module', 'context') . '/plugins', + 'file' => 'context_condition_context_all.inc', + 'class' => 'context_condition_context_all', + 'parent' => 'context_condition_path', + ), + ); $plugins['context_condition_node'] = array( 'handler' => array( 'path' => drupal_get_path('module', 'context') . '/plugins', @@ -171,6 +199,14 @@ function _context_context_plugins() { 'parent' => 'context_condition', ), ); + $plugins['context_condition_default'] = array( + 'handler' => array( + 'path' => drupal_get_path('module', 'context') . '/plugins', + 'file' => 'context_condition_default.inc', + 'class' => 'context_condition_default', + 'parent' => 'context_condition', + ), + ); $plugins['context_condition_path'] = array( 'handler' => array( 'path' => drupal_get_path('module', 'context') . '/plugins', @@ -179,6 +215,14 @@ function _context_context_plugins() { 'parent' => 'context_condition', ), ); + $plugins['context_condition_query_string'] = array( + 'handler' => array( + 'path' => drupal_get_path('module', 'context') .'/plugins', + 'file' => 'context_condition_query_string.inc', + 'class' => 'context_condition_query_string', + 'parent' => 'context_condition_path', + ), + ); $plugins['context_condition_user'] = array( 'handler' => array( 'path' => drupal_get_path('module', 'context') . '/plugins', @@ -294,6 +338,14 @@ function _context_context_plugins() { 'parent' => 'context_reaction_menu', ), ); + $plugins['context_reaction_template_suggestions'] = array( + 'handler' => array( + 'path' => drupal_get_path('module', 'context') . '/plugins', + 'file' => 'context_reaction_template_suggestions.inc', + 'class' => 'context_reaction_template_suggestions', + 'parent' => 'context_reaction', + ), + ); $plugins['context_reaction_menu'] = array( 'handler' => array( 'path' => drupal_get_path('module', 'context') . '/plugins', diff --git a/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.info b/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.info index 47c09918..5ddb2cfb 100644 --- a/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.info +++ b/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.info @@ -6,9 +6,9 @@ core = 7.x files[] = plugins/context_layouts_reaction_block.inc -; Information added by drupal.org packaging script on 2013-07-29 -version = "7.x-3.0-beta7" +; Information added by Drupal.org packaging script on 2015-01-06 +version = "7.x-3.6" core = "7.x" project = "context" -datestamp = "1375065368" +datestamp = "1420573188" diff --git a/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.module b/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.module index a1fa86eb..06cdff3a 100644 --- a/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.module +++ b/sites/all/modules/contrib/admin/context/context_layouts/context_layouts.module @@ -49,7 +49,7 @@ function context_layouts_theme() { if (!empty($layout['template'])) { $info["page__context_layouts_{$theme->name}_{$layout['layout']}"] = array( 'template' => $layout['template'], - 'path' => drupal_get_path('theme', $theme->name), + 'path' => $layout['path'], ); } } @@ -107,10 +107,12 @@ function context_layouts_get_layouts($theme = NULL, $reset = FALSE) { // Merge layout info into a single array. foreach ($themes as $key => $info) { + $path = drupal_get_path('theme', $key); if (!empty($info['layouts'])) { foreach ($info['layouts'] as $layout => $layout_info) { $layout_info['layout'] = str_replace('-', '_', $layout); $layout_info['theme'] = $key; + $layout_info['path'] = $path; $layouts[$theme][$layout] = $layout_info; } } diff --git a/sites/all/modules/contrib/admin/context/context_ui/context_ui.info b/sites/all/modules/contrib/admin/context/context_ui/context_ui.info index d89f8b53..00066996 100644 --- a/sites/all/modules/contrib/admin/context/context_ui/context_ui.info +++ b/sites/all/modules/contrib/admin/context/context_ui/context_ui.info @@ -8,9 +8,9 @@ configure = admin/structure/context files[] = context.module files[] = tests/context_ui.test -; Information added by drupal.org packaging script on 2013-07-29 -version = "7.x-3.0-beta7" +; Information added by Drupal.org packaging script on 2015-01-06 +version = "7.x-3.6" core = "7.x" project = "context" -datestamp = "1375065368" +datestamp = "1420573188" diff --git a/sites/all/modules/contrib/admin/context/context_ui/context_ui.module b/sites/all/modules/contrib/admin/context/context_ui/context_ui.module index 239d79f7..2ed2aa68 100644 --- a/sites/all/modules/contrib/admin/context/context_ui/context_ui.module +++ b/sites/all/modules/contrib/admin/context/context_ui/context_ui.module @@ -80,6 +80,10 @@ function context_ui_permission() { 'title' => 'Administer contexts', 'description' => 'Associate menus, views, blocks, etc. with different contexts to structure your site.' ); + $permissions['context ajax block access'] = array( + 'title' => t('Access All Blocks'), + 'description' => t('Allows users to access all rendered blocks via an AJAX callback. If you have some blocks that should not be rendered for some users but need those users to be able to use context UI, then implement hook_context_allow_ajax_block_access with the necessary logic.'), + ); return $permissions; } @@ -383,8 +387,10 @@ function context_ui_menu_contextual_links_alter(&$links, $router_item, $root_pat * A page call back to activate the context_ui inline editor dialog. */ function context_ui_activate() { - $_SESSION['context_ui_active'] = $_GET['destination']; - drupal_goto($_GET['destination']); + if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) { + $_SESSION['context_ui_active'] = $_GET['destination']; + drupal_goto($_GET['destination']); + } } /** @@ -394,8 +400,10 @@ function context_ui_activate() { * to navigate to when deactivating context_ui_editor */ function context_ui_deactivate() { - $_SESSION['context_ui_active'] = FALSE; - drupal_goto($_GET['destination']); + if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) { + $_SESSION['context_ui_active'] = FALSE; + drupal_goto($_GET['destination']); + } } /** diff --git a/sites/all/modules/contrib/admin/context/context_ui/export_ui/context_export_ui.class.php b/sites/all/modules/contrib/admin/context/context_ui/export_ui/context_export_ui.class.php index 881f9ae4..db5cf86d 100644 --- a/sites/all/modules/contrib/admin/context/context_ui/export_ui/context_export_ui.class.php +++ b/sites/all/modules/contrib/admin/context/context_ui/export_ui/context_export_ui.class.php @@ -73,6 +73,7 @@ class context_export_ui extends ctools_export_ui { if (!empty($this->plugin['form']['submit'])) { $this->plugin['form']['submit']($form, $form_state); } + context_invalidate_cache(); } /** diff --git a/sites/all/modules/contrib/admin/context/context_ui/tests/context_ui.test b/sites/all/modules/contrib/admin/context/context_ui/tests/context_ui.test index 1e8092ce..06c7a5ea 100644 --- a/sites/all/modules/contrib/admin/context/context_ui/tests/context_ui.test +++ b/sites/all/modules/contrib/admin/context/context_ui/tests/context_ui.test @@ -24,6 +24,7 @@ class ContextUiTestCase extends DrupalWebTestCase { $admin_user = $this->drupalCreateUser(array( 'access administration pages', 'administer site configuration', + 'administer contexts', 'access content', 'create blog content' )); diff --git a/sites/all/modules/contrib/admin/context/plugins/context_condition_context.inc b/sites/all/modules/contrib/admin/context/plugins/context_condition_context.inc index b9140705..aca0e6ae 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_condition_context.inc +++ b/sites/all/modules/contrib/admin/context/plugins/context_condition_context.inc @@ -9,7 +9,8 @@ class context_condition_context extends context_condition_path { $active_contexts = array_keys(context_active_contexts()); foreach ($this->get_contexts() as $context) { if (!in_array($context->name, $active_contexts, TRUE) && $values = $this->fetch_from_context($context, 'values')) { - if ($this->match($active_contexts, $values)) { + // Always check against the active contexts. + if ($this->match(array_keys(context_active_contexts()), $values)) { $this->condition_met($context); } } @@ -20,4 +21,45 @@ class context_condition_context extends context_condition_path { } } } + + /** + * Retrieve all context conditions. + * + * This method is slightly adapted to context_condition::get_contexts() in + * order to ensure that a context that is used as condition in another context + * gets handled before. + */ + function get_contexts($value = NULL) { + $map = context_condition_map(); + $map = isset($map[$this->plugin]) ? $map[$this->plugin] : array(); + + $contexts = array(); + + // Add the contexts that are needed for conditions in the other contexts + // first. Start with the negated ones first, as we can not unset a met + // condition afterwards. + krsort($map); + foreach ($map as $key => $submap) { + // Negated context conditions start with a "~". + if (substr($key, 0, 1) == "~") { + $key = substr($key, 1); + } + if (!isset($contexts[$key])) { + $context = context_load($key); + // Check if context exists. This will fail for wildcards. + if ($context) { + $contexts[$context->name] = $context; + } + } + } + foreach ($map as $key => $submap) { + foreach ($submap as $name) { + if (!isset($contexts[$name])) { + $context = context_load($name); + $contexts[$context->name] = $context; + } + } + } + return $contexts; + } } diff --git a/sites/all/modules/contrib/admin/context/plugins/context_condition_context_all.inc b/sites/all/modules/contrib/admin/context/plugins/context_condition_context_all.inc new file mode 100644 index 00000000..faecbb34 --- /dev/null +++ b/sites/all/modules/contrib/admin/context/plugins/context_condition_context_all.inc @@ -0,0 +1,29 @@ +condition_used()) { + $active_contexts = array_keys(context_active_contexts()); + foreach ($this->get_contexts() as $context) { + + // Only test contexts that haven't been activated yet, + // and have values set. + if (!in_array($context->name, $active_contexts, TRUE) && $values = $this->fetch_from_context($context, 'values')) { + + // The condition is met if all contexts are active. + if (count(array_intersect($values, $active_contexts)) == count($values)) { + $this->condition_met($context); + } + } + } + + // If the list of active contexts has changed, we need to recurse. + if ($active_contexts != array_keys(context_active_contexts())) { + $this->execute(); + } + } + } +} diff --git a/sites/all/modules/contrib/admin/context/plugins/context_condition_default.inc b/sites/all/modules/contrib/admin/context/plugins/context_condition_default.inc new file mode 100644 index 00000000..b463c0a9 --- /dev/null +++ b/sites/all/modules/contrib/admin/context/plugins/context_condition_default.inc @@ -0,0 +1,35 @@ + t('Default context')); + } + + function editor_form($context = NULL) { + $form = parent::editor_form($context); + $form[1]['#title'] = t('Default context'); + $form['#weight'] = -10; + return $form; + } + + function execute() { + if ($this->condition_used()) { + $active_contexts = context_active_contexts(); + + foreach ($active_contexts as $name => $context) { + foreach (array_keys($context->conditions) as $cond) { + if (!in_array($cond, array('default', 'sitewide'))) { + return; + } + } + } + foreach ($this->get_contexts('context_condition_default') as $context) { + $this->condition_met($context, 'context_condition_default'); + } + } + } +} diff --git a/sites/all/modules/contrib/admin/context/plugins/context_condition_query_string.inc b/sites/all/modules/contrib/admin/context/plugins/context_condition_query_string.inc new file mode 100644 index 00000000..781d4cbb --- /dev/null +++ b/sites/all/modules/contrib/admin/context/plugins/context_condition_query_string.inc @@ -0,0 +1,28 @@ +condition_used()) { + $current_query_string = $_SERVER["QUERY_STRING"]; + foreach ($this->get_contexts() as $context) { + $query_strings = $this->fetch_from_context($context, 'values'); + if ($this->match($current_query_string, $query_strings, TRUE)) { + $this->condition_met($context); + } + } + } + } +} diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.css b/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.css index 7af243fa..e82a6a66 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.css +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.css @@ -168,7 +168,6 @@ body.context-editing .draggable:hover a.context-block-remove { * Block visibility =================================================== */ #context-blockform .context-blockform-selector { - height:20em; overflow:auto; } @@ -179,6 +178,7 @@ body.context-editing .draggable:hover a.context-block-remove { border:1px solid #ddd; padding:10px; width:50%; + vertical-align: top; } #context-blockform td.blocks .label, diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.inc b/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.inc index 433e7112..abcafd87 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.inc +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.inc @@ -42,13 +42,19 @@ class context_reaction_block extends context_reaction { $group = isset($block->context_group) ? $block->context_group : $block->module; if (!isset($form['selector'][$group])) { $form['selector'][$group] = array( - '#type' => 'checkboxes', + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, '#title' => isset($block->context_group) ? $block->context_group : $modules[$block->module], + ); + $form['selector'][$group]['checkboxes'] = array( + '#type' => 'checkboxes', '#options' => array(), ); } - $form['selector'][$group]['#options'][$block->bid] = check_plain($block->info); + $form['selector'][$group]['checkboxes']['#options'][$block->bid] = check_plain($block->info); } + ksort($form['selector']); /** @@ -58,7 +64,7 @@ class context_reaction_block extends context_reaction { '#tree' => TRUE, '#theme' => 'context_block_regions_form', ); - foreach (system_region_list($theme_key, REGIONS_VISIBLE) as $region => $label) { + foreach ($this->system_region_list($theme_key, REGIONS_VISIBLE) as $region => $label) { $form['blocks'][$region] = array( '#type' => 'item', '#title' => $label, @@ -215,7 +221,7 @@ class context_reaction_block extends context_reaction { } // Populate all block regions - $all_regions = system_region_list($theme); + $all_regions = $this->system_region_list($theme); // Load all region content assigned via blocks. foreach (array_keys($all_regions) as $region) { @@ -255,7 +261,7 @@ class context_reaction_block extends context_reaction { */ protected function is_enabled_region($region) { global $theme; - $regions = array_keys(system_region_list($theme)); + $regions = array_keys($this->system_region_list($theme)); return in_array($region, $regions, TRUE); } @@ -290,7 +296,7 @@ class context_reaction_block extends context_reaction { return FALSE; } // Check that this region is not hidden - $visible = system_region_list($theme, REGIONS_VISIBLE); + $visible = $this->system_region_list($theme, REGIONS_VISIBLE); return $requirements && $this->is_enabled_region($region) && isset($visible[$region]); } @@ -299,15 +305,7 @@ class context_reaction_block extends context_reaction { */ protected function editable_block($block) { if (!empty($block->content)) { - $block->content = array( - 'content' => $block->content, - 'context' => array('#markup' => ""), - ); - //Contextual links are in the wrong spot in the render array once we've nested them - if (isset($block->content['content']['#contextual_links'])) { - $block->content['#contextual_links'] = $block->content['content']['#contextual_links']; - unset($block->content['content']['#contextual_links']); - } + $block->content['#theme_wrappers'][] = 'context_block_edit_wrap'; } else { // the block alter in context.module should ensure that blocks are never @@ -328,7 +326,7 @@ class context_reaction_block extends context_reaction { context_isset('context_ui', 'context_ui_editor_present')) ) { global $theme; - $regions = system_region_list($theme); + $regions = $this->system_region_list($theme); $name = isset($regions[$region]) ? $regions[$region] : $region; // The negative weight + sorted will push our region marker to the top of the region $build['context'] = array( @@ -388,13 +386,29 @@ class context_reaction_block extends context_reaction { } $this->is_editable_check($context_blocks); - foreach ($context_blocks as $r => $blocks) { - $context_blocks[$r] = _block_render_blocks($blocks); + global $theme; + $active_regions = $this->system_region_list($theme); - // Make blocks editable if allowed. - if ($this->is_editable_region($r)) { - foreach ($context_blocks[$r] as $key => $block) { - $context_blocks[$r][$key] = $this->editable_block($block); + // Make context renders regions in the same order as core. + $_context_blocks = array(); + foreach ($active_regions as $r => $name) { + if (isset($context_blocks[$r])) { + $_context_blocks[$r] = $context_blocks[$r]; + } + } + $context_blocks = $_context_blocks; + unset($_context_blocks); + + foreach ($context_blocks as $r => $blocks) { + //only render blocks in an active region + if (array_key_exists($r, $active_regions)) { + $context_blocks[$r] = _block_render_blocks($blocks); + + // Make blocks editable if allowed. + if ($this->is_editable_region($r)) { + foreach ($context_blocks[$r] as $key => $block) { + $context_blocks[$r][$key] = $this->editable_block($block); + } } } @@ -514,7 +528,12 @@ class context_reaction_block extends context_reaction { $result = db_select('block') ->fields('block') ->condition('theme', $theme_key) - ->execute(); + ->execute() + ->fetchAllAssoc('bid'); + + drupal_alter('block_list', $result); + drupal_alter('context_block_list', $result); + foreach ($result as $row) { if (isset($block_info["{$row->module}-{$row->delta}"])) { $block_info["{$row->module}-{$row->delta}"] = (object) array_merge((array) $row, (array) $block_info["{$row->module}-{$row->delta}"]); @@ -576,50 +595,9 @@ class context_reaction_block extends context_reaction { if (function_exists('json_decode')) { return json_decode($json, $assoc); } - return context_reaction_block::_json_decode($json); - } - - /** - * From http://www.php.net/manual/en/function.json-decode.php#91216 - * with modifications for consistency with output of json_decode(). - * - * Original author: walidator.info 2009. - */ - static function _json_decode($json) { - $comment = FALSE; - $out = '$x = '; - for ($i=0; $i < strlen($json); $i++) { - if (!$comment) { - switch ($json[$i]) { - case '{': - $out .= ' (object) array('; - break; - case '}': - $out .= ')'; - break; - case '[': - $out .= ' array('; - break; - case ']': - $out .= ')'; - break; - case ':'; - $out .= '=>'; - break; - default: - $out .= $json[$i]; - break; - } - } - else { - $out .= $json[$i]; - } - if ($json[$i] == '"') { - $comment = !$comment; - } + else { + watchdog('context', 'Please upgrade your PHP version to one that supports json_decode.'); } - eval($out . ';'); - return $x; } /** @@ -640,7 +618,7 @@ class context_reaction_block extends context_reaction { list($bid, $context) = explode(',', $param); list($module, $delta) = explode('-', $bid, 2); // Check token to make sure user has access to block. - if (empty($_GET['context_token']) || $_GET['context_token'] != drupal_get_token($bid)) { + if (!(user_access('administer contexts') || user_access('context ajax block access') || $this->context_block_ajax_rendering_allowed($bid))) { echo drupal_json_encode(array('status' => 0)); exit; } @@ -670,4 +648,34 @@ class context_reaction_block extends context_reaction { echo drupal_json_encode(array('status' => 0)); drupal_exit(); } + + /** + * Provide caching for system_region_list since it can get called + * frequently. Evaluate for removal once https://drupal.org/node/1873450 + * lands or system_region_list is otherwise cached in core + */ + protected function system_region_list($theme_key, $show = REGIONS_ALL) { + static $cache = array(); + if (!isset($cache[$theme_key])) { + $cache[$theme_key] = array(); + } + if (!isset($cache[$theme_key][$show])) { + $cache[$theme_key][$show] = system_region_list($theme_key, $show); + } + return $cache[$theme_key][$show]; + } + + /** + * Allow modules to selectively allow ajax rendering of a specific block + */ + private function context_block_ajax_rendering_allowed($bid) { + $allowed = FALSE; + foreach (module_invoke_all('context_allow_ajax_block_access', $bid) as $module_allow) { + $allowed = $allow || $module_allow; + if ($allowed) { + break; + } + } + return $allowed; + } } diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.js b/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.js index b51e2f34..10e25a26 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.js +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_block.js @@ -327,11 +327,6 @@ DrupalContextBlockEditor.prototype = { // Construct query params for our AJAX block request. var params = Drupal.settings.contextBlockEditor.params; params.context_block = bid + ',' + context; - if (!Drupal.settings.contextBlockEditor.block_tokens || !Drupal.settings.contextBlockEditor.block_tokens[bid]) { - alert(Drupal.t('An error occurred trying to retrieve block content. Please contact a site administer.')); - return; - } - params.context_token = Drupal.settings.contextBlockEditor.block_tokens[bid]; // Replace item with loading block. //ui.sender.append(ui.item); @@ -443,7 +438,7 @@ DrupalContextBlockEditor.prototype = { dropOnEmpty: true, placeholder: 'draggable-placeholder', forcePlaceholderSize: true, - items: '> .block:has(a.context-block.editable)', + items: '> *:has(a.context-block.editable)', handle: 'a.context-block-handle', start: function(event, ui) { self.scriptFix(event, ui, editor, context); }, stop: function(event, ui) { self.addBlock(event, ui, editor, context); }, diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_breadcrumb.inc b/sites/all/modules/contrib/admin/context/plugins/context_reaction_breadcrumb.inc index 17efb0a2..66d121cc 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_reaction_breadcrumb.inc +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_breadcrumb.inc @@ -5,35 +5,35 @@ */ class context_reaction_breadcrumb extends context_reaction_menu { /** - * Override of execute(). + * Overrides set_active_trail_from_link to set the breadcrumb instead of the menu path. */ - function execute(&$vars = NULL) { - if ($active_paths = $this->get_active_paths()) { - $breadcrumb = array(l(t('Home'), '', array('purl' => array('disabled' => TRUE)))); - foreach ($active_paths as $path) { - $result = db_select('menu_links') - ->fields('menu_links', array('p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8')) - ->condition('hidden', 0) - ->condition('link_path', $path) - ->execute(); - while ($parents = $result->fetchAssoc()) { - $set = FALSE; - foreach (array_filter($parents) as $plid) { - $parent = menu_link_load($plid); - if ($parent && $parent['access'] && empty($parent['hidden']) && !empty($parent['title'])) { - $set = TRUE; - $breadcrumb[] = l($parent['title'], $parent['href']); - } - } - // Only set the breadcrumb if one or more links were added to the - // trail. If not, continue iterating through possible menu links. - if ($set) { - drupal_set_breadcrumb($breadcrumb); - break; - } + function set_active_trail_from_link($item) { + $result = db_select('menu_links') + ->fields('menu_links', array('p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8')) + ->condition('hidden', 0) + ->condition('link_path', $item['link_path']) + ->execute(); + while ($parents = $result->fetchAssoc()) { + $set = FALSE; + foreach (array_filter($parents) as $plid) { + $parent = menu_link_load($plid); + if ($parent && $parent['access'] && empty($parent['hidden']) && !empty($parent['title'])) { + $set = TRUE; + $breadcrumb[] = l($parent['title'], $parent['href']); } } + // Only set the breadcrumb if one or more links were added to the + // trail. If not, continue iterating through possible menu links. + if ($set) { + drupal_set_breadcrumb($breadcrumb); + break; + } } } + /** + * Return the title to be used for the current menu item. + */ + function get_link_title($item) { + return module_exists('i18n_menu') ? _i18n_menu_link_title($item) : $item['title']; + } } - diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_debug.inc b/sites/all/modules/contrib/admin/context/plugins/context_reaction_debug.inc index a0577a05..97f38679 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_reaction_debug.inc +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_debug.inc @@ -12,13 +12,27 @@ class context_reaction_debug extends context_reaction { return array('debug' => 1); } + /** + * Settings form for variables. + */ + function settings_form() { + $form = array(); + $form['context_reaction_debug_enable_global'] = array( + '#title' => t('Enable debug reaction on all contexts'), + '#type' => 'checkbox', + '#default_value' => variable_get('context_reaction_debug_enable_global', FALSE), + '#description' => t('Enable the debug reaction on all contexts.') + ); + return $form; + } + /** * Output a list of active contexts. */ function execute() { $contexts = context_active_contexts(); foreach ($contexts as $context) { - if (!empty($context->reactions['debug'])) { + if (!empty($context->reactions['debug']) || variable_get('context_reaction_debug_enable_global', FALSE)) { if (user_access('administer site configuration') && module_exists('context_ui')) { $name = l($context->name, "admin/structure/context/list/{$context->name}", array('query' => array('destination' => $_GET['q']))); } diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_menu.inc b/sites/all/modules/contrib/admin/context/plugins/context_reaction_menu.inc index e51143ba..0d82adce 100644 --- a/sites/all/modules/contrib/admin/context/plugins/context_reaction_menu.inc +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_menu.inc @@ -8,35 +8,33 @@ class context_reaction_menu extends context_reaction { * Provide a form element that allow the admin to chose a menu item. */ function options_form($context) { + $options = array("-- " . t('None') . " --"); if (module_exists('menu')) { $menus = menu_parent_options(menu_get_menus(), array('mlid' => 0)); - $root_menus = array(); - foreach ($menus as $key => $name) { - $id = explode(':', $key); - if ($id[1] == '0') { - $root_menus[$id[0]] = check_plain($name); + $menu_names = array(); + foreach ($menus as $id => $title) { + list($menu_name, $mlid) = explode(':', $id); + // Store the title each menu for reference. + if ($mlid == '0') { + $menu_names[$menu_name] = $title; } else { - $link = menu_link_load($id[1]); + $link = menu_link_load($mlid); $identifier = $link['link_path']; - $root_menu = $root_menus[$id[0]]; - while (isset($menus[$root_menu][$identifier])) { + $root_menu = $menu_names[$menu_name]; + while (isset($options[$root_menu][$identifier])) { $identifier .= "'"; } - $menus[$root_menu][$identifier] = $name; + $options[$root_menu][$menu_name . ':' . $identifier] = $title; } - unset($menus[$key]); } - array_unshift($menus, "-- " . t('None') . " --"); - } - else { - $menus = array(); } return array( '#title' => $this->title, '#description' => $this->description, - '#options' => $menus, + '#options' => $options, '#type' => 'select', + '#multiple' => TRUE, '#default_value' => $this->fetch_from_context($context), ); } @@ -46,97 +44,100 @@ class context_reaction_menu extends context_reaction { * Trim any identifier padding for non-unique path menu items. */ function options_form_submit($values) { - return trim($values, "'"); + $trimmed = array(); + foreach ($values as $value) { + $value = trim($value, "'"); + $trimmed[] = $value; + } + return $trimmed; } /** - * If primary + secondary links are pointed at the same menu, provide - * contextual trailing by default. + * Overrides parent function to include legacy handling for old format of just storing a single path. */ - function execute(&$vars = NULL) { - if (variable_get('menu_main_links_source', 'main-menu') == variable_get('menu_secondary_links_source', 'user-menu')) { - $vars['main_menu'] = theme_get_setting('toggle_main_menu') ? $this->menu_navigation_links(variable_get('menu_main_links_source', 'main-menu')) : $vars['main_menu']; - $vars['secondary_menu'] = theme_get_setting('toggle_secondary_menu') ? $this->menu_navigation_links(variable_get('menu_secondary_links_source', 'secondary-links'), 1) : $vars['secondary_menu']; + function fetch_from_context($context) { + $values = parent::fetch_from_context($context); + // Legacy - convert single string value to an array with a preferred menu + if (is_string($values)) { + $menu = menu_link_get_preferred($values); + if (!$menu) { + return array(); + } + return array($menu['menu_name'] . ':' . $menu['link_path']); } - - $vars['main_menu'] = $this->menu_set_active($vars['main_menu']); - $vars['secondary_menu'] = $this->menu_set_active($vars['secondary_menu']); + return $values; } + /** + * Provide active trail in all menus in which our path appears. + */ + function execute(&$vars = NULL) { + $menu_names = menu_get_active_menu_names(); + $active_paths = $this->get_active_paths(); + foreach ($menu_names as $menu_name) { + if (isset($active_paths[$menu_name])) { + foreach($active_paths[$menu_name] as $path) { + if ($link = menu_link_get_preferred($path, $menu_name)) { + $this->set_active_trail_from_link($link); + return; + } + } + } + } + + // None of the links can be found in their preferred menus. Instead we just try to find any of the paths in any + // menu. Note that the preferred menu names list is still used but not always honoured. + // We hope to not have to fall into this section as we could end up doing rather a lot of lookups. + foreach ($active_paths as $menu_name => $paths) { + foreach($paths as $path) { + if ($link = menu_link_get_preferred($path)) { + $this->set_active_trail_from_link($link); + return; + } + } + } + } + + /** + * Helper function to build and set the active trail from a menu link. + * + * @param $item + * A menu link item. + */ + function set_active_trail_from_link($item) { + menu_tree_set_path($item['menu_name'], $item['link_path']); + $trail = array(); + while($item) { + array_unshift($trail, $item); + $item = menu_link_load($item['plid']); + } + array_unshift($trail, array( + 'title' => t('Home'), + 'href' => '', + 'link_path' => '', + 'localized_options' => array(), + 'type' => 0, + )); + menu_set_active_trail($trail); + } + + /** + * Helper function to return the list of currently active paths. + * + * The paths are grouped by menu name. + */ function get_active_paths() { $active_paths = array(); foreach ($this->get_contexts() as $context) { - if (isset($context->reactions[$this->plugin])) { - $active_paths[] = $context->reactions[$this->plugin]; - } - } - return $active_paths; - } - - /** - * Iterates through a provided links array for use with theme_links() - * (e.g. from menu_primary_links()) and provides an active class for - * any items that have a path that matches an active context. - * - * @param $links - * An array of links. - * @param $reset - * A boolean flag for resetting the static cache. - * - * @return - * A modified links array. - */ - function menu_set_active($links = array(), $reset = FALSE) { - $new_links = array(); - if (!empty($links)) { - $active_paths = $this->get_active_paths(); - - // Iterate through the provided links and build a new set of links - // that includes active classes - foreach ($links as $key => $link) { - if (!empty($link['href']) && in_array($link['href'], $active_paths)) { - $link['attributes']['class'][] = 'active'; - - if (strpos(' active', $key) === FALSE) { - $new_links[$key . ' active'] = $link; - } - } - else { - $new_links[$key] = $link; - } - } - } - return $new_links; - } - - /** - * Wrapper around menu_navigation_links() that gives themers the option of - * building navigation links based on an active context trail. - */ - function menu_navigation_links($menu_name, $level = 0) { - // Retrieve original path so we can repair it after our hack. - $original_path = $_GET['q']; - $original_menu_trail = drupal_static('menu_set_active_trail'); - - // Retrieve the first active menu path found. - if ($active_paths = $this->get_active_paths()) { - $path = current($active_paths); - if (menu_get_item($path)) { - menu_set_active_item($path); - } + $paths = $this->fetch_from_context($context); + $active_paths = array_merge($active_paths, $paths); } - // Build the links requested - if (module_exists('i18n_menu')) { - $links = i18n_menu_navigation_links($menu_name, $level); - } else { - $links = menu_navigation_links($menu_name, $level); + $by_menu_name = array(); + foreach ($active_paths as $id) { + list($menu_name, $path) = explode(':', $id); + $by_menu_name[$menu_name][] = $path; } - - // Repair and get out - menu_set_active_item($original_path); - $repair_menu_trail = &drupal_static('menu_set_active_trail'); - $repair_menu_trail = $original_menu_trail; - return $links; + return $by_menu_name; } } diff --git a/sites/all/modules/contrib/admin/context/plugins/context_reaction_template_suggestions.inc b/sites/all/modules/contrib/admin/context/plugins/context_reaction_template_suggestions.inc new file mode 100644 index 00000000..0376f0a8 --- /dev/null +++ b/sites/all/modules/contrib/admin/context/plugins/context_reaction_template_suggestions.inc @@ -0,0 +1,47 @@ +fetch_from_context($context); + + return array( + '#title' => t('Template suggestions'), + '#type' => 'textarea', + '#description' => t('Enter template suggestions such as "page__front", one per line, in order of preference (using underscores instead of hyphens). For more information, please visit ') . l(t('Drupal 7 Template (Theme Hook) Suggestions'), 'http://drupal.org/node/1089656', array(array('target' => '_blank'), 'html' => TRUE,)) . '.', + '#default_value' => is_string($default_value) ? $default_value : '', + ); + } + + /** + * Add any new template suggestions to the current list. + */ + function execute(&$vars = NULL) { + + // Get the list of contexts associated with this reaction. + $contexts = $this->get_contexts(); + + // Iterate through each, and process those with something set. + foreach ($contexts as $context) { + if (isset($context->reactions) && (!empty($context->reactions[$this->plugin]))) { + + // Get the suggestion data entered by the user. + $suggestions = $this->fetch_from_context($context, 'values'); + + // Convert it to an list and reverse it (as higher priority items + // should be on the bottom). + $suggestions = array_reverse(explode("\n", $suggestions)); + + // Append the suggested list to the existing list. + $vars['theme_hook_suggestions'] = array_merge($vars['theme_hook_suggestions'], $suggestions); + } + } + } +} + diff --git a/sites/all/modules/contrib/admin/context/tests/context.reactions.test b/sites/all/modules/contrib/admin/context/tests/context.reactions.test index c35f2933..1ac215f8 100644 --- a/sites/all/modules/contrib/admin/context/tests/context.reactions.test +++ b/sites/all/modules/contrib/admin/context/tests/context.reactions.test @@ -88,19 +88,44 @@ class ContextReactionBlockAjaxTest extends DrupalWebTestCase { } function setUp() { - parent::setUp('context', 'ctools'); - $admin_user = $this->drupalCreateUser(array('administer site configuration')); + parent::setUp('context', 'context_ui', 'ctools'); + $admin_user = $this->drupalCreateUser(array('context ajax block access')); $this->drupalLogin($admin_user); } function test() { - $token = drupal_hmac_base64('user-online', $this->session_id . drupal_get_private_key() . drupal_get_hash_salt()); $this->drupalGet('node', array( - 'query' => array('context_block' => 'user-online,testcontext', 'context_token' => $token) + 'query' => array('context_block' => 'user-online,testcontext') )); - $this->assertText('"status":1', 'Successful return status. $drupal_hash_salt must be set explicitly for this test to pass'); - $this->assertText('Who\\u0027s online', 'Expected text in block data. drupal_hash_salt must be set explicitly for this test to pass'); + $this->assertText('"status":1', 'Successful return status.'); + $this->assertText('Who\\u0027s online', 'Expected text in block data.'); + } +} + +class ContextReactionBlockAjaxAccessTest extends DrupalWebTestCase { + protected $profile = 'testing'; + + public static function getInfo() { + return array( + 'name' => 'Reaction: block ajax access', + 'description' => 'Test block reaction ajax access behavior.', + 'group' => 'Context', + ); + } + + function setUp() { + parent::setUp('context', 'ctools'); + $admin_user = $this->drupalCreateUser(); + $this->drupalLogin($admin_user); + } + + function test() { + $this->drupalGet('node', array( + 'query' => array('context_block' => 'user-online,testcontext') + )); + + $this->assertText('"status":0', 'Failed return status.'); } } diff --git a/sites/all/modules/contrib/admin/context/theme/context_reaction_block.theme.inc b/sites/all/modules/contrib/admin/context/theme/context_reaction_block.theme.inc index 09e75df4..4f538bc1 100644 --- a/sites/all/modules/contrib/admin/context/theme/context_reaction_block.theme.inc +++ b/sites/all/modules/contrib/admin/context/theme/context_reaction_block.theme.inc @@ -121,11 +121,16 @@ function template_preprocess_context_block_browser(&$vars) { * Preprocessor for theme('context_block_browser_item'). */ function template_preprocess_context_block_browser_item(&$vars) { - static $added = array(); $vars['bid'] = $vars['block']->bid; $vars['info'] = check_plain($vars['block']->info); - if (empty($added[$vars['bid']])) { - drupal_add_js(array('contextBlockEditor' => array('block_tokens' => array($vars['bid'] => drupal_get_token($vars['bid'])))), 'setting'); - $added[$vars['bid']] = TRUE; - } +} + +/** + * Theme wrapper for editable blocks. + * + * @ingroup themeable + */ +function theme_context_block_edit_wrap($vars) { + $block = $vars['element']['#block']; + return $vars['element']['#children'] . ""; } diff --git a/sites/all/modules/contrib/admin/print/INSTALL.txt b/sites/all/modules/contrib/admin/print/INSTALL.txt index 77ba5230..3d72c2da 100644 --- a/sites/all/modules/contrib/admin/print/INSTALL.txt +++ b/sites/all/modules/contrib/admin/print/INSTALL.txt @@ -11,65 +11,14 @@ 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. +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. Good support of CSS 2.1 and partially CSS3. - - 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's support for CSS is considerably worse than the other tools. - Unicode is supported (use of Unicode fonts result in HUGE files). Page - header and footer are supported. This module requires TCPDF >= 5.9.012. - - 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: - wkhtmltopdf is a webkit-based tool that actually is a browser in order to - generate the PDF. Resource hungry: expect to need some 30Mb+ of RAM and - some seconds of CPU power. The static binaries may need additional - libraries in your site, which may present problems in shared hosting - environments. The best, if you can run it. - - 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 ------ diff --git a/sites/all/modules/contrib/admin/print/css/print-rtl.css b/sites/all/modules/contrib/admin/print/css/print-rtl.css index bd4505ef..352ba72a 100644 --- a/sites/all/modules/contrib/admin/print/css/print-rtl.css +++ b/sites/all/modules/contrib/admin/print/css/print-rtl.css @@ -1,10 +1,5 @@ - -body { - direction: rtl; -} -th { - text-align: right; -} +body {direction: rtl;} +th {text-align: right;} .print-links, .print-source_url, .print-taxonomy { diff --git a/sites/all/modules/contrib/admin/print/css/print.css b/sites/all/modules/contrib/admin/print/css/print.css index b8951628..31e6849f 100644 --- a/sites/all/modules/contrib/admin/print/css/print.css +++ b/sites/all/modules/contrib/admin/print/css/print.css @@ -1,4 +1,3 @@ - body { margin: 1em; background-color: #fff; @@ -9,21 +8,11 @@ th { 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; -} +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;} @@ -35,9 +24,7 @@ img.print-logo {border: 0;} .print-title {} .print-submitted {font-size: small;} .print-created {font-size: small;} -.print-taxonomy { - text-align: right; -} +.print-taxonomy {text-align: right;} .print-taxonomy li {display: inline;} .print-content {} .print-hr { diff --git a/sites/all/modules/contrib/admin/print/icons/mail_icon.gif b/sites/all/modules/contrib/admin/print/icons/mail_icon.gif deleted file mode 100644 index 515a047b63d4813c74f91d951d79678e439f2052..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 919 zcmZ?wbhEHb6krfw_|CxK=jWHQ@aa2qg%2+JpA!8SFJ9cV`Bm@U4;wFh+IIQ#&a0pI zUjMT1#+O64z8<~v_2j*8r|y5d@c8@1$KS6#`*G{#&pWSv-hK7+{+nM9-~M{??$?Wt zzh8d({rdBtw_pBz`1a@1_rG6%{{8v;-=Dw#{{8#^R$To5|Nji5U^D~4HOuxxd4j{jMe}E diff --git a/sites/all/modules/contrib/admin/print/icons/pdf_icon.gif b/sites/all/modules/contrib/admin/print/icons/pdf_icon.gif deleted file mode 100644 index 6ce5d1dfa2449b3c4826e6c2c03c77a3c92e5088..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 985 zcmZ?wbhEHb6krfw_|CxK=jV4>L+Y%J$ypoI^R}j!jn%IJk%{_6JJZYdrdJ$HuR55X z2@bg6?e<@A(t+ys?(XglGd6CUv#EFQhuOzIEjaOc*_qF)&wW{Q{>z4oUp8L)y6N)Q ztyjKnyZUwewXZv_ecOHG+nyWW_TBup@7A{y4ISrOI?s3XUhU|*-r04bd&1pWv+m8B zb$`{`$8%>t-L(1O?eB-~d_Qvc`_a4KPu%};^1+W&4}P3}@Z;>`pXVO^xbp1h)n~u1 zzxZ|Q<*z%he?52$M86-s`~CRc?`I!=KmG9M`KLcGKK^;}>Cdare_nt7`{v7^w_pCg z|MvI&_rD*%|NZd&-uCr=LP~o`FU@E}k;pos5!J)@fqIFM5crtL%*HLMvFEAhPNSzi2FBTSnH!7`HZU+)a{&NB Cjul$~ diff --git a/sites/all/modules/contrib/admin/print/icons/print_icon.gif b/sites/all/modules/contrib/admin/print/icons/print_icon.gif deleted file mode 100644 index 12d2cf725d5d5ce383047cf816dc382a34e62003..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 917 zcmZ?wbhEHb6krfw_|CxK=jWH5oqbJTx@D)|q)C$&FJ9cc_rvY;i=N%xcktlBW5C>k#-+z4j`SZuGUq65U`SbVhzkmPUNlE?x|DRzL zjE2CF3IWBREQ|~c5)3*ZSA+5d14ki)A%~2|h6M+kIk+`qA{ZPF@dzke*+eKb9qkt8 zG`h2+Afb_6!MTgY@}qLoWDP+H355rao-FK1r{;7nc*4lUQ1t4I=K}{f23u~EgbfOg q4D%&fg&YDFFtu_DFUrWN_CSDE(Yc2pjpk@vL diff --git a/sites/all/modules/contrib/admin/print/icons/print_icon.png b/sites/all/modules/contrib/admin/print/icons/print_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f2e730e30d256bdc6ff35b43170e1015f72acf49 GIT binary patch literal 252 zcmV*`?iw2Z|NnR2l8*oY00DGTPE!Ct=GbNc003M`L_t&-(~XZy z4uCKS1xpnK|9{i_UsMCN)?H^qn1ly7R|FaGiJ)X+QQ$wIXg_Cw3Nf0xG9jE06^sx; z*4(GkIP|S&h $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 = _print_drush_download_file($url); + if ($filename) { + $extract_ret = _print_drush_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); +} + +/** + * 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 _print_drush_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('print_drush_'); + + $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; +} + +/** + * Helper to extract the downloaded zip/tar archive. + * + * @param string $filename + * filename of the file to extract + * + * @return bool + * TRUE on success, FALSE on failure + */ +function _print_drush_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 %s', $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 %s', $filename); + break; + case 'application/x-bzip2': + // Decompress the tar bz2 archive + $arch_ret = drush_shell_exec('tar xjf %s', $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; +} diff --git a/sites/all/modules/contrib/admin/print/includes/print.inc b/sites/all/modules/contrib/admin/print/includes/print.inc new file mode 100644 index 00000000..bcd0dbd8 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/includes/print.inc @@ -0,0 +1,100 @@ ++text+ + * + * @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; +} + +/** + * 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 string $html + * contents of the post-processed template already with the node data + * @param bool $images_via_file + * if TRUE, convert also files in the 'public' filesystem to local paths + * + * @return string + * converted file names + */ +function _print_access_images_via_file($html, $images_via_file) { + global $base_url, $language; + + $lang = (function_exists('language_negotiation_get_any') && language_negotiation_get_any('locale-url')) ? $language->language : ''; + + // Always convert private to local paths + $pattern = "!(]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?system/files/([^>]*?>)!is"; + $replacement = '$1file://' . realpath(variable_get('file_private_path', '')) . '/$2'; + $html = preg_replace($pattern, $replacement, $html); + if ($images_via_file) { + $pattern = "!(]*?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; +} diff --git a/sites/all/modules/contrib/admin/print/print.admin.inc b/sites/all/modules/contrib/admin/print/print.admin.inc index 6ffb5bbf..7aa82748 100644 --- a/sites/all/modules/contrib/admin/print/print.admin.inc +++ b/sites/all/modules/contrib/admin/print/print.admin.inc @@ -11,7 +11,7 @@ */ /** - * Menu callback for the Printer-friendly pages module settings form. + * Form constructor for the Printer-friendly pages module settings form. * * @ingroup forms */ @@ -168,7 +168,7 @@ function print_main_settings() { } /** - * Validate print_main_settings form. + * Form validation handler for print_main_settings(). */ function _print_main_settings_validate($form, &$form_state) { global $base_root; @@ -188,123 +188,18 @@ function _print_main_settings_validate($form, &$form_state) { } /** - * Menu callback for the Printer-friendly pages HTML settings form. + * Form constructor for the Printer-friendly pages HTML settings form. * * @ingroup forms */ function print_html_settings() { + $link = print_print_link(); + $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', drupal_json_decode(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' => '')), - ); - - if (module_exists('php')) { - $access = user_access('use PHP for settings'); - - 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 TRUE (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' => '')); - } - } - - $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.') . '
' . - 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' => '')), - ); - - if (module_exists('php')) { - 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 TRUE (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' => '')); - } - } - - $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'), @@ -326,18 +221,18 @@ function print_html_settings() { '#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( + $form['settings']['print_html_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), + '#default_value' => variable_get('print_html_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, + '#type' => 'fieldset', + '#title' => t('Robots META tags'), + '#collapsible' => TRUE, + '#collapsed' => FALSE, ); $form['settings']['print_robots_settings']['print_robots_noindex'] = array( @@ -361,92 +256,22 @@ function print_html_settings() { '#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( + $form['settings']['link_text'] = array( '#type' => 'fieldset', - '#title' => t('Text strings'), + '#title' => t('Custom link text'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, ); - - $form['print_main_text']['print_text_published'] = array( + $form['settings']['link_text']['print_html_link_text_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Enable custom link text'), + '#default_value' => variable_get('print_html_link_text_enabled', PRINT_TYPE_LINK_TEXT_ENABLED_DEFAULT), + ); + $form['settings']['link_text']['print_html_link_text'] = 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')), - ); - $form['print_main_text']['reset'] = array( - '#type' => 'submit', - '#value' => t('Reset to defaults'), - '#submit' => array('print_main_strings_settings_delete'), - ); - - return system_settings_form($form); -} - -/** - * Reset button callback for text strings settings form - * - * @ingroup forms - */ -function print_main_strings_settings_delete() { - variable_del('print_text_published'); - variable_del('print_text_source_url'); - variable_del('print_text_retrieved'); - variable_del('print_text_links'); -} - -/** - * 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')), + '#default_value' => variable_get('print_html_link_text', $link['text']), '#description' => t('Text used in the link to the printer-friendly version.'), ); - $form['print_html_text']['reset'] = array( - '#type' => 'submit', - '#value' => t('Reset to defaults'), - '#submit' => array('print_html_strings_settings_delete'), - ); return system_settings_form($form); } - -/** - * Reset button callback for text strings settings form - * - * @ingroup forms - */ -function print_html_strings_settings_delete() { - variable_del('print_html_link_text'); -} diff --git a/sites/all/modules/contrib/admin/print/print.api.php b/sites/all/modules/contrib/admin/print/print.api.php new file mode 100644 index 00000000..4cc70389 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print.api.php @@ -0,0 +1,122 @@ +name); } @@ -126,7 +119,7 @@ function print_schema() { 'fields' => array( 'path' => array( 'type' => 'varchar', - 'length' => 128, + 'length' => 255, 'not null' => TRUE, 'description' => 'Page path', ), @@ -166,12 +159,55 @@ function print_update_7000(&$sandbox) { update_fix_d7_block_deltas($sandbox, $renamed_deltas, array()); } +/** + * Enable the print UI module + */ +function print_update_7199(&$sandbox) { + module_enable(array('print_ui'), FALSE); +} + +/** + * Delete old variables + */ +function print_update_7200(&$sandbox) { + variable_del('print_settings'); + variable_del('print_sourceurl_settings'); + variable_del('print_html_settings'); + variable_del('print_robot_settings'); + + variable_del('print_html_node_link_pages'); + variable_del('print_html_node_link_visibility'); + + 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\_%'"); + foreach ($settings as $variable) { + $name = $variable->name; + + variable_set(str_replace('print_', 'print_html_', $name), variable_get($name)); + variable_del($name); + } +} + /** * Enable block and help area links */ -function print_update_7101(&$sandbox) { +function print_update_7202(&$sandbox) { $link_pos = variable_get('print_html_link_pos', drupal_json_decode('{ "link": "link", "block": "block", "help": "help" }')); $link_pos['block'] = 'block'; $link_pos['help'] = 'help'; variable_set('print_html_link_pos', $link_pos); } + +/** + * Increase size of the path field in the print_page_counter table + */ +function print_update_7203(&$sandbox) { + db_drop_primary_key('print_page_counter'); + db_change_field('print_page_counter', 'path', 'path', + array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'description' => 'Page path'), + array('primary key' => array('path'))); +} diff --git a/sites/all/modules/contrib/admin/print/print.module b/sites/all/modules/contrib/admin/print/print.module index 23b9bcf2..1a56c9fa 100644 --- a/sites/all/modules/contrib/admin/print/print.module +++ b/sites/all/modules/contrib/admin/print/print.module @@ -1,31 +1,5 @@ 'html', + 'text' => t('Printer-friendly version'), + 'description' => t('Display a printer-friendly version of this page.'), + 'path' => 'print', + 'class' => 'print-page', + 'icon' => 'print_icon.png', + 'module' => 'print', + ); +} + +/** + * Implements hook_print_new_window_alter(). + */ +function print_print_new_window_alter(&$new_window, $format) { + $new_window = variable_get('print_html_new_window', PRINT_HTML_NEW_WINDOW_DEFAULT); +} /** * Implements hook_permission(). @@ -92,10 +72,6 @@ function print_permission() { 'title' => t('Administer the module'), 'description' => t('Perform maintenance tasks for the print module.'), ), - 'node-specific print configuration' => array( - 'title' => t('Node-specific configuration'), - 'description' => t('Enable access to the per-node settings.'), - ), 'access print' => array( 'title' => t('Access the printer-friendly page'), 'description' => t('View the printer-friendly pages and the links to them in the original pages.'), @@ -108,12 +84,30 @@ function print_permission() { */ function print_theme() { return array( - 'print_format_link' => array( - 'variables' => array(), - ), 'print' => array( - 'variables' => array('print' => array(), 'type' => PRINT_HTML_FORMAT, 'node' => NULL), + 'variables' => array('node' => NULL, 'query' => NULL, 'format' => '', 'expand_css' => FALSE, 'message' => ''), 'template' => 'print', + 'file' => 'print.pages.inc', + ), + 'print_published' => array( + 'variables' => array(), + 'file' => 'print.pages.inc', + ), + 'print_breadcrumb' => array( + 'variables' => array('node' => NULL), + 'file' => 'print.pages.inc', + ), + 'print_footer' => array( + 'variables' => array(), + 'file' => 'print.pages.inc', + ), + 'print_sourceurl' => array( + 'variables' => array('url' => '', 'node' => NULL, 'cid' => NULL), + 'file' => 'print.pages.inc', + ), + 'print_url_list' => array( + 'variables' => array(), + 'file' => 'print.pages.inc', ), ); } @@ -122,7 +116,7 @@ function print_theme() { * Implements hook_preprocess_HOOK(). */ function print_preprocess_node(&$variables) { - if (($variables['elements']['#view_mode'] == 'print') && isset($variables['elements']['#print_format'])) { + if (($variables['elements']['#view_mode'] == PRINT_VIEW_MODE) && isset($variables['elements']['#print_format'])) { $type = $variables['elements']['#node']->type; $format = $variables['elements']['#print_format']; $nid = $variables['elements']['#node']->nid; @@ -134,61 +128,21 @@ function print_preprocess_node(&$variables) { } } -/** - * Implements hook_preprocess_HOOK(). - */ -function print_preprocess_print(&$variables) { - static $hooks = NULL; - if (!isset($hooks)) { - drupal_theme_initialize(); - $hooks = theme_get_registry(); - } - - $variables['page']['#show_messages'] = FALSE; - - // Stolen from theme() so that ALL preprocess functions are called - $hook = 'page'; - $info = $hooks[$hook]; - if (isset($info['preprocess functions']) || isset($info['process functions'])) { - foreach (array('preprocess functions', 'process functions') as $phase) { - if (!empty($info[$phase])) { - foreach ($info[$phase] as $processor_function) { - if (function_exists($processor_function)) { - // We don't want a poorly behaved process function changing $hook. - $hook_clone = $hook; - $processor_function($variables, $hook_clone); - } - } - } - } - } - - $format = $variables['type']; - $type = (isset($variables['node']->type)) ? $variables['node']->type : ''; - $nid = (isset($variables['node']->nid)) ? $variables['node']->nid : ''; - - $variables['theme_hook_suggestions'] = array(); - $variables['theme_hook_suggestions'][] = "print__node__{$type}"; - $variables['theme_hook_suggestions'][] = "print__node__{$type}__{$nid}"; - $variables['theme_hook_suggestions'][] = "print__{$format}"; - $variables['theme_hook_suggestions'][] = "print__{$format}__node__{$type}"; - $variables['theme_hook_suggestions'][] = "print__{$format}__node__{$type}__{$nid}"; -} - /** * Implements hook_menu(). */ function print_menu() { + $link = print_print_link(); $items = array(); - $items[PRINT_PATH] = array( + $items[$link['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( + $items[$link['path'] . '/' . $link['path']] = array( 'access callback' => FALSE, ); $items['admin/config/user-interface/print'] = array( @@ -204,21 +158,6 @@ function print_menu() { 'weight' => 1, 'type' => MENU_DEFAULT_LOCAL_TASK, ); - $items['admin/config/user-interface/print/html/options'] = array( - 'title' => 'Options', - 'weight' => 1, - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/config/user-interface/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/config/user-interface/print/common'] = array( 'title' => 'Settings', 'description' => 'Settings for the common functionalities for all the print sub-modules.', @@ -229,123 +168,58 @@ function print_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'print.admin.inc', ); - $items['admin/config/user-interface/print/common/options'] = array( - 'title' => 'Options', - 'weight' => 1, - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/config/user-interface/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; } +/** + * Implements hook_variable_info(). + */ +function print_variable_info($options) { + $link = print_print_link(); + + $variable['print_html_link_text'] = array( + 'title' => t('Printer-friendly version'), + 'description' => t('Text used in the link to the printer-friendly version.'), + 'type' => 'string', + 'default' => t($link['text']), + ); + + return $variable; +} + /** * Implements hook_block_info(). */ function print_block_info() { - $block['print-links']['info'] = t('Printer, email and PDF versions'); - $block['print-links']['cache'] = DRUPAL_CACHE_PER_PAGE; - $block['print-top']['info'] = t('Most printed'); - $block['print-top']['cache'] = DRUPAL_CACHE_GLOBAL; - return $block; + $block['print-top']['info'] = t('Most printed'); + $block['print-top']['cache'] = DRUPAL_CACHE_GLOBAL; + return $block; } /** * Implements hook_block_view(). */ function print_block_view($delta = '') { + $block = array(); + switch ($delta) { - case 'print-links': - $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', drupal_json_decode(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 'print-top': $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) ->fetchAll(); if (count($result)) { - $block['content'] = '
    '; + $items = array(); foreach ($result as $obj) { - $block['content'] .= '
  • ' . l(_print_get_title($obj->path), $obj->path) . '
  • '; + $items[] = l(_print_get_title($obj->path), $obj->path); } - $block['content'] .= '
'; + $block['content'] = theme('item_list', array('items' => $items, 'type' => 'ul')); } break; } return $block; } -/** - * Implements hook_node_view_alter(). - */ -function print_node_view_alter(&$build) { - if (isset($build['links']['book']['#links']['book_printer'])) { - $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', drupal_json_decode(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 = $build['links']['book']['#links']['book_printer']['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 && ($alias = drupal_lookup_path('alias', 'node/' . $build['#node']->nid))) ? $alias : $build['#node']->nid; - break; - } - - $build['links']['book']['#links']['book_printer'] = array( - 'href' => PRINT_PATH . '/' . $path, - 'title' => $format['text'], - 'attributes' => $format['attributes'], - 'html' => $format['html'], - ); - } - else { - unset($build['links']['book']['#links']['book_printer']); - } - } - } -} - /** * Implements hook_help(). */ @@ -355,203 +229,46 @@ function print_help($path, $arg) { // Return a line-break version of the module README return _filter_autop(file_get_contents(drupal_get_path('module', 'print') . '/README.txt')); } - - $print_html_link_pos = variable_get('print_html_link_pos', drupal_json_decode(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 "$link"; - } - } - } -} - -/** - * Implements hook_node_view(). - */ -function print_node_view($node, $view_mode) { - $print_html_link_pos = variable_get('print_html_link_pos', drupal_json_decode(PRINT_HTML_LINK_POS_DEFAULT)); - $print_html_link_use_alias = variable_get('print_html_link_use_alias', PRINT_HTML_LINK_USE_ALIAS_DEFAULT); - - foreach (array('node', 'comment') as $type) { - $allowed_type = print_link_allowed(array('type' => $type, 'node' => $node, 'view_mode' => $view_mode)); - 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'); - - $path = (($print_html_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/' . $node->nid))) ? $alias : $node->nid; - - $links['print_html'] = array( - 'href' => PRINT_PATH . '/' . $path, - 'title' => $format['text'], - 'attributes' => $format['attributes'], - 'html' => $format['html'], - 'query' => print_query_string_encode($_GET, array('q')), - ); - - $link_content = array( - '#theme' => 'links', - '#links' => $links, - '#attributes' => array('class' => array('links', 'inline')), - ); - - if ($type == 'node') { - $node->content['links']['print_html'] = $link_content; - } - elseif (($type == 'comment') && isset($node->content['comments']['comments'])) { - foreach ($node->content['comments']['comments'] as $cid => $comment) { - if (is_numeric($cid)) { - $link_content['#links']['print_html']['query']['comment'] = $cid; - $node->content['comments']['comments'][$cid]['links']['print_html'] = $link_content; - } - } - } - } - } - - if ($view_mode == 'full') { - // Insert content corner links - $node->content['print_links'] = array( - '#prefix' => '', - '#markup' => '', - '#suffix' => '', - '#weight' => -101, - ); - if (!empty($print_html_link_pos['corner'])) { - $node->content['print_links']['#markup'] .= print_insert_link(NULL, $node); - } - } -} - -/** - * Implements hook_node_load(). - */ -function print_node_load($nodes, $types) { - $ids = array(); - foreach ($nodes as $node) { - $ids[] = $node->nid; - } - - $result = db_query('SELECT nid, link, comments, url_list FROM {print_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid'); - - foreach ($nodes as $node) { - $node->print_display = isset($result[$node->nid]) ? intval($result[$node->nid]->link) : variable_get('print_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT); - $node->print_display_comment = isset($result[$node->nid]) ? intval($result[$node->nid]->comments) : variable_get('print_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT); - $node->print_display_urllist = isset($result[$node->nid]) ? intval($result[$node->nid]->url_list) : variable_get('print_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); - } -} - -/** - * Implements hook_node_insert(). - */ -function print_node_insert($node) { - 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); - } -} - -/** - * Implements hook_node_update(). - */ -function print_node_update($node) { - 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); - } } /** * Implements hook_node_delete(). */ function print_node_delete($node) { - db_delete('print_node_conf') - ->condition('nid', $node->nid) - ->execute(); db_delete('print_page_counter') ->condition('path', 'node/' . $node->nid) ->execute(); } -/** - * Implements 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') || !empty($form['#node_edit_form']))) { - $form['print'] = array( - '#type' => 'fieldset', - '#title' => t('Printer, email and PDF versions'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#weight' => PRINT_TYPE_FIELDS_WEIGHT, - '#group' => 'additional_settings', - ); - - $form['print']['label'] = array( - '#type' => 'markup', - '#markup' => '

' . t('Printer-friendly version') . '

', - ); - - $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); - } - } -} - /** * Implements hook_entity_info_alter(). */ function print_entity_info_alter(&$info) { // Add the 'Print' view mode for nodes. $info['node']['view modes'] += array( - 'print' => array( + PRINT_VIEW_MODE => array( 'label' => t('Print'), - 'custom settings' => TRUE, + 'custom settings' => FALSE, ), ); + // Add the 'Print' view mode for field_collections + if (module_exists('field_collection')) { + $info['field_collection_item']['view modes'] += array( + PRINT_VIEW_MODE => array( + 'label' => t('Print'), + 'custom settings' => FALSE, + ), + ); + } } /** * Auxiliary function to discover a given page's title * - * @param $path + * @param string $path * path of the page being identified - * @return + * + * @return string * string with the page's title */ function _print_get_title($path) { @@ -578,338 +295,47 @@ function _print_get_title($path) { } } -/** - * 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_merge('print_node_conf') - ->key(array('nid' => $nid)) - ->fields(array( - 'link' => $link, - 'comments' => $comments, - 'url_list' => $url_list, - )) - ->execute(); -} - -/** - * 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'] = array($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', array('path' => $img, 'alt' => $text, 'title' => $text, 'attributes' => array('class' => array('print-icon')))); - break; - case 3: - $text = theme('image', array('path' => $img, 'alt' => $text, 'title' => $text, 'attributes' => array('class' => array('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 + * @param string $path + * path to be used in the link. If not specified, the current URL is used. + * @param object $node + * node object, to be used in checking node access. If the path argument is + * not provided, the path used will be node/nid. + * @param string $location + * where in the page where the link is being inserted ('link', 'corner', + * 'block', 'help'). + * + * @return string + * HTML link to the printer-friendly page + * + * @ingroup print_api */ -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')); - } - else { - $query = NULL; - } - drupal_add_css(drupal_get_path('module', 'print') . '/css/printlinks.css'); - $format = theme('print_format_link'); - return '' . l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) . ''; +function print_insert_link($path = NULL, $node = NULL, $location = '') { + if (function_exists('print_ui_insert_link')) { + return print_ui_insert_link(print_print_link(), array('path' => $path, 'node' => $node, 'location' => $location)); } 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) { - if (module_exists('php')) { - return php_eval($pages); - } - else { - return FALSE; - } - } - $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 + * @param array $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 + * view_mode, node, type, path + * + * @return bool + * FALSE if not allowed, TRUE otherwise */ function print_link_allowed($args) { - $view_mode = isset($args['view_mode']) ? $args['view_mode'] : ''; - if ((($view_mode == 'teaser') && !variable_get('print_html_link_teaser', PRINT_HTML_LINK_TEASER_DEFAULT)) - || !in_array($view_mode, array('full', 'teaser', '')) || !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_query("SELECT comments FROM {print_node_conf} WHERE nid = :nid", array(':nid' => $node->nid))->fetchField(); - } - $print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? $res[$node->nid] : 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. (see #301192) - * - * @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 (in_array($key, $exclude, TRUE)) { - continue; - } - - if (is_array($value)) { - $params[$key] = print_query_string_encode($value, $exclude, $key); - } - else { - $params[$key] = $value; - } - } - - return empty($params) ? NULL : $params; + return (user_access('access print')); } /** @@ -922,43 +348,6 @@ function print_contextual_links_view_alter(&$element, $items) { } } -/** - * 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 +text+ - * - * @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(). */ diff --git a/sites/all/modules/contrib/admin/print/print.pages.inc b/sites/all/modules/contrib/admin/print/print.pages.inc index a7bd7345..691be7d7 100644 --- a/sites/all/modules/contrib/admin/print/print.pages.inc +++ b/sites/all/modules/contrib/admin/print/print.pages.inc @@ -22,25 +22,25 @@ function print_controller_html() { $args = func_get_args(); $path = filter_xss(implode('/', $args)); $cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL; + $link = print_print_link(); - // Handle the query - $query = $_GET; - unset($query['q']); + $node = print_controller($path, $link['format'], $cid); + if ($node) { + // Handle the query + $query = $_GET; + unset($query['q']); - $print = print_controller($path, $query, $cid, PRINT_HTML_FORMAT); - if ($print !== FALSE) { - $node = $print['node']; - $html = theme('print', array('print' => $print, 'type' => PRINT_HTML_FORMAT, 'node' => $node)); + $html = theme('print', array('node' => $node, 'query' => $query, 'format' => $link['format'])); drupal_add_http_header('Content-Type', 'text/html; charset=utf-8'); drupal_send_headers(); print $html; - $nodepath = (isset($node->path) && is_string($node->path)) ? drupal_get_normal_path($node->path) : 'node/' . $path; + $nodepath = (isset($node->nid)) ? 'node/' . $node->nid : drupal_get_normal_path($path); db_merge('print_page_counter') ->key(array('path' => $nodepath)) ->fields(array( - 'totalcount' => 1, - 'timestamp' => REQUEST_TIME, + 'totalcount' => 1, + 'timestamp' => REQUEST_TIME, )) ->expression('totalcount', 'totalcount + 1') ->execute(); @@ -53,26 +53,24 @@ function print_controller_html() { * Depending on the type of node, this functions chooses the appropriate * generator function. * - * @param $path + * @param string $path * path of the original page - * @param array $query - * (optional) array of key/value pairs as used in the url() function for the - * query - * @param $cid - * comment ID of the individual comment to be rendered - * @param $format + * @param string $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 + * @param int $cid + * comment ID of the individual comment to be rendered + * @param string $view_mode + * (optional) view mode to be used when rendering the content + * + * @return object + * node-like object to be used in the print template + * * @see _print_generate_node() * @see _print_generate_path() * @see _print_generate_book() + * @see print_preprocess_print() */ -function print_controller($path, $query = NULL, $cid = NULL, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) { +function print_controller($path, $format, $cid = NULL, $view_mode = PRINT_VIEW_MODE) { if (empty($path)) { // If no path was provided, let's try to generate a page for the referer global $base_url; @@ -93,113 +91,301 @@ function print_controller($path, $query = NULL, $cid = NULL, $format = PRINT_HTM array_shift($parts); $path = implode('/', $parts); } - if (ctype_digit($parts[0]) && (count($parts) == 1)) { - $print = _print_generate_node($path, $query, $cid, $format, $teaser, $message); + $revision_view = preg_match('!^[\d]*/revisions/[\d]*/view$!', $path); + if (ctype_digit($parts[0]) && ((count($parts) == 1) || $revision_view)) { + $vid = $revision_view ? $parts[2] : NULL; + $node = _print_generate_node($path, $format, $vid, $cid, $view_mode); } 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], $query, $format, $teaser, $message); + $node = _print_generate_book($matches[1], $format); } else { // If no content node was found, handle the page printing with the 'printable' engine - $print = _print_generate_path($path, $query, $format, $teaser, $message); + $node = _print_generate_path($path, $format); + } + } + + return $node; +} + +/** + * Implements hook_preprocess_HOOK(). + */ +function print_preprocess_print(&$variables) { + global $language; + + $node = $variables['node']; + $format = $variables['format']; + $path = drupal_get_path_alias(empty($node->nid) ? $node->path : "node/$node->nid"); + + static $hooks = NULL; + if (!isset($hooks)) { + drupal_theme_initialize(); + $hooks = theme_get_registry(); + } + + $variables['page']['#show_messages'] = FALSE; + + // Stolen from theme() so that ALL preprocess functions are called + $hook = 'page'; + $info = $hooks[$hook]; + if (isset($info['preprocess functions']) || isset($info['process functions'])) { + $variables['theme_hook_suggestions'] = array(); + foreach (array('preprocess functions', 'process functions') as $phase) { + if (!empty($info[$phase])) { + foreach ($info[$phase] as $processor_function) { + if (function_exists($processor_function)) { + // We don't want a poorly behaved process function changing $hook. + $hook_clone = $hook; + $processor_function($variables, $hook_clone); + } + } + } + } + } + + $logo_url = FALSE; + switch (variable_get('print_logo_options', PRINT_LOGO_OPTIONS_DEFAULT)) { + case 1: // theme's + $logo_url = theme_get_setting('logo'); + break; + case 2: // user-specifed + $logo_url = strip_tags(variable_get('print_logo_url', PRINT_LOGO_URL_DEFAULT)); + break; + } + $logo_url = preg_replace('!^' . base_path() . '!', '', $logo_url); + + $variables['print_logo'] = $logo_url ? theme('image', array('path' => $logo_url, 'alt' => variable_get('site_name', 'Drupal'), 'attributes' => array('class' => 'print-logo', 'id' => 'logo'))) : NULL; + + $variables['print_node'] = $node; + $variables['content'] = $node->content; + $variables['scripts'] = drupal_get_js(); + $variables['footer_scripts'] = drupal_get_js('footer'); + $variables['sourceurl_enabled'] = variable_get('print_sourceurl_enabled', PRINT_SOURCEURL_ENABLED_DEFAULT); + $variables['url'] = url($path, array('absolute' => TRUE, 'query' => $variables['query'])); + $variables['source_url'] = url(variable_get('print_sourceurl_forcenode', PRINT_SOURCEURL_FORCENODE_DEFAULT) ? drupal_get_normal_path($path) : $path, array('alias' => TRUE, 'absolute' => TRUE, 'query' => $variables['query'])); + $variables['cid'] = isset($node->cid) ? $node->cid : NULL; + $variables['print_title'] = check_plain($node->title); + $variables['head'] = drupal_get_html_head(); + $variables['robots_meta'] = _print_robots_meta_generator(); + $variables['css'] = _print_css_generator($variables['expand_css']); + + if (variable_get('print_html_sendtoprinter', PRINT_HTML_SENDTOPRINTER_DEFAULT) && ($format == 'html')) { + drupal_add_js('misc/drupal.js', array('weight' => JS_LIBRARY)); + + $window_close = (variable_get('print_html_new_window', PRINT_HTML_NEW_WINDOW_DEFAULT) && variable_get('print_html_windowclose', PRINT_HTML_WINDOWCLOSE_DEFAULT)) ? 'window.close();' : ''; + $variables['sendtoprinter'] = ''; + } + + $type = (isset($node->type)) ? $node->type : ''; + $nid = (isset($node->nid)) ? $node->nid : ''; + + $variables['theme_hook_suggestions'] = array(); + $variables['theme_hook_suggestions'][] = "print__node__{$type}"; + $variables['theme_hook_suggestions'][] = "print__node__{$type}__{$nid}"; + $variables['theme_hook_suggestions'][] = "print__{$format}"; + $variables['theme_hook_suggestions'][] = "print__{$format}__node__{$type}"; + $variables['theme_hook_suggestions'][] = "print__{$format}__node__{$type}__{$nid}"; +} + +/** + * Returns HTML for the published line of the print template. + * + * @param array $vars + * An empty associative array + * + * @return string + * HTML text with the published line + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_published($vars) { + global $base_url; + + $published_site = variable_get('site_name', 0); + return $published_site ? t('Published on %site_name', array('%site_name' => $published_site)) . ' (' . l($base_url, $base_url) . ')' : ''; +} + +/** + * Returns HTML for the breadcrumb line of the print template. + * + * @param array $vars + * An associative array containing: + * - $node: the node object + * + * @return string + * HTML text with the breadcrumb + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_breadcrumb($vars) { + $node = $vars['node']; + $old_path = $_GET['q']; + + $path = empty($node->nid) ? $node->path : "node/$node->nid"; + menu_set_active_item($path); + $breadcrumb = drupal_get_breadcrumb(); + if (!empty($breadcrumb)) { + $breadcrumb[] = menu_get_active_title(); + menu_set_active_item($old_path); + return filter_xss(implode(' > ', $breadcrumb)); + } + else { + menu_set_active_item($old_path); + return ''; + } +} + +/** + * Returns HTML for the footer of the print template. + * + * @param array $vars + * An empty associative array + * + * @return string + * HTML text with the footer + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_footer($vars) { + $footer = ''; + + switch (variable_get('print_footer_options', PRINT_FOOTER_OPTIONS_DEFAULT)) { + case 1: // theme's + $footer_blocks = block_get_blocks_by_region('footer'); + $footer = variable_get('site_footer', FALSE) . "\n" . drupal_render($footer_blocks); + break; + case 2: // user-specifed + $footer = variable_get('print_footer_user', PRINT_FOOTER_USER_DEFAULT); + break; + } + // Delete the contextual links + $footer = preg_replace('!\s*!sim', '', $footer); + + return filter_xss_admin($footer); +} + +/** + * Returns HTML for the source URL line of the print template. + * + * @param array $vars + * An associative array containing: + * - $url: the URL to the full node view. + * - $node: the node object. + * - $cid; comment ID of the comment to display. + * + * @return string + * HTML text with the footer + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_sourceurl($vars) { + $sourceurl_date = variable_get('print_sourceurl_date', PRINT_SOURCEURL_DATE_DEFAULT); + $url = is_int($vars['cid']) ? $vars['url'] . '#comment-' . $vars['cid'] : $vars['url']; + + $output = '' . t('Source URL'); + if ($sourceurl_date && isset($vars['node'])) { + $output .= ' ('; + $date = format_date($vars['node']->changed, 'short'); + + $output .= empty($vars['node']->nid) ? t('retrieved on !date', array('!date' => $date)) : t('modified on !date', array('!date' => $date)); + + $output .= ')'; + } + $output .= ': ' . $url; + + return $output; +} + +/** + * Returns HTML for the URL list of the print template. + * + * @param array $vars + * An empty associative array + * + * @return string + * HTML text with the URL list + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_url_list($vars) { + global $_print_urls; + + // Display the collected links at the bottom of the page. Code once taken from Kjartan Mannes' project.module + if (!empty($_print_urls)) { + $urls = _print_friendly_urls(); + $max = count($urls); + $url_list = ''; + foreach ($urls as $key => $url) { + drupal_alter('print_url_list', $url); + $url_list .= '[' . ($key + 1) . '] ' . check_plain($url) . "
\n"; + } + if (!empty($url_list)) { + return "

" . t('Links') . "
$url_list

"; + } + else { + return ''; } } - return $print; } /** * Generates a robots meta tag to tell them what they may index * - * @return - * string with the meta robots tag + * @return string + * 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)) { + if (variable_get('print_robots_noindex', PRINT_ROBOTS_NOINDEX_DEFAULT)) { $robots_meta[] = 'noindex'; } - if (!empty($print_robots_nofollow)) { + if (variable_get('print_robots_nofollow', PRINT_ROBOTS_NOFOLLOW_DEFAULT)) { $robots_meta[] = 'nofollow'; } - if (!empty($print_robots_noarchive)) { + if (variable_get('print_robots_noarchive', PRINT_ROBOTS_NOARCHIVE_DEFAULT)) { $robots_meta[] = 'noarchive'; } if (count($robots_meta) > 0) { - $robots_meta = implode(', ', $robots_meta); - $robots_meta = "\n"; + return ''; } else { - $robots_meta = ''; + return ''; } - - return $robots_meta; } /** - * Post-processor that fills the array for the template with common details + * Generates the CSS directive to include in the printer-friendly version * - * @param $node - * generated node with a printer-friendly node body - * @param array $query - * (optional) array of key/value pairs as used in the url() function for the - * query - * @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 + * @param bool $expand + * If TRUE, the provided CSS will be expanded, instead of given as a list + * of includes. + * + * @return string + * applicable CSS */ -function _print_var_generator($node, $query = NULL, $message = NULL, $cid = NULL) { - global $base_url, $language, $_print_urls; - - $path = empty($node->nid) ? $node->path : "node/$node->nid"; - - // print module settings +function _print_css_generator($expand = FALSE) { $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', array('weight' => JS_LIBRARY)); - } - $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, 'query' => $query)); - $print['base_href'] = "\n"; - $print['favicon'] = theme_get_setting('toggle_favicon') ? "\n" : ''; if (!empty($print_css)) { - drupal_add_css(strtr($print_css, array('%t' => path_to_theme()))); + 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) { + if (!variable_get('print_keep_theme_css', PRINT_KEEP_THEME_CSS_DEFAULT)) { foreach ($drupal_css as $key => $css_file) { if ($css_file['group'] == CSS_THEME) { // Unset the theme's CSS @@ -208,131 +394,33 @@ function _print_var_generator($node, $query = NULL, $message = NULL, $cid = NULL } } - // If we are sending a message via email, the CSS must be embedded - if (!empty($message)) { + // Expand the CSS if requested + if ($expand) { $style = ''; $css_files = array_keys($drupal_css); foreach ($css_files as $filename) { - $res = file_exists($filename) ? file_get_contents($filename, TRUE) : FALSE; - if ($res != FALSE) { - $style .= $res; + if (file_exists($filename)) { + $style .= file_get_contents($filename, TRUE); } } - $print['css'] = "\n"; + return "\n"; } else { - $print['css'] = drupal_get_css($drupal_css); + return drupal_get_css($drupal_css); } - - $window_close = ($print_html_new_window && $print_html_windowclose) ? 'window.close();' : ''; - $print['sendtoprinter'] = $print_html_sendtoprinter ? '' : ''; - - 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', array('path' => $logo_url, 'alt' => $site_name, 'attributes' => array('class' => 'print-logo', 'id' => 'logo'))) : ''; - - switch ($print_footer_options) { - case 0: // none - $footer = ''; - break; - case 1: // theme's - $footer_blocks = block_get_blocks_by_region('footer'); - $footer = variable_get('site_footer', FALSE) . "\n" . drupal_render($footer_blocks); - 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(REQUEST_TIME, 'short'); - $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'] = '' . $source_url . $print['printdate'] . ': ' . 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]) . "
\n"; - } - $links = filter_xss(variable_get('print_text_links', t('Links'))); - $print['pfp_links'] = "

$links:
$pfp_links

"; - } - } - - $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. + * Manipulate URLs to make them absolute in the URLs list, and add a [n] + * footnote marker. * - * @param $matches + * @param array $matches * array with the matched tag patterns, usually +text+ - * @return - * tag with re-written URL and when appropriate the [n] index to the - * URL list + * + * @return string + * tag with re-written URL and, if applicable, the [n] index to the URL list */ function _print_rewrite_urls($matches) { global $base_url, $base_root, $_print_urls; @@ -387,7 +475,7 @@ function _print_rewrite_urls($matches) { } // Because base href is the original page, change the link to // still be usable inside the print page - $matches[1] = str_replace($url, base_path() . $_GET['q'] . $url, $matches[1]); + $matches[1] = str_replace($url, check_plain(base_path() . $_GET['q'] . $url), $matches[1]); } else { // URL is relative, convert it into absolute URL @@ -416,15 +504,16 @@ function _print_rewrite_urls($matches) { } } - return $ret; + return filter_xss_admin($ret); } /** * Auxiliary function to store the Printer-friendly URLs list as static. * - * @param $url + * @param string $url * absolute URL to be inserted in the list - * @return + * + * @return array * list of URLs previously stored if $url is 0, or the current count * otherwise. */ @@ -448,43 +537,20 @@ function _print_friendly_urls($url = 0) { /** * Check URL list settings for this node * - * @param node + * @param object $node * node object - * @param $format + * @param string $format * format of the page being generated - * @return + * + * @return bool * TRUE if URL list should be displayed, FALSE otherwise */ -function _print_url_list_enabled($node, $format = PRINT_HTML_FORMAT) { +function _print_url_list_enabled($node, $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; - } + $node_urllist = variable_get('print_' . $format . '_display_sys_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; - } + $node_urllist = isset($node->{'print_' . $format . '_display_urllist'}) ? $node->{'print_' . $format . '_display_urllist'} : variable_get('print_' . $format . '_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); } // Get value of Printer-friendly URLs setting @@ -494,23 +560,21 @@ function _print_url_list_enabled($node, $format = PRINT_HTML_FORMAT) { /** * Prepare a Printer-friendly-ready node body for content nodes * - * @param $nid + * @param int $nid * node ID of the node to be rendered into a printer-friendly page - * @param array $query - * (optional) array of key/value pairs as used in the url() function for the - * query - * @param $cid - * comment ID of the individual comment to be rendered - * @param $format + * @param string $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 + * @param int $vid + * (optional) revision ID of the node to use + * @param int $cid + * (optional) comment ID of the individual comment to be rendered + * @param string $view_mode + * (optional) view mode to be used when rendering the content + * + * @return object + * filled node-like object to be used in the print template */ -function _print_generate_node($nid, $query = NULL, $cid = NULL, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) { +function _print_generate_node($nid, $format, $vid = NULL, $cid = NULL, $view_mode = PRINT_VIEW_MODE) { global $_print_urls; if (!isset($langcode)) { @@ -518,7 +582,7 @@ function _print_generate_node($nid, $query = NULL, $cid = NULL, $format = PRINT_ } // We can take a node id - $node = node_load($nid); + $node = node_load($nid, $vid); if (!$node) { // Node not found drupal_not_found(); @@ -531,17 +595,6 @@ function _print_generate_node($nid, $query = NULL, $cid = NULL, $format = PRINT_ } drupal_set_title($node->title); - $view_mode = $teaser ? 'teaser' : '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 @@ -549,18 +602,13 @@ function _print_generate_node($nid, $query = NULL, $cid = NULL, $format = PRINT_ // Disable the links area unset($node->content['links']); - // Disable fivestar widget output - unset($node->content['fivestar_widget']); - // Disable service links module output - unset($node->content['service_links']); $build = $node->content; unset($node->content); } - $print_comments = variable_get('print_comments', PRINT_COMMENTS_DEFAULT); - - if (function_exists('comment_node_page_additions') && (($cid != NULL) || ($print_comments))) { + if (function_exists('comment_node_page_additions') && + (($cid != NULL) || (variable_get('print_comments', PRINT_COMMENTS_DEFAULT)))) { // Print only the requested comment (or if $cid is NULL, all of them) $comments = comment_node_page_additions($node); @@ -609,30 +657,23 @@ function _print_generate_node($nid, $query = NULL, $cid = NULL, $format = PRINT_ $pattern = '!<(a\s[^>]*?)>(.*?)()!is'; $content = preg_replace_callback($pattern, '_print_rewrite_urls', $content); - $print = _print_var_generator($node, $query, $message, $cid); - $print['content'] = $content; + $node->content = $content; - return $print; + return $node; } /** * Prepare a Printer-friendly-ready node body for non-content pages * - * @param $path + * @param string $path * path of the node to be rendered into a printer-friendly page - * @param array $query - * (optional) array of key/value pairs as used in the url() function for the - * query - * @param $format + * @param string $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 + * + * @return object + * filled node-like object to be used in the print template */ -function _print_generate_path($path, $query = NULL, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) { +function _print_generate_path($path, $format) { global $_print_urls; // Handle node tabs @@ -646,13 +687,13 @@ function _print_generate_path($path, $query = NULL, $format = PRINT_HTML_FORMAT, menu_set_active_item($path); // Adapted from index.php. $node = new stdClass(); - $node->body = menu_execute_active_handler($path, FALSE); - if (is_array($node->body)) { - $node->body = drupal_render($node->body); + $node->content = menu_execute_active_handler($path, FALSE); + if (is_array($node->content)) { + $node->content = drupal_render($node->content); } - if (is_int($node->body)) { - switch ($node->body) { + if (is_int($node->content)) { + switch ($node->content) { case MENU_NOT_FOUND: drupal_not_found(); return FALSE; @@ -666,43 +707,37 @@ function _print_generate_path($path, $query = NULL, $format = PRINT_HTML_FORMAT, $node->title = drupal_get_title(); $node->path = $path; - $node->changed = 0; + $node->changed = REQUEST_TIME; // Delete any links area - $node->body = preg_replace('!\s*!sim', '', $node->body); + $node->content = preg_replace('!\s*!sim', '', $node->content); + + // Delete the contextual links also + $node->content = preg_replace('!\s*!sim', '', $node->content); // Check URL list settings $_print_urls = _print_url_list_enabled($node, $format); // Convert the a href elements $pattern = '!<(a\s[^>]*?)>(.*?)()!is'; - $node->body = preg_replace_callback($pattern, '_print_rewrite_urls', $node->body); + $node->content = preg_replace_callback($pattern, '_print_rewrite_urls', $node->content); - $print = _print_var_generator($node, $query, $message); - $print['content'] = $node->body; - - return $print; + return $node; } /** * Prepare a Printer-friendly-ready node body for book pages * - * @param $nid + * @param int $nid * node ID of the node to be rendered into a printer-friendly page - * @param array $query - * (optional) array of key/value pairs as used in the url() function for the - * query - * @param $format + * @param string $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 + * + * @return object + * filled node-like object to be used in the print template */ -function _print_generate_book($nid, $query = NULL, $format = PRINT_HTML_FORMAT, $teaser = FALSE, $message = NULL) { +function _print_generate_book($nid, $format) { global $_print_urls; $node = node_load($nid); @@ -718,20 +753,14 @@ function _print_generate_book($nid, $query = NULL, $format = PRINT_HTML_FORMAT, } $tree = book_menu_subtree_data($node->book); - $node->body = book_export_traverse($tree, 'book_node_export'); + $node->content = 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[^>]*?)>(.*?)()!is'; - $node->body = preg_replace_callback($pattern, '_print_rewrite_urls', $node->body); + $node->content = preg_replace_callback($pattern, '_print_rewrite_urls', $node->content); - $print = _print_var_generator($node, $query, $message); - $print['content'] = $node->body; - - // The title is already displayed by the book_recurse, so avoid duplication - $print['title'] = ''; - - return $print; + return $node; } diff --git a/sites/all/modules/contrib/admin/print/print.tpl.php b/sites/all/modules/contrib/admin/print/print.tpl.php index 18a50255..8c95a9fe 100644 --- a/sites/all/modules/contrib/admin/print/print.tpl.php +++ b/sites/all/modules/contrib/admin/print/print.tpl.php @@ -2,37 +2,110 @@ /** * @file - * Default print module template + * Default theme implementation to display a printer-friendly version page. * + * This file is akin to Drupal's page.tpl.php template. The contents being + * displayed are all included in the $content variable, while the rest of the + * template focuses on positioning and theming the other page elements. + * + * All the variables available in the page.tpl.php template should also be + * available in this template. In addition to those, the following variables + * defined by the print module(s) are available: + * + * Arguments to the theme call: + * - $node: The node object. For node content, this is a normal node object. + * For system-generated pages, this contains usually only the title, path + * and content elements. + * - $format: The output format being used ('html' for the Web version, 'mail' + * for the send by email, 'pdf' for the PDF version, etc.). + * - $expand_css: TRUE if the CSS used in the file should be provided as text + * instead of a list of @include directives. + * - $message: The message included in the send by email version with the + * text provided by the sender of the email. + * + * Variables created in the preprocess stage: + * - $print_logo: the image tag with the configured logo image. + * - $content: the rendered HTML of the node content. + * - $scripts: the HTML used to include the JavaScript files in the page head. + * - $footer_scripts: the HTML to include the JavaScript files in the page + * footer. + * - $sourceurl_enabled: TRUE if the source URL infromation should be + * displayed. + * - $url: absolute URL of the original source page. + * - $source_url: absolute URL of the original source page, either as an alias + * or as a system path, as configured by the user. + * - $cid: comment ID of the node being displayed. + * - $print_title: the title of the page. + * - $head: HTML contents of the head tag, provided by drupal_get_html_head(). + * - $robots_meta: meta tag with the configured robots directives. + * - $css: the syle tags contaning the list of include directives or the full + * text of the files for inline CSS use. + * - $sendtoprinter: depending on configuration, this is the script tag + * including the JavaScript to send the page to the printer and to close the + * window afterwards. + * + * print[--format][--node--content-type[--nodeid]].tpl.php + * + * The following suggestions can be used: + * 1. print--format--node--content-type--nodeid.tpl.php + * 2. print--format--node--content-type.tpl.php + * 3. print--format.tpl.php + * 4. print--node--content-type--nodeid.tpl.php + * 5. print--node--content-type.tpl.php + * 6. print.tpl.php + * + * Where format is the ouput format being used, content-type is the node's + * content type and nodeid is the node's identifier (nid). + * + * @see print_preprocess_print() + * @see theme_print_published + * @see theme_print_breadcrumb + * @see theme_print_footer + * @see theme_print_sourceurl + * @see theme_print_url_list + * @see page.tpl.php * @ingroup print */ ?> - - + + + - - - <?php print $print['title']; ?> - - - - - + + + <?php print $print_title; ?> + + + + + ' type='image/x-icon' /> + + - '. $print['message'] .'

'; - } ?> -

- + +

+ + +

+ +

-

+ - - + type)): ?> + + + + - - - + + + + + diff --git a/sites/all/modules/contrib/admin/print/print_epub/icons/epub_icon.png b/sites/all/modules/contrib/admin/print/print_epub/icons/epub_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fd49e3029d46e01100fea3c103f29952da6f0f17 GIT binary patch literal 500 zcmVqj=eIAyf%=&I+MURlE6Zfz(uCa zWU0+;vC@CF)qjhNi>%LvuhD_D(}1?tg0a$syx5DQ%9Fp_mB-$r!rQvT+`Wyx@V3>; zy4Tv9#`3(_;jq%}pvd#4%=4-ymB`rz&R;_dq4?)&BN z{OI!h>ht{X_Wktu{q_3&^!fhw`Tq6#{`mX;`TPF)`~Up?|NQ>{|Ns9Hb4nfn0004W zQchCYH`jDi3VJh3lHp8%$3Nw@;G3QE{|NmRk z#-i}OJI~!wlw9N+%0LLgqh}ZphCaX}y%#Vd9!NsWb&R_nK}jjZd;sk}bX-d58~6xX zYzlSfw39G~CY#`fV+^+vYH;z(RcD4PmV~eb=lgAeH9G_5t8m<7)n1zteD7M&im literal 0 HcmV?d00001 diff --git a/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.drush.inc b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.drush.inc new file mode 100644 index 00000000..4aba243f --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.drush.inc @@ -0,0 +1,32 @@ + '_print_epub_phpepub_drush_download_url', + ); +} + +/** + * Discover the correct URL of the package to download. + * + * @return string + * URL of the file to download, FALSE if not known + */ +function _print_epub_phpepub_drush_download_url() { + return PHPEPUB_DOWNLOAD_URI; +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.info b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.info new file mode 100644 index 00000000..0c4f09f3 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.info @@ -0,0 +1,12 @@ +name = "PHPePub library handler" +description = "EPUB generation library using PHPePub." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print_epub + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.module b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.module new file mode 100644 index 00000000..191ba12f --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.module @@ -0,0 +1,65 @@ + $t('Printer, email and EPUB versions - EPUB generation library'), + 'value' => $t('PHPePub') . ' ' . $version, + ); + } + } + } + break; + } + return $requirements; +} + +/** + * Find out the version of the PHPePub library + * + * @param string $epub_tool + * Filename of the tool to be analysed. + * + * @return string + * version number of the library + */ +function _print_epub_phpepub_version($epub_tool) { + require_once(DRUPAL_ROOT . '/' . $epub_tool); + + return EPub::VERSION; +} + +/** + * Implements hook_print_epub_available_libs_alter(). + */ +function print_epub_phpepub_print_epub_available_libs_alter(&$epub_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('phpepub', '!^EPub.php$!'); + + foreach ($tools as $tool) { + $epub_tools['print_epub_phpepub|' . $tool] = 'PHPePub (' . dirname($tool) . ')'; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.pages.inc b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.pages.inc new file mode 100644 index 00000000..23d7d86e --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/lib_handlers/print_epub_phpepub/print_epub_phpepub.pages.inc @@ -0,0 +1,48 @@ +setTitle(html_entity_decode($meta['title'], ENT_QUOTES, 'UTF-8')); + $epub->setIdentifier($meta['url'], EPub::IDENTIFIER_URI); + $epub->setLanguage($language->language); + if (isset($meta['name'])) { + $epub->setAuthor(strip_tags($meta['name']), strip_tags($meta['name'])); + } + $epub->setPublisher(variable_get('site_name', 'Drupal'), $base_url); + $epub->setSourceURL($meta['url']); + + @$epub->addChapter("Chapter", "epub.html", $html, FALSE); + + $epub->finalize(); // Finalize the book, and build the archive. + + // Close and output EPUB document + $epub->sendBook(empty($filename) ? 'page' : $filename); + return TRUE; +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.admin.inc b/sites/all/modules/contrib/admin/print/print_epub/print_epub.admin.inc new file mode 100644 index 00000000..08ef0067 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.admin.inc @@ -0,0 +1,115 @@ + 'fieldset', + '#title' => t('EPUB options'), + ); + + $form['settings']['print_epub_epub_tool'] = array( + '#type' => 'radios', + '#title' => t('EPUB generation tool'), + '#options' => $epub_tools, + '#default_value' => $epub_tool_default, + '#description' => t('This option selects the EPUB generation tool being used by this module to create the EPUB version.'), + ); + + $form['settings']['print_epub_images_via_file'] = array( + '#type' => 'checkbox', + '#title' => t('Access images via local file access'), + '#default_value' => variable_get('print_epub_images_via_file', PRINT_EPUB_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_epub_filename'] = array( + '#type' => 'textfield', + '#title' => t('EPUB filename'), + '#default_value' => variable_get('print_epub_filename', PRINT_EPUB_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 .epub extension will be appended automatically."), + ); + if (module_exists('token')) { + $form['settings']['print_epub_filename_patterns'] = array( + '#type' => 'fieldset', + '#title' => t('Replacement patterns'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['settings']['print_epub_filename_patterns']['descriptions'] = array( + '#theme' => 'token_tree', + '#token_types' => array('node'), + ); + } + + $form['settings']['print_epub_display_sys_urllist'] = array( + '#type' => 'checkbox', + '#title' => t('Printer-friendly URLs list in system pages'), + '#default_value' => variable_get('print_epub_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']['link_text'] = array( + '#type' => 'fieldset', + '#title' => t('Custom link text'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['settings']['link_text']['print_epub_link_text_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Enable custom link text'), + '#default_value' => variable_get('print_epub_link_text_enabled', PRINT_TYPE_LINK_TEXT_ENABLED_DEFAULT), + ); + $form['settings']['link_text']['print_epub_link_text'] = array( + '#type' => 'textfield', + '#default_value' => variable_get('print_epub_link_text', $link['text']), + '#description' => t('Text used in the link to the EPUB version.'), + ); + + $form['#validate'][] = '_print_epub_settings_validate'; + } + else { + variable_set('print_epub_epub_tool', PRINT_EPUB_EPUB_TOOL_DEFAULT); + + $form['settings'] = array( + '#type' => 'markup', + '#markup' => '

' . t("No EPUB generation tool found! Please download a supported PHP EPUB generation tool. Check this module's INSTALL.txt for more details.") . '

', + ); + } + + return system_settings_form($form); +} + +/** + * Form validation handler for print_epub_settings(). + * + * @see print_epub_settings() + * @ingroup forms + */ +function _print_epub_settings_validate($form, &$form_state) { + if (empty($form_state['values']['print_epub_epub_tool'])) { + form_set_error('print_epub_epub_tool', t("No EPUB tool selected")); + } +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.api.php b/sites/all/modules/contrib/admin/print/print_epub/print_epub.api.php new file mode 100644 index 00000000..437e68b6 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.api.php @@ -0,0 +1,96 @@ +writeHTML($html); + if ($filename) { + $epub->Output($filename); + return TRUE; + } + else { + return $epub->Output(); + } +} + +/** + * Alters the list of available EPUB libraries. + * + * During the configuration of the EPUB library to be used, the module needs + * to discover and display the available libraries. This function should use + * the internal _print_scan_libs() function which will scan both the module + * and the libraries directory in search of the unique file pattern that can + * be used to identify the library location. + * + * @param array $epub_tools + * An associative array using as key the format 'module|path', and as value + * a string describing the discovered library, where: + * - module: the machine name of the module that handles this library. + * - path: the path where the library is installed, relative to DRUPAL_ROOT. + * If the recommended path is used, it begins with sites/all/libraries. + * As a recommendation, the value should contain in parantheses the path + * where the library was found, to allow the user to distinguish between + * multiple install paths of the same library version. + * + * @ingroup print_hooks + */ +function hook_print_epub_available_libs_alter(&$epub_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('foo', '!^foo.php$!'); + + foreach ($tools as $tool) { + $epub_tools['print_epub_foo|' . $tool] = 'foo (' . dirname($tool) . ')'; + } +} + +/** + * Alters the EPUB filename. + * + * Changes the value of the EPUB filename variable, just before it is used to + * create the file. When altering the variable, do not suffix it with the + * '.epub' extension, as the module will do that automatically. + * + * @param string $epub_filename + * current value of the epub_filename variable, after processing tokens and + * any transliteration steps. + * @param string $path + * original alias/system path of the page being converted to EPUB. + * + * @ingroup print_hooks + */ +function hook_print_epub_filename_alter(&$epub_filename, &$path) { + $epub_filename = 'foo'; +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.drush.inc b/sites/all/modules/contrib/admin/print/print_epub/print_epub.drush.inc new file mode 100644 index 00000000..583783d9 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.drush.inc @@ -0,0 +1,65 @@ + 'Download and extract a EPUB library.', + 'arguments' => array( + 'library' => dt('The EPUB library to download. Available choices: !libs.', array('!libs' => implode(', ', array_keys($epub_libs)))), + ), + '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('epubdl'), + 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT, // No site or config needed. + ); + + return $items; +} + +/** + * Implements of drush_hook_COMMAND_validate(). + */ +function drush_print_epub_download_validate($library = NULL) { + if (is_null($library)) { + $epub_libs = array(); + drush_command_invoke_all_ref('drush_epub_libs_alter', $epub_libs); + + drush_set_error('DRUSH_EPUBDL_MISSING_ARG', dt("Usage: drush !cmd \nWhere is one of the following: !libs\n\nTry 'drush !cmd --help' for more information.", array('!cmd' => 'print-epub-download', '!libs' => implode(', ', array_keys($epub_libs))))); + } +} + +/** + * Download and extract EPUB archive. + * + * @param string $library + * library to download + */ +function drush_print_epub_download($library) { + $epub_libs = array(); + drush_command_invoke_all_ref('drush_epub_libs_alter', $epub_libs); + + if (isset($library) && isset($epub_libs[drupal_strtolower($library)])) { + $func = $epub_libs[drupal_strtolower($library)]['callback']; + + $download_url = $func(); + if ($download_url) { + _print_drush_download_lib($library, $download_url); + } + } + else { + drush_log(dt('Please specify a EPUB library. Available choices: !libs.', array('!libs' => implode(', ', array_keys($epub_libs)))), 'error'); + } +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.info b/sites/all/modules/contrib/admin/print/print_epub/print_epub.info new file mode 100644 index 00000000..63be5046 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.info @@ -0,0 +1,13 @@ +name = "EPUB version" +description = "Adds the capability to export pages as EPUB. Requires an EPUB library and the respective handler module." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print +configure = admin/config/user-interface/print/epub + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.install b/sites/all/modules/contrib/admin/print/print_epub/print_epub.install new file mode 100644 index 00000000..d97aedf4 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.install @@ -0,0 +1,159 @@ +fields(array( + 'weight' => 4, + )) + ->condition('type', 'module') + ->condition('name', 'print_epub') + ->execute(); +} + +/** + * Implements hook_uninstall(). + */ +function print_epub_uninstall() { + variable_del('print_epub_display_sys_urllist'); + variable_del('print_epub_filename'); + variable_del('print_epub_images_via_file'); + variable_del('print_epub_link_text'); + variable_del('print_epub_link_text_enabled'); + variable_del('print_epub_epub_tool'); + + variable_del('print_epub_book_link'); + variable_del('print_epub_link_class'); + variable_del('print_epub_link_pos'); + variable_del('print_epub_link_teaser'); + variable_del('print_epub_link_use_alias'); + variable_del('print_epub_show_link'); + variable_del('print_epub_sys_link_pages'); + variable_del('print_epub_sys_link_visibility'); + + $settings = db_query("SELECT name FROM {variable} WHERE name LIKE 'print\_epub\_display\_%'"); + foreach ($settings as $variable) { + variable_del($variable->name); + } +} + +/** + * Implements hook_schema(). + */ +function print_epub_schema() { + $schema['print_epub_node_conf'] = array( + 'description' => 'EPUB version node-specific configuration settings', + 'fields' => array( + 'nid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => 'The {node}.nid of the node.', + ), + 'link' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + 'size' => 'tiny', + 'description' => 'Show link', + ), + 'comments' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + 'size' => 'tiny', + 'description' => 'Show link in individual comments', + ), + 'url_list' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + 'size' => 'tiny', + 'description' => 'Show Printer-friendly URLs list', + ), + ), + 'primary key' => array('nid'), + ); + + $schema['print_epub_page_counter'] = array( + 'description' => 'EPUB version access counter', + 'fields' => array( + 'path' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'description' => 'Page path', + ), + 'totalcount' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'size' => 'big', + 'description' => 'Number of page accesses', + ), + 'timestamp' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Last access', + ), + ), + 'primary key' => array('path'), + ); + + return $schema; +} + +/** + * Remove hardcoded numeric deltas from all blocks + */ +function print_epub_update_7000(&$sandbox) { + $renamed_deltas = array( + 'print_epub' => array( + '0' => 'print_epub-top', + ), + ); + + update_fix_d7_block_deltas($sandbox, $renamed_deltas, array()); + + if (variable_get('print_epub_filename', '') == '[site-name] - [title] - [mod-yyyy]-[mod-mm]-[mod-dd]') { + variable_set('print_epub_filename', '[site:name] - [node:title] - [node:changed:custom:Y-m-d]'); + } +} + +/** + * Enable block and help area links + */ +function print_epub_update_7202(&$sandbox) { + $link_pos = variable_get('print_epub_link_pos', drupal_json_decode('{ "link": "link", "block": "block", "help": "help" }')); + $link_pos['block'] = 'block'; + $link_pos['help'] = 'help'; + variable_set('print_epub_link_pos', $link_pos); +} + +/** + * Increase size of the path field in the print_epub_page_counter table + */ +function print_epub_update_7203(&$sandbox) { + db_drop_primary_key('print_epub_page_counter'); + db_change_field('print_epub_page_counter', 'path', 'path', + array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'description' => 'Page path'), + array('primary key' => array('path'))); +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.module b/sites/all/modules/contrib/admin/print/print_epub/print_epub.module new file mode 100644 index 00000000..8fc04c87 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.module @@ -0,0 +1,254 @@ + 'epub', + 'text' => t('EPUB version'), + 'description' => t('Display a EPUB version of this page.'), + 'path' => 'printepub', + 'class' => 'print-epub', + 'icon' => 'epub_icon.png', + 'module' => 'print_epub', + ); +} + +/** + * Implements hook_permission(). + */ +function print_epub_permission() { + return array( + 'access EPUB version' => array( + 'title' => t('Access the EPUB version'), + 'description' => t('View the EPUB versions and the links to them in the original pages.'), + ), + ); +} + +/** + * Implements hook_menu(). + */ +function print_epub_menu() { + $link = print_epub_print_link(); + $items = array(); + + $items[$link['path']] = array( + 'title' => 'Printer-friendly EPUB', + 'page callback' => 'print_epub_controller', + 'access arguments' => array('access EPUB version'), + 'type' => MENU_CALLBACK, + 'file' => 'print_epub.pages.inc', + ); + $items[$link['path'] . '/' . $link['path']] = array( + 'access callback' => FALSE, + ); + $items['admin/config/user-interface/print/epub'] = array( + 'title' => 'EPUB', + 'description' => 'Configure the settings of the EPUB generation functionality.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('print_epub_settings'), + 'access arguments' => array('administer print'), + 'weight' => 3, + 'type' => MENU_LOCAL_TASK, + 'file' => 'print_epub.admin.inc', + ); + $items['admin/config/user-interface/print/epub/options'] = array( + 'title' => 'Options', + 'weight' => -1, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + + return $items; +} + +/** + * Implements hook_variable_info(). + */ +function print_epub_variable_info($options) { + $link = print_epub_print_link(); + + $variable['print_epub_link_text'] = array( + 'title' => t('EPUB version'), + 'description' => t('Text used in the link to the EPUB version.'), + 'type' => 'string', + 'default' => t($link['text']), + ); + + return $variable; +} + +/** + * Implements hook_block_info(). + */ +function print_epub_block_info() { + $block['print_epub-top']['info'] = t('Most EPUBed'); + $block['print_epub-top']['cache'] = DRUPAL_CACHE_GLOBAL; + return $block; +} + +/** + * Implements hook_block_view(). + */ +function print_epub_block_view($delta = 0) { + switch ($delta) { + case 'print_epub-top': + $block['subject'] = t('Most EPUBd'); + $result = db_query_range("SELECT path FROM {print_epub_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) + ->fetchAll(); + if (count($result)) { + $items = array(); + foreach ($result as $obj) { + $items[] = l(_print_get_title($obj->path), $obj->path); + } + $block['content'] = theme('item_list', array('items' => $items, 'type' => 'ul')); + } + break; + } + return $block; +} + +/** + * Implements hook_requirements(). + */ +function print_epub_requirements($phase) { + $requirements = array(); + $t = get_t(); + switch ($phase) { + // At runtime, make sure that a EPUB generation tool is selected + case 'runtime': + $print_epub_epub_tool = variable_get('print_epub_epub_tool', PRINT_EPUB_EPUB_TOOL_DEFAULT); + if (empty($print_epub_epub_tool)) { + $requirements['print_epub_tool'] = array( + 'title' => $t('Printer, email and EPUB versions - EPUB generation library'), + 'value' => $t('No EPUB tool selected'), + 'description' => $t('Please configure it in the !url.', array('!url' => l($t('EPUB settings page'), 'admin/config/user-interface/print/epub'))), + 'severity' => REQUIREMENT_ERROR, + ); + } + else { + $tool = explode('|', $print_epub_epub_tool); + + if (!is_file($tool[1]) || !is_readable($tool[1])) { + $requirements['print_epub_tool'] = array( + 'title' => $t('Printer, email and EPUB versions - EPUB generation library'), + 'value' => $t('File not found'), + 'description' => $t('The currently selected EPUB generation library (%file) is no longer accessible.', array('%file' => $tool[1])), + 'severity' => REQUIREMENT_ERROR, + ); + } + } + break; + } + return $requirements; +} + +/** + * Implements hook_node_delete(). + */ +function print_epub_node_delete($node) { + db_delete('print_epub_page_counter') + ->condition('path', 'node/' . $node->nid) + ->execute(); +} + +/** + * Auxiliary function to display a formatted EPUB version link + * + * Function made available so that developers may call this function from + * their defined pages/blocks. + * + * @param string $path + * path to be used in the link. If not specified, the current URL is used. + * @param object $node + * node object, to be used in checking node access. If the path argument is + * not provided, the path used will be node/nid. + * @param string $location + * where in the page where the link is being inserted ('link', 'corner', + * 'block', 'help'). + * + * @return bool + * string with the HTML link to the printer-friendly page + * + * @ingroup print_api + */ +function print_epub_insert_link($path = NULL, $node = NULL, $location = '') { + if (function_exists('print_ui_insert_link')) { + return print_ui_insert_link(print_epub_print_link(), array('path' => $path, 'node' => $node, 'location' => $location)); + } + else { + return FALSE; + } +} + +/** + * Check if the link to the EPUB version is allowed depending on the settings + * + * @param array $args + * array containing the possible parameters: + * view_mode, node, type, path + * + * @return bool + * FALSE if not allowed, TRUE otherwise + */ +function print_epub_link_allowed($args) { + $print_epub_epub_tool = variable_get('print_epub_epub_tool', PRINT_EPUB_EPUB_TOOL_DEFAULT); + + return (user_access('access EPUB version') && (!empty($print_epub_epub_tool))); +} + +/** + * Generate a EPUB version of the provided HTML. + * + * @param string $html + * HTML content of the EPUB + * @param array $meta + * Meta information to be used in the EPUB + * - url: original URL + * - name: author's name + * - title: Page title + * - node: node object + * @param string $filename + * (optional) Filename of the generated EPUB + * + * @return + * generated EPUB page, or NULL in case of error + * + * @see print_epub_controller() + * + * @ingroup print_api + */ +function print_epub_generate_html($html, $meta, $filename = NULL) { + $epub_tool = explode('|', variable_get('print_epub_epub_tool', PRINT_EPUB_EPUB_TOOL_DEFAULT)); + + module_load_include('inc', $epub_tool[0], $epub_tool[0] . '.pages'); + + $function = $epub_tool[0] . '_print_epub_generate'; + if (function_exists($function)) { + return $function($html, $meta, $filename); + } + + return NULL; +} + +/** + * Implements hook_views_api(). + */ +function print_epub_views_api() { + return array( + 'api' => 2.0, + 'path' => drupal_get_path('module', 'print_epub'), + ); +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.pages.inc b/sites/all/modules/contrib/admin/print/print_epub/print_epub.pages.inc new file mode 100644 index 00000000..fa46a9d1 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.pages.inc @@ -0,0 +1,126 @@ + $node), array('clear' => TRUE)); + } + else { + $epub_filename = token_replace($epub_filename, array('site'), array('clear' => TRUE)); + if (empty($epub_filename)) { + // If empty, use a fallback solution + $epub_filename = str_replace('/', '_', $path); + } + } + } + else { + $epub_filename = 'page'; + } + + if (function_exists('transliteration_clean_filename')) { + $epub_filename = transliteration_clean_filename($epub_filename, language_default('language')); + } + + drupal_alter('print_epub_filename', $epub_filename, $path); + + $epub = print_epub_generate_path($path, $query, $cid, $epub_filename . '.epub'); + if ($epub == NULL) { + drupal_goto($path); + exit; + } + + $nodepath = (isset($node->nid)) ? 'node/' . $node->nid : drupal_get_normal_path($path); + db_merge('print_epub_page_counter') + ->key(array('path' => $nodepath)) + ->fields(array( + 'totalcount' => 1, + 'timestamp' => REQUEST_TIME, + )) + ->expression('totalcount', 'totalcount + 1') + ->execute(); + + drupal_exit(); +} + +/** + * Gennerate a EPUB for a given Drupal path. + * + * @param string $path + * path of the page to convert to EPUB + * @param array $query + * (optional) array of key/value pairs as used in the url() function for the + * query + * @param int $cid + * (optional) comment ID of the comment to render. + * @param string $epub_filename + * (optional) filename of the generated EPUB + * @param string $view_mode + * (optional) view mode to be used when rendering the content + * + * @return + * generated EPUB page, or NULL in case of error + * + * @see print_epub_controller() + */ +function print_epub_generate_path($path, $query = NULL, $cid = NULL, $epub_filename = NULL, $view_mode = PRINT_VIEW_MODE) { + global $base_url; + + $link = print_epub_print_link(); + $node = print_controller($path, $link['format'], $cid, $view_mode); + if ($node) { + $html = theme('print', array('node' => $node, 'query' => $query, 'expand_css' => TRUE, 'format' => $link['format'])); + + $meta = array( + 'node' => $node, + 'url' => url(drupal_get_path_alias(empty($node->nid) ? $node->path : "node/$node->nid"), array('absolute' => TRUE)), + ); + if (isset($node->name)) $meta['name'] = $node->name; + if (isset($node->title)) $meta['title'] = $node->title; + + return print_epub_generate_html($html, $meta, $epub_filename); + } + else { + return NULL; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_epub/print_epub.views.inc b/sites/all/modules/contrib/admin/print/print_epub/print_epub.views.inc new file mode 100644 index 00000000..30b9cd71 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_epub/print_epub.views.inc @@ -0,0 +1,121 @@ + 'nid', + 'field' => 'nid', +// 'type' => 'INNER', + ); + $data['print_epub_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_epub_node_conf fields + $data['print_epub_node_conf']['link'] = array( + 'title' => t('EPUB: Show link'), + 'help' => t('Whether to show the EPUB 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_epub_node_conf']['comments'] = array( + 'title' => t('EPUB: Show link in individual comments'), + 'help' => t('Whether to show the EPUB 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_epub_node_conf']['url_list'] = array( + 'title' => t('EPUB: 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_epub_page_counter fields + $data['print_epub_page_counter']['totalcount'] = array( + 'title' => t('EPUB: Number of page accesses'), + 'help' => t('Counter of accesses to the EPUB 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_epub_page_counter']['timestamp'] = array( + 'title' => t('EPUB: Last access'), + 'help' => t("The date of the last access to the node's EPUB 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; +} diff --git a/sites/all/modules/contrib/admin/print/print_join_page_counter.inc b/sites/all/modules/contrib/admin/print/print_join_page_counter.inc index e988d6e1..fe73f002 100644 --- a/sites/all/modules/contrib/admin/print/print_join_page_counter.inc +++ b/sites/all/modules/contrib/admin/print/print_join_page_counter.inc @@ -11,13 +11,15 @@ 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, $left_table, $left_field, $field, $extra = array(), $type = 'LEFT') { + 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 build_join($select_query, $table, $view_query) { - $this->left_field = "CONCAT('node/', " . $this->left_table . '.' . $this->left_field . ')'; - $this->left_table = NULL; + if ($this->left_table) { + $this->left_field = "CONCAT('node/', $this->left_table.$this->left_field)"; + $this->left_table = NULL; + } parent::build_join($select_query, $table, $view_query); } } diff --git a/sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme-rtl.css b/sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme-rtl.css new file mode 100644 index 00000000..0a09f70d --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme-rtl.css @@ -0,0 +1,3 @@ +label.printmail-label { + float: right; +} diff --git a/sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme.css b/sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme.css new file mode 100644 index 00000000..fe7096cb --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_mail/css/print_mail.theme.css @@ -0,0 +1,8 @@ +label.printmail-label { + width: 175px; + float: left; +} + +form#print-mail-form textarea#edit-txt-to-addrs { + width: auto; +} diff --git a/sites/all/modules/contrib/admin/print/print_mail/icons/mail_icon.png b/sites/all/modules/contrib/admin/print/print_mail/icons/mail_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2e4954b6f4bd6144af4b5d1d06bc7ddf8100b408 GIT binary patch literal 283 zcmV+$0p$LPP)$L-}cbs z_tE3`*5>%y>G|C1`Q7UI-|YI~?fT^I`snfd>GJ#Q^Zf1f{P6bt^7sAq`ThC({`~#^ z{{H{}|NpGuHkAMX00DGTPE!Ct=GbNc0037>L_t&-(_>&D1F#_jMv#Ci2q-JcNr?$@ zzy(y4`Y8dvXUY!%y1PT4WdH)JV+|o#f1fUxu60nN(wR(B7%I}oDcyH hBmfp*L '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', drupal_json_decode(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' => '')), - ); - - if (module_exists('php')) { - $access = user_access('use PHP for settings'); - - 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 TRUE (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' => '')); - } - } - - $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.') . '
' . - 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' => '')), - ); - - if (module_exists('php')) { - 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 TRUE (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' => '')); - } - } - - $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'), @@ -153,6 +48,13 @@ function print_mail_settings() { '#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_user_recipients'] = array( + '#type' => 'checkbox', + '#title' => t('Enable user list recipients'), + '#default_value' => variable_get('print_mail_user_recipients', PRINT_MAIL_USER_RECIPIENTS_DEFAULT), + '#description' => t("If selected, a user list will be included as possible email recipients."), + ); + $form['settings']['print_mail_teaser_choice'] = array( '#type' => 'checkbox', '#title' => t('Enable teaser/full mode choice'), @@ -188,78 +90,22 @@ function print_mail_settings() { '#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( + $form['settings']['link_text'] = array( '#type' => 'fieldset', - '#title' => t('Text strings'), + '#title' => t('Custom link text'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, ); - - $form['print_mail_text']['print_mail_link_text'] = array( + $form['settings']['link_text']['print_mail_link_text_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Enable custom link text'), + '#default_value' => variable_get('print_mail_link_text_enabled', PRINT_TYPE_LINK_TEXT_ENABLED_DEFAULT), + ); + $form['settings']['link_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.'), - ); - $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.'), - ); - $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.'), - ); - $form['print_mail_text']['reset'] = array( - '#type' => 'submit', - '#value' => t('Reset to defaults'), - '#submit' => array('print_mail_strings_settings_delete'), + '#default_value' => variable_get('print_mail_link_text', $link['text']), + '#description' => t('Text used in the link to the send by email form.'), ); return system_settings_form($form); } - -/** - * Reset button callback for text strings settings form - * - * @ingroup forms - */ -function print_mail_strings_settings_delete() { - variable_del('print_mail_link_text'); - variable_del('print_mail_text_title'); - variable_del('print_mail_text_subject'); - variable_del('print_mail_text_message'); - variable_del('print_mail_text_content'); - variable_del('print_mail_text_confirmation'); -} diff --git a/sites/all/modules/contrib/admin/print/print_mail/print_mail.inc b/sites/all/modules/contrib/admin/print/print_mail/print_mail.inc index 43785a9c..b673346e 100644 --- a/sites/all/modules/contrib/admin/print/print_mail/print_mail.inc +++ b/sites/all/modules/contrib/admin/print/print_mail/print_mail.inc @@ -10,19 +10,15 @@ * @ingroup print */ -require_once(DRUPAL_ROOT . '/' . drupal_get_path('module', 'print') . '/print.pages.inc'); - // Include MIME library @include_once('Mail/mime.php'); /** - * Menu callback for the send by email form. + * Form constructor for the send by email form. * * @ingroup forms */ function print_mail_form($form, &$form_state) { - global $user; - // Remove the printmail/ prefix $path_arr = explode('/', $_GET['q']); unset($path_arr[0]); @@ -30,13 +26,14 @@ function print_mail_form($form, &$form_state) { if (empty($path)) { // If no path was provided, let's try to generate a page for the referer global $base_url; + $link = print_mail_print_link(); $ref = $_SERVER['HTTP_REFERER']; $path = preg_replace("!^$base_url/!", '', $ref); if (($path === $ref) || empty($path)) { $path = variable_get('site_frontpage', 'node'); } - drupal_goto(PRINTMAIL_PATH . '/' . $path); + drupal_goto($link['path'] . '/' . $path); } elseif (ctype_digit($path_arr[1])) { if (drupal_lookup_path('source', $path)) { @@ -56,6 +53,19 @@ function print_mail_form($form, &$form_state) { $query = $_GET; unset($query['q']); + return print_mail_form_for_path($form, $form_state, $path, $query); +} + +/** + * Build email form for the page provided in the path argument. + * + * @ingroup forms + */ +function print_mail_form_for_path($form, &$form_state, $path, $query = NULL, $user = NULL) { + if ($user === NULL) { + global $user; + } + $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))) { @@ -68,11 +78,26 @@ function print_mail_form($form, &$form_state) { $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); + $print_mail_user_recipients_default = variable_get('print_mail_user_recipients', PRINT_MAIL_USER_RECIPIENTS_DEFAULT); $form = array(); $cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL; $title = _print_get_title($path); + if ($print_mail_user_recipients_default) { + $options = array(); + if (module_exists('realname')) { + $sql = "SELECT u.mail, r.realname AS name from {users} u LEFT JOIN {realname} r ON u.uid = r.uid WHERE u.uid <> :uid ORDER BY name ASC"; + } + else { + $sql = "SELECT mail, name from {users} WHERE uid <> :uid ORDER BY name ASC"; + } + $recipients = db_query($sql, array(':uid' => drupal_anonymous_user()->uid)); + foreach ($recipients as $recipient) { + $options[$recipient->mail] = $recipient->name; + } + } + if (count($form_state['input']) == 0) { $nodepath = drupal_get_normal_path($path); db_merge('print_mail_page_counter') @@ -101,14 +126,26 @@ function print_mail_form($form, &$form_state) { '#title' => t('Your name'), '#size' => 62, ); - $form['txt_to_addrs'] = array( + $form['txt_to'] = array( + '#tree' => TRUE, + ); + $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, + '#required' => !$print_mail_user_recipients_default, ); + if ($print_mail_user_recipients_default) { + $form['txt_to']['users'] = array( + '#type' => 'select', + '#title' => t('Send to users'), + '#multiple' => TRUE, + '#size' => 10, + '#options' => $options, + ); + } $form['fld_subject'] = array( '#type' => 'textfield', '#title' => t('Subject'), @@ -116,8 +153,8 @@ function print_mail_form($form, &$form_state) { '#required' => TRUE, ); if (!empty($title)) { - // To prevent useless translation strings, try to translate only node titles - if (drupal_substr($path, 0, 5) == 'node/') { + // To prevent useless translation strings, try to translate only non-node titles + if (drupal_substr($path, 0, 5) != 'node/') { $title = t($title); } @@ -150,10 +187,6 @@ function print_mail_form($form, &$form_state) { '#type' => 'submit', '#value' => t('Send email'), ); - $form['btn_clear'] = array( - '#type' => 'markup', - '#markup' => '', - ); $form['btn_cancel'] = array( '#name' => 'cancel', '#type' => 'submit', @@ -171,33 +204,37 @@ function print_mail_form($form, &$form_state) { $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); + $form['fld_subject']['#default_value'] = t('!user has sent you a message from !site', array('!user' => $user_name, '!site' => $site_name, '!title' => $title)); + $form['txt_message']['#default_value'] = t(''); return $form; } /** - * Theme function for the send by-email form submission. + * Returns HTML for the send by-email form. * * Adds a class to the form labels. This class is used to place the label on * the left of the input fields. * + * @param array $form + * Form array + * + * @see print_mail_form() * @ingroup forms + * @ingroup themeable + * @ingroup print_themeable */ function theme_print_mail_form($variables) { $form = $variables['form']; - drupal_add_css(drupal_get_path('module', 'print') . '/css/printlinks.css'); + drupal_add_css(drupal_get_path('module', 'print_mail') . '/css/print_mail.theme.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 'txt_to': case 'fld_subject': case 'fld_title': $tmp = str_replace('
' . l($params['title'], $params['link']); +} + +/** + * Form validation handler for print_mail_form(). + * + * @see print_mail_form() * @ingroup forms */ function print_mail_form_validate($form, &$form_state) { + $print_mail_user_recipients_default = variable_get('print_mail_user_recipients', PRINT_MAIL_USER_RECIPIENTS_DEFAULT); + if (array_key_exists('cancel', $form_state['input'])) { form_set_error(NULL, '', TRUE); drupal_get_messages('error'); @@ -227,10 +297,22 @@ function print_mail_form_validate($form, &$form_state) { 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); + $to_array = array(); + if (!empty($form_state['values']['txt_to']['users'])) { + $to_array = array_values($form_state['values']['txt_to']['users']); + } + + if (!empty($form_state['values']['txt_to']['addrs'])) { + // 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 = array_merge($to_array, explode(',', $to_addrs)); + } + + if (empty($to_array) && $print_mail_user_recipients_default) { + form_set_error('txt_to', t('You must specify at least one email address or user as a recipient.')); + } + // Verify each element of the array foreach ($to_array as $key => $address) { $address = trim($address); @@ -244,14 +326,14 @@ function print_mail_form_validate($form, &$form_state) { $test = user_validate_mail($address); } if ($test) { - form_set_error('txt_to_addrs', $test); + form_set_error('txt_to', $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))); + form_set_error('txt_to', 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 @@ -264,29 +346,33 @@ function print_mail_form_validate($form, &$form_state) { $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); + $form_state['values']['txt_to']['addrs'] = implode(', ', $to_array); } /** - * Process the send by-email form submission. + * Form submission handler for print_mail_form(). * + * @see print_mail_form() + * @see print_controller() * @ingroup forms */ function print_mail_form_submit($form, &$form_state) { if (!array_key_exists('cancel', $form_state['values'])) { + module_load_include('inc', 'print', 'print.pages'); + module_load_include('inc', 'print', 'includes/print'); + + $link = print_mail_print_link(); $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 . ':

' . nl2br(check_plain($form_state['values']['txt_message'])) . ''; + $view_mode = $form_state['values']['chk_teaser'] ? 'teaser' : PRINT_VIEW_MODE; + $node = print_controller($form_state['values']['path'], $link['format'], $cid, $view_mode); - $print = print_controller($form_state['values']['path'], $form_state['values']['query'], $cid, PRINT_MAIL_FORMAT, $form_state['values']['chk_teaser'], $sender_message); - - if ($print !== FALSE) { + if ($node) { $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['message'] = t('Message from sender') . ':

' . nl2br(check_plain($form_state['values']['txt_message'])) . ''; + $params['link'] = url($form_state['values']['path'], array('absolute' => TRUE, 'query' => $form_state['values']['query'])); $params['title'] = $form_state['values']['title']; // If a name is provided, make From: in the format Common Name
@@ -305,10 +391,9 @@ function print_mail_form_submit($form, &$form_state) { // 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->content = preg_replace_callback($pattern, '_print_replace_spaces', $node->content); - $node = $print['node']; - $params['body'] = theme('print', array('print' => $print, 'type' => PRINT_MAIL_FORMAT, 'node' => $node)); + $params['body'] = theme('print', array('node' => $node, 'query' => $form_state['values']['query'], 'format' => $link['format'], 'expand_css' => TRUE, 'message' => $params['message'])); // Img elements must be set to absolute $pattern = '!<(img\s[^>]*?)>!is'; @@ -318,13 +403,16 @@ function print_mail_form_submit($form, &$form_state) { $pattern = '!<(a\s[^>]*?)>!is'; $params['body'] = preg_replace_callback($pattern, '_print_rewrite_urls', $params['body']); + // Enable support for third-party modules to alter the e-mail before it's sent + drupal_alter('print_mail', $params, $to); + $ok = FALSE; $use_job_queue = variable_get('print_mail_job_queue', PRINT_MAIL_JOB_QUEUE_DEFAULT); if ($use_job_queue) { $queue = DrupalQueue::get('print_mail_send'); } - $addresses = explode(', ', $form_state['values']['txt_to_addrs']); + $addresses = explode(', ', $form_state['values']['txt_to']['addrs']); foreach ($addresses as $to) { if ($use_job_queue) { // Use job queue to send mails during cron runs @@ -341,10 +429,9 @@ function print_mail_form_submit($form, &$form_state) { } if ($ok) { $query = empty($form_state['values']['query']) ? '' : '?' . rawurldecode(drupal_http_build_query($form_state['values']['query'])); - 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'] . $query, '%to' => $form_state['values']['txt_to_addrs'])); + 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'] . $query, '%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)))); + drupal_set_message(check_plain(t('Thank you for spreading the word about !site.', array('!site' => $site_name)))); $nodepath = drupal_get_normal_path($form_state['values']['path']); db_update('print_mail_page_counter') diff --git a/sites/all/modules/contrib/admin/print/print_mail/print_mail.info b/sites/all/modules/contrib/admin/print/print_mail/print_mail.info index 4d62ebf3..bfd9dab2 100644 --- a/sites/all/modules/contrib/admin/print/print_mail/print_mail.info +++ b/sites/all/modules/contrib/admin/print/print_mail/print_mail.info @@ -1,18 +1,13 @@ name = "Send by email" description = "Provides the capability to send the web page by email" -core=7.x +core = 7.x package = "Printer, email and PDF versions" dependencies[] = print -files[] = print_mail.module -files[] = print_mail.inc -files[] = print_mail.admin.inc -files[] = print_mail.install -files[] = print_mail.views.inc configure = admin/config/user-interface/print/email -; Information added by drupal.org packaging script on 2012-09-04 -version = "7.x-1.2" +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" core = "7.x" project = "print" -datestamp = "1346768900" +datestamp = "1396426766" diff --git a/sites/all/modules/contrib/admin/print/print_mail/print_mail.install b/sites/all/modules/contrib/admin/print/print_mail/print_mail.install index 1b91e057..fd44e029 100644 --- a/sites/all/modules/contrib/admin/print/print_mail/print_mail.install +++ b/sites/all/modules/contrib/admin/print/print_mail/print_mail.install @@ -40,29 +40,26 @@ function print_mail_disable() { * Implements hook_uninstall(). */ function print_mail_uninstall() { - variable_del('print_mail_settings'); - variable_del('print_mail_show_link'); + variable_del('print_mail_display_sys_urllist'); + variable_del('print_mail_hourly_threshold'); + variable_del('print_mail_job_queue'); + variable_del('print_mail_link_text'); + variable_del('print_mail_link_text_enabled'); + variable_del('print_mail_send_option_default'); + variable_del('print_mail_teaser_choice'); + variable_del('print_mail_teaser_default'); + variable_del('print_mail_use_reply_to'); + variable_del('print_mail_user_recipients'); + + variable_del('print_mail_book_link'); + variable_del('print_mail_link_class'); 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'); + variable_del('print_mail_show_link'); + variable_del('print_mail_sys_link_pages'); + variable_del('print_mail_sys_link_visibility'); + $settings = db_query("SELECT name FROM {variable} WHERE name LIKE 'print\_mail\_display\_%'"); foreach ($settings as $variable) { variable_del($variable->name); @@ -115,7 +112,7 @@ function print_mail_schema() { 'fields' => array( 'path' => array( 'type' => 'varchar', - 'length' => 128, + 'length' => 255, 'not null' => TRUE, 'description' => 'Page path', ), @@ -192,12 +189,38 @@ function print_mail_update_7101(&$sandbox) { ->execute(); } +/** + * Delete old variables + */ +function print_mail_update_7200(&$sandbox) { + variable_del('print_mail_settings'); + + variable_del('print_mail_node_link_pages'); + variable_del('print_mail_node_link_visibility'); + + 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'); +} + /** * Enable block and help area links */ -function print_mail_update_7102(&$sandbox) { +function print_mail_update_7202(&$sandbox) { $link_pos = variable_get('print_mail_link_pos', drupal_json_decode('{ "link": "link", "block": "block", "help": "help" }')); $link_pos['block'] = 'block'; $link_pos['help'] = 'help'; variable_set('print_mail_link_pos', $link_pos); } + +/** + * Increase size of the path field in the print_mail_page_counter table + */ +function print_mail_update_7203(&$sandbox) { + db_drop_primary_key('print_mail_page_counter'); + db_change_field('print_mail_page_counter', 'path', 'path', + array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'description' => 'Page path'), + array('primary key' => array('path'))); +} diff --git a/sites/all/modules/contrib/admin/print/print_mail/print_mail.module b/sites/all/modules/contrib/admin/print/print_mail/print_mail.module index 517a9165..4520f24c 100644 --- a/sites/all/modules/contrib/admin/print/print_mail/print_mail.module +++ b/sites/all/modules/contrib/admin/print/print_mail/print_mail.module @@ -7,27 +7,28 @@ * @ingroup print */ -define('PRINTMAIL_PATH', 'printmail'); - -// Defined in print.module -// define('PRINT_MAIL_FORMAT', 'mail'); - -define('PRINT_MAIL_LINK_POS_DEFAULT', '{ "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); +define('PRINT_MAIL_USER_RECIPIENTS_DEFAULT', 0); + +/** + * Implements hook_print_link(). + */ +function print_mail_print_link() { + return array( + 'format' => 'mail', + 'text' => t('Send by email'), + 'description' => t('Send this page by email.'), + 'path' => 'printmail', + 'class' => 'print-mail', + 'icon' => 'mail_icon.png', + 'module' => 'print_mail', + ); +} /** * Implements hook_permission(). @@ -50,13 +51,18 @@ function print_mail_permission() { */ function print_mail_theme() { return array( - 'print_mail_format_link' => array( - 'variables' => array(), - ), 'print_mail_form' => array( 'render element' => 'form', 'file' => 'print_mail.inc', ), + 'print_mail_sendlink_html' => array( + 'variables' => array('params' => NULL), + 'file' => 'print_mail.inc', + ), + 'print_mail_sendlink_plain' => array( + 'variables' => array('params' => NULL), + 'file' => 'print_mail.inc', + ), ); } @@ -64,10 +70,11 @@ function print_mail_theme() { * Implements hook_menu(). */ function print_mail_menu() { + $link = print_mail_print_link(); $items = array(); - $items[PRINTMAIL_PATH] = array( - 'title' => variable_get('print_mail_text_title', 'Send page by email'), + $items[$link['path']] = array( + 'title' => 'Send by email', 'page callback' => 'drupal_get_form', 'page arguments' => array('print_mail_form'), 'access callback' => '_print_mail_access', @@ -75,7 +82,7 @@ function print_mail_menu() { 'type' => MENU_CALLBACK, 'file' => 'print_mail.inc', ); - $items[PRINTMAIL_PATH . '/' . PRINTMAIL_PATH] = array( + $items[$link['path'] . '/' . $link['path']] = array( 'access callback' => FALSE, ); $items['admin/config/user-interface/print/email'] = array( @@ -88,25 +95,26 @@ function print_mail_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'print_mail.admin.inc', ); - $items['admin/config/user-interface/print/email/options'] = array( - 'title' => 'Options', - 'weight' => 1, - 'type' => MENU_DEFAULT_LOCAL_TASK, - ); - $items['admin/config/user-interface/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; } +/** + * Implements hook_variable_info(). + */ +function print_mail_variable_info($options) { + $link = print_mail_print_link(); + + $variable['print_mail_link_text'] = array( + 'title' => t('Send by email'), + 'description' => t('Text used in the link to the send by email form.'), + 'type' => 'string', + 'default' => t($link['text']), + ); + + return $variable; +} + /** * Implements hook_requirements(). */ @@ -136,207 +144,41 @@ function print_mail_requirements($phase) { * Implements hook_block_info(). */ function print_mail_block_info() { - $block['print_mail-top']['info'] = t('Most emailed'); - $block['print_mail-top']['cache'] = DRUPAL_CACHE_GLOBAL; - return $block; + $block['print_mail-top']['info'] = t('Most emailed'); + $block['print_mail-top']['cache'] = DRUPAL_CACHE_GLOBAL; + return $block; } /** * Implements hook_block_view(). */ function print_mail_block_view($delta = 0) { - switch ($delta) { - case 'print_mail-top': - $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) - ->fetchAll(); - if (count($result)) { - $block['content'] = '
    '; - foreach ($result as $obj) { - $block['content'] .= '
  • ' . l(_print_get_title($obj->path), $obj->path) . '
  • '; - } - $block['content'] .= '
'; + switch ($delta) { + case 'print_mail-top': + $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) + ->fetchAll(); + if (count($result)) { + $items = array(); + foreach ($result as $obj) { + $items[] = l(_print_get_title($obj->path), $obj->path); } - break; + $block['content'] = theme('item_list', array('items' => $items, 'type' => 'ul')); } - return $block; -} - -/** - * Implements hook_node_view(). - */ -function print_mail_node_view($node, $view_mode) { - $print_mail_link_pos = variable_get('print_mail_link_pos', drupal_json_decode(PRINT_MAIL_LINK_POS_DEFAULT)); - $print_mail_link_use_alias = variable_get('print_mail_link_use_alias', PRINT_MAIL_LINK_USE_ALIAS_DEFAULT); - - foreach (array('node', 'comment') as $type) { - $allowed_type = print_mail_link_allowed(array('type' => $type, 'node' => $node, 'view_mode' => $view_mode)); - 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'], - ); - } - elseif ($allowed_type === PRINT_ALLOW_NORMAL_LINK) { - $path = (($print_mail_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/' . $node->nid))) ? $alias : $node->nid; - - $links['print_mail'] = array( - 'href' => PRINTMAIL_PATH . '/' . $path, - 'title' => $format['text'], - 'attributes' => $format['attributes'], - 'html' => $format['html'], - 'query' => print_query_string_encode($_GET, array('q')), - ); - } - - $link_content = array( - '#theme' => 'links', - '#links' => $links, - '#attributes' => array('class' => array('links', 'inline')), - ); - - if ($type == 'node') { - $node->content['links']['print_mail'] = $link_content; - } - elseif (($type == 'comment') && isset($node->content['comments']['comments'])) { - foreach ($node->content['comments']['comments'] as $cid => $comment) { - if (is_numeric($cid)) { - $link_content['#links']['print_mail']['query']['comment'] = $cid; - $node->content['comments']['comments'][$cid]['links']['print_mail'] = $link_content; - } - } - } - } - } - - // Insert content corner links - if (!empty($print_mail_link_pos['corner']) && ($view_mode == 'full')) { - $node->content['print_links']['#markup'] .= print_mail_insert_link(NULL, $node); - } -} - -/** - * Implements hook_help(). - */ -function print_mail_help($path, $arg) { - $print_mail_link_pos = variable_get('print_mail_link_pos', drupal_json_decode(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 "$link"; - } - } - } -} - -/** - * Implements hook_node_load(). - */ -function print_mail_node_load($nodes, $types) { - $ids = array(); - foreach ($nodes as $node) { - $ids[] = $node->nid; - } - - $result = db_query('SELECT nid, link, comments, url_list FROM {print_mail_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid'); - - foreach ($nodes as $node) { - $node->print_mail_display = isset($result[$node->nid]) ? intval($result[$node->nid]->link) : variable_get('print_mail_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT); - $node->print_mail_display_comment = isset($result[$node->nid]) ? intval($result[$node->nid]->comments) : variable_get('print_mail_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT); - $node->print_mail_display_urllist = isset($result[$node->nid]) ? intval($result[$node->nid]->url_list) : variable_get('print_mail_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); - } -} - -/** - * Implements hook_node_insert(). - */ -function print_mail_node_insert($node) { - 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); - } -} - -/** - * Implements hook_node_update(). - */ -function print_mail_node_update($node) { - 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; } + return $block; } /** * Implements hook_node_delete(). */ function print_mail_node_delete($node) { - db_delete('print_mail_node_conf') - ->condition('nid', $node->nid) - ->execute(); db_delete('print_mail_page_counter') ->condition('path', 'node/' . $node->nid) ->execute(); } -/** - * Implements 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') || !empty($form['#node_edit_form']))) { - $form['print']['mail_label'] = array( - '#type' => 'markup', - '#markup' => '

' . t('Send by email') . '

', - ); - - $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); - } - } -} - /** * Implements hook_cron_queue_info(). */ @@ -348,6 +190,19 @@ function print_mail_cron_queue_info() { return $queues; } +/** + * Worker callback for print_mail_cron_queue_info() + * + * @param array $data + * An associative array containing: + * - module: A module name to invoke hook_mail() on. + * - key: A key to identify the e-mail sent. + * - to: The e-mail address or addresses where the message will be sent to. + * - language: Language object to use to compose the e-mail. + * - params: Optional parameters to build the e-mail. + * - from: Sets From to this value, if given. + * These are the input arguments of the drupal_mail() function. + */ function print_mail_send($data) { drupal_mail($data['module'], $data['key'], $data['to'], $data['language'], $data['params'], $data['from']); } @@ -369,8 +224,8 @@ function print_mail_mail($key, &$message, $params) { 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'] . '

' . l($params['title'], $params['link']); + $sendlink_plain = theme('print_mail_sendlink_plain', $params); + $sendlink_html = theme('print_mail_sendlink_html', $params); // Send HTML-only version if MIME library not present if (!class_exists('Mail_mime')) { @@ -416,15 +271,17 @@ function print_mail_mail($key, &$message, $params) { /** * Access callback to check a combination of user_acess() and page access * - * @param $permission + * @param string $permission * permission required to view the page - * @return + * + * @return bool * TRUE if the user has permission to view the page, FALSE otherwise */ function _print_mail_access($permission) { + $link = print_mail_print_link(); $page_access = TRUE; $parts = explode('/', $_GET['q']); - if ($parts[0] == PRINTMAIL_PATH) { + if ($parts[0] == $link['path']) { if (count($parts) > 1) { unset($parts[0]); $path = implode('/', $parts); @@ -451,109 +308,29 @@ function _print_mail_access($permission) { 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_merge('print_mail_node_conf') - ->key(array('nid' => $nid)) - ->fields(array( - 'link' => $link, - 'comments' => $comments, - 'url_list' => $url_list, - )) - ->execute(); -} - -/** - * 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 + * @param string $path + * path to be used in the link. If not specified, the current URL is used. + * @param object $node + * node object, to be used in checking node access. If the path argument is + * not provided, the path used will be node/nid. + * @param string $location + * where in the page where the link is being inserted ('link', 'corner', + * 'block', 'help'). + * + * @return string * string with the HTML link to the printer-friendly page + * + * @ingroup print_api */ -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')); - } - else { - $query = NULL; - } - drupal_add_css(drupal_get_path('module', 'print') . '/css/printlinks.css'); - $format = theme('print_mail_format_link'); - return '' . l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) . ''; +function print_mail_insert_link($path = NULL, $node = NULL, $location = '') { + if (function_exists('print_ui_insert_link')) { + return print_ui_insert_link(print_mail_print_link(), array('path' => $path, 'node' => $node, 'location' => $location)); } else { return FALSE; @@ -563,86 +340,15 @@ function print_mail_insert_link($path = NULL, $node = NULL) { /** * Check if the link to send by email is allowed depending on the settings * - * @param $args + * @param array $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 + * view_mode, node, type, path + * + * @return bool + * FALSE if not allowed, TRUE otherwise */ function print_mail_link_allowed($args) { - $view_mode = isset($args['view_mode']) ? $args['view_mode'] : ''; - if ((($view_mode == 'teaser') && !variable_get('print_mail_link_teaser', PRINT_MAIL_LINK_TEASER_DEFAULT)) - || !in_array($view_mode, array('full', 'teaser', '')) || !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_query("SELECT comments FROM {print_mail_node_conf} WHERE nid = :nid", array(':nid' => $node->nid))->fetchField(); - } - $print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? $res[$node->nid] : 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; + return (user_access('access send by email')); } /** @@ -650,7 +356,7 @@ function print_mail_link_allowed($args) { */ function print_mail_mollom_form_list() { $forms['print_mail_form'] = array( - 'title' => t('Send page form'), + 'title' => t('Send by email form'), 'entity' => 'print_mail', ); return $forms; @@ -666,7 +372,7 @@ function print_mail_mollom_form_info($form_id) { 'elements' => array( 'fld_from_addr' => t('Sender email'), 'fld_from_name' => t('Sender name'), - 'txt_to_addrs' => t('Recipients'), + 'txt_to' => t('Recipients'), 'fld_subject' => t('Subject'), 'fld_title' => t('Page to be sent'), 'txt_message' => t('Your message'), @@ -729,12 +435,12 @@ function print_mail_action_submit($from, $from_name, $to, $subject, $message, $n $form_state['values'] = array( 'path' => 'node/' . $node->nid, - 'cid' => NULL, 'query' => NULL, + 'cid' => NULL, 'title' => $node->title, 'fld_from_addr' => $from, 'fld_from_name' => $from_name, - 'txt_to_addrs' => $to, + 'txt_to' => array('addrs' => $to), 'fld_subject' => $subject, 'txt_message' => $message, 'chk_teaser' => FALSE, diff --git a/sites/all/modules/contrib/admin/print/print_pdf/icons/pdf_icon.png b/sites/all/modules/contrib/admin/print/print_pdf/icons/pdf_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cfdb67668747a750b1d756f325e228ab1ce3e014 GIT binary patch literal 518 zcmV+h0{Q)kP)FJvGxaC)6`1)HEm2J~h)nHPk>g)j&1OQ&7-LM!m)o5u2>$n&Pm^Q+GEtk3kY(e$y>^|I6Twbb^u)%Ca5^|;pdyV&-;*!I5J_P*No z$bg8?go)3Hjn#;X*NKYIi;&%#n%R+Sotx#dv%%Z8|P z;P}hn_|4<_&f@sg=K0m;`q$|C+Ufe->-ymB`rz&R;_mz7?)&EO`{nTb=komM@%-rW z{Oa@k>+}8W^!)Ag{qOeu@Av)j_x*L_t&-(`C=q5`s_^g<;qh_EGG{Zm|m$ z#X`j{-v31e598?g->vU%5yW5U6RCkLKdy)ENCjbBd literal 0 HcmV?d00001 diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/INSTALL.txt b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/INSTALL.txt new file mode 100644 index 00000000..8e29d565 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/INSTALL.txt @@ -0,0 +1,18 @@ +dompdf support: + The dompdf tool produces results that are more faithful to the HTML + printer-friendly page. Good support of CSS 2.1 and partially CSS3. + + 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. diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.admin.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.admin.inc new file mode 100644 index 00000000..27d77578 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.admin.inc @@ -0,0 +1,38 @@ + 'fieldset', + '#title' => t('dompdf options'), + ); + + $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_dompdf_font_subsetting'] = array( + '#type' => 'checkbox', + '#title' => t('Enable font subsetting'), + '#default_value' => variable_get('print_pdf_dompdf_font_subsetting', PRINT_PDF_DOMPDF_FONT_SUBSETTING_DEFAULT), + '#description' => t('Only embed those font characters that are actually used. This can generates smaller PDF files but may significantly slow down processing.'), + ); + + return system_settings_form($form); +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.drush.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.drush.inc new file mode 100644 index 00000000..56678add --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.drush.inc @@ -0,0 +1,32 @@ + '_print_pdf_dompdf_drush_download_url', + ); +} + +/** + * Discover the correct URL of the package to download. + * + * @return string + * URL of the file to download, FALSE if not known + */ +function _print_pdf_dompdf_drush_download_url() { + return DOMPDF_DOWNLOAD_URI; +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.info b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.info new file mode 100644 index 00000000..ce8348c7 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.info @@ -0,0 +1,13 @@ +name = "dompdf library handler" +description = "PDF generation library using dompdf." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print_pdf +configure = admin/config/user-interface/print/pdf/dompdf + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.install b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.install new file mode 100644 index 00000000..4ba01437 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.install @@ -0,0 +1,16 @@ + 'dompdf', + 'url' => 'http://code.google.com/p/dompdf/downloads/list', + 'expand_css' => FALSE, + 'public_dirs' => array( + 'fonts', + ), + ); +} + +/** + * Implements hook_theme(). + */ +function print_pdf_dompdf_theme() { + return array( + 'print_pdf_dompdf_footer' => array( + 'variables' => array('html' => ''), + 'file' => 'print_pdf_dompdf.pages.inc', + ), + ); +} + +/** + * Implements hook_menu(). + */ +function print_pdf_dompdf_menu() { + $items = array(); + + $items['admin/config/user-interface/print/pdf/dompdf'] = array( + 'title' => 'dompdf', + 'description' => 'Configure the dompdf options.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('print_pdf_dompdf_settings'), + 'access arguments' => array('administer print'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'print_pdf_dompdf.admin.inc', + ); + + return $items; +} + +/** + * Implements hook_pdf_tool_version(). + */ +function print_pdf_dompdf_pdf_tool_version($pdf_tool) { + require_once(DRUPAL_ROOT . '/' . $pdf_tool); + + // Poor man's way to find dompdf version + if (!defined('DOMPDF_DIR')) { + return 'unknown'; + } + elseif (!defined('DOMPDF_CHROOT')) { + return '0.5.1'; + } + elseif (!defined('DOMPDF_FONT_CACHE')) { + return '0.5.2'; + } + elseif (!defined('DOMPDF_LOG_OUTPUT_FILE')) { + return '0.6.0 beta1'; + } + elseif (!defined('DOMPDF_ADMIN_USERNAME')) { + return '0.6.0 beta2'; + } + else { + return '0.6.0 beta3'; + } +} + +/** + * Implements hook_print_pdf_available_libs_alter(). + */ +function print_pdf_dompdf_print_pdf_available_libs_alter(&$pdf_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('dompdf', '!^dompdf_config.inc.php$!'); + + foreach ($tools as $tool) { + $pdf_tools['print_pdf_dompdf|' . $tool] = 'dompdf (' . dirname($tool) . ')'; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.pages.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.pages.inc new file mode 100644 index 00000000..0061a0ee --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_dompdf/print_pdf_dompdf.pages.inc @@ -0,0 +1,158 @@ +]*?)>!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('!!', '', $html); + + $url_array = parse_url($meta['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($paper_size), $page_orientation); + $dompdf->set_protocol($protocol); + +// dompdf can't handle footers cleanly, so disable the following +// $html = theme('print_pdf_dompdf_footer', array('html' => $html)); + + // If dompdf Unicode support is disabled, try to convert to ISO-8859-1 and then to HTML entities + if (!$unicode) { + // Convert the euro sign to an HTML entity + $html = str_replace('€', '€', $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('!]*?>|!i', '', $html); + + $dompdf->load_html($html); + + $dompdf->render(); + return $dompdf->output(); +} + +/** + * Format the dompdf footer contents + * + * @param array $vars + * An associative array containing: + * - $html: contents of the body of the HTML from the original node + * + * @return string + * customized HTML text + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_pdf_dompdf_footer($vars) { + preg_match('!!si', $vars['html'], $tpl_footer); + if (isset($tpl_footer[1])) { + $html = str_replace($tpl_footer[0], '', $vars['html']); + + $text = ''; + + return str_replace("", "" . $text, $html); + } else { + return $vars['html']; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.drush.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.drush.inc new file mode 100644 index 00000000..d89d61b1 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.drush.inc @@ -0,0 +1,32 @@ + '_print_pdf_mpdf_drush_download_url', + ); +} + +/** + * Discover the correct URL of the package to download. + * + * @return string + * URL of the file to download, FALSE if not known + */ +function _print_pdf_mpdf_drush_download_url() { + return MPDF_DOWNLOAD_URI; +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.info b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.info new file mode 100644 index 00000000..67065b00 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.info @@ -0,0 +1,12 @@ +name = "mPDF library handler" +description = "PDF generation library using mPDF." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print_pdf + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.module b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.module new file mode 100644 index 00000000..b1605874 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.module @@ -0,0 +1,52 @@ + 'mPDF', + 'url' => 'http://www.mpdf1.com/mpdf/download', + 'expand_css' => FALSE, + 'public_dirs' => array( + 'ttfontdata', + 'tmp', + ), + 'tool_dirs' => array( + 'graph_cache', + ), + ); +} + +/** + * Implements hook_pdf_tool_version(). + */ +function print_pdf_mpdf_pdf_tool_version($pdf_tool) { + require_once(DRUPAL_ROOT . '/' . $pdf_tool); + + if (defined('mPDF_VERSION')) { + return mPDF_VERSION; + } + else { + return 'unknown'; + } +} + +/** + * Implements hook_print_pdf_available_libs_alter(). + */ +function print_pdf_mpdf_print_pdf_available_libs_alter(&$pdf_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('mpdf', '!^mpdf.php$!'); + + foreach ($tools as $tool) { + $pdf_tools['print_pdf_mpdf|' . $tool] = 'mPDF (' . dirname($tool) . ')'; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.pages.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.pages.inc new file mode 100644 index 00000000..52c9e1c0 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_mpdf/print_pdf_mpdf.pages.inc @@ -0,0 +1,65 @@ +SetAuthor(strip_tags($meta['name'])); + $mpdf->SetCreator(variable_get('site_name', 'Drupal')); + // Pulled from the HTML meta data + // $mpdf->SetTitle(html_entity_decode($meta['title'], ENT_QUOTES, 'UTF-8')); + +// $keys = implode(' ', explode("\n", trim(strip_tags($print['taxonomy'])))); +// $mpdf->SetKeywords($keys); + + // Encrypt the file and grant permissions to the user to copy and print + // No password is required to open the document + // Owner has full rights using the password "MyPassword" + // $mpdf->SetProtection(array('copy', 'print'), '', 'MyPassword'); + // $mpdf->SetProtection(array('copy', 'print', 'print-highres'), '', ''); + drupal_alter('print_pdf_mpdf', $mpdf, $html, $meta); + + $mpdf->WriteHTML($html); + + // try to recover from any warning/error + ob_clean(); + + return $mpdf->Output('', 'S'); +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/INSTALL.txt b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/INSTALL.txt new file mode 100644 index 00000000..ac5d7766 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/INSTALL.txt @@ -0,0 +1,12 @@ +TCPDF support: + TCPDF's support for CSS is considerably worse than the other tools. + Unicode is supported (use of Unicode fonts result in HUGE files). Page + header and footer are supported. This module requires TCPDF >= 5.9.012. + + 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. diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.admin.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.admin.inc new file mode 100644 index 00000000..9c3270b0 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.admin.inc @@ -0,0 +1,63 @@ + 'fieldset', + '#title' => t('TCPDF options'), + ); + + $form['settings']['print_pdf_font_family'] = array( + '#type' => 'textfield', + '#title' => t('Font family'), + '#default_value' => variable_get('print_pdf_font_family', PRINT_PDF_TCPDF_FONT_FAMILY_DEFAULT), + '#size' => 60, + '#maxlength' => 250, + '#description' => t('Set the font family to be used. Examples: %examples.', array('%examples' => 'helvetica, times, courier, dejavusans, dejavuserif, freesans, freeserif, freemono')) . '
' . + 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_TCPDF_FONT_SIZE_DEFAULT), + '#size' => 2, + '#maxlength' => 3, + '#description' => t('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_TCPDF_FONT_SUBSETTING_DEFAULT), + '#description' => t('Only embed those font characters that are actually used. This can generates smaller PDF files but may significantly slow down processing.'), + ); + + $form['#validate'][] = '_print_pdf_tcpdf_settings_validate'; + + return system_settings_form($form); +} + +/** + * Form validation handler for print_pdf_tcpdf_settings(). + * + * @see print_pdf_tcpdf_settings() + * @ingroup forms + */ +function _print_pdf_tcpdf_settings_validate($form, &$form_state) { + if ($form_state['values']['print_pdf_font_size'] < 1) { + form_set_error('print_pdf_font_size', t("Font size must be at least 1.")); + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.class.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.class.inc similarity index 67% rename from sites/all/modules/contrib/admin/print/print_pdf/print_pdf.class.inc rename to sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.class.inc index 9eaa8cf9..b6a4c530 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.class.inc +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.class.inc @@ -12,8 +12,13 @@ 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 SetFooterData($arg = '') { + public function setFooterContent($arg = '') { $this->footer = $arg; } diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.drush.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.drush.inc new file mode 100644 index 00000000..de1d60ee --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.drush.inc @@ -0,0 +1,32 @@ + '_print_pdf_tcpdf_drush_download_url', + ); +} + +/** + * Discover the correct URL of the package to download. + * + * @return string + * URL of the file to download, FALSE if not known + */ +function _print_pdf_tcpdf_drush_download_url() { + return TCPDF_DOWNLOAD_URI; +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.info b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.info new file mode 100644 index 00000000..1984f9ce --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.info @@ -0,0 +1,14 @@ +name = "TCPDF library handler" +description = "PDF generation library using TCPDF." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print_pdf +files[] = print_pdf_tcpdf.class.inc +configure = admin/config/user-interface/print/pdf/tcpdf + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.install b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.install new file mode 100644 index 00000000..e09a7942 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.install @@ -0,0 +1,17 @@ + 'TCPDF', + 'min_version' => '5.9.001', + 'url' => 'http://sourceforge.net/projects/tcpdf/files/latest', + 'expand_css' => TRUE, + 'public_dirs' => array( + 'cache', + ), + 'tool_dirs' => array( + 'images', + ), + ); +} + +/** + * Implements hook_theme(). + */ +function print_pdf_tcpdf_theme() { + return array( + 'print_pdf_tcpdf_header' => array( + 'variables' => array('pdf' => NULL, 'html' => '', 'font' => array()), + 'file' => 'print_pdf_tcpdf.pages.inc', + ), + 'print_pdf_tcpdf_page' => array( + 'variables' => array('pdf' => NULL), + 'file' => 'print_pdf_tcpdf.pages.inc', + ), + 'print_pdf_tcpdf_content' => array( + 'variables' => array('pdf' => NULL, 'html' => '', 'font' => array()), + 'file' => 'print_pdf_tcpdf.pages.inc', + ), + 'print_pdf_tcpdf_footer' => array( + 'variables' => array('pdf' => NULL, 'html' => '', 'font' => array()), + 'file' => 'print_pdf_tcpdf.pages.inc', + ), + 'print_pdf_tcpdf_footer2' => array( + 'variables' => array('pdf' => NULL), + 'file' => 'print_pdf_tcpdf.pages.inc', + ), + ); +} + +/** + * Implements hook_menu(). + */ +function print_pdf_tcpdf_menu() { + $items = array(); + + $items['admin/config/user-interface/print/pdf/tcpdf'] = array( + 'title' => 'TCPDF', + 'description' => 'Configure the TCPDF options.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('print_pdf_tcpdf_settings'), + 'access arguments' => array('administer print'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'print_pdf_tcpdf.admin.inc', + ); + + return $items; +} + +/** + * Implements hook_pdf_tool_version(). + */ +function print_pdf_tcpdf_pdf_tool_version($pdf_tool) { + if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) { + // prevent TCPDF default configs + define('K_TCPDF_EXTERNAL_CONFIG', TRUE); + } + require_once(DRUPAL_ROOT . '/' . $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'; +} + +/** + * Implements hook_print_pdf_available_libs_alter(). + */ +function print_pdf_tcpdf_print_pdf_available_libs_alter(&$pdf_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('tcpdf', '!^tcpdf.php$!'); + + foreach ($tools as $tool) { + $pdf_tools['print_pdf_tcpdf|' . $tool] = 'TCPDF (' . dirname($tool) . ')'; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.pages.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.pages.inc new file mode 100644 index 00000000..029cd290 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_tcpdf/print_pdf_tcpdf.pages.inc @@ -0,0 +1,285 @@ +]*?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 = "!(]*?src\s*?=\s*?['\"]?{$base_url}[^>]*?)(?:%3F|\?)[^\s'\"]+([^>]*?>)!is"; + $html = preg_replace($pattern, '$1$2', $html); + + require_once(DRUPAL_ROOT . '/' . $pdf_tool[1]); + module_load_include('inc', 'print_pdf_tcpdf', 'print_pdf_tcpdf.class'); + + $font = Array( + check_plain(variable_get('print_pdf_font_family', PRINT_PDF_TCPDF_FONT_FAMILY_DEFAULT)), + '', + check_plain(variable_get('print_pdf_font_size', PRINT_PDF_TCPDF_FONT_SIZE_DEFAULT)), + ); + $orientation = drupal_strtoupper($page_orientation[0]); + + // create new PDF document + $pdf = new PrintTCPDF($orientation , 'mm', $paper_size, TRUE); + + // set document information + if (isset($meta['name'])) { + $pdf->SetAuthor(strip_tags($meta['name'])); + } + $pdf->SetCreator(variable_get('site_name', 'Drupal')); + $pdf->SetTitle(html_entity_decode($meta['title'], ENT_QUOTES, 'UTF-8')); + $pdf->setPDFVersion('1.6'); + $pdf->setFontSubsetting(variable_get('print_pdf_font_subsetting', PRINT_PDF_TCPDF_FONT_SUBSETTING_DEFAULT)); + $pdf->setTcpdfLink(false); + + if ($language->direction == LANGUAGE_RTL) { + $pdf->setRTL(TRUE); + } + + $pdf = theme('print_pdf_tcpdf_header', array('pdf' => $pdf, 'html' => $html, 'font' => $font)); + $pdf = theme('print_pdf_tcpdf_footer', array('pdf' => $pdf, 'html' => $html, 'font' => $font)); + $pdf = theme('print_pdf_tcpdf_page', array('pdf' => $pdf)); + + // Enable third-party module to alter the pdf object, via hook_print_pdf_tcpdf_alter() + drupal_alter('print_pdf_tcpdf', $pdf, $html, $meta); + + // add a page + $pdf->AddPage(); + + $pdf = theme('print_pdf_tcpdf_content', array('pdf' => $pdf, 'html' => $html, 'font' => $font)); + + // reset pointer to the last page + $pdf->lastPage(); + + // try to recover from any warning/error + ob_clean(); + + return $pdf = $pdf->Output('', 'S'); +} + +/** + * Format the TCPDF header + * + * @param array $vars + * An associative array containing: + * - $pdf: current TCPDF object + * - $html: contents of the body of the HTML from the original node + * - $font: array with the font definition (font name, styles and size) + * + * @return object + * modified PDF object + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_pdf_tcpdf_header($vars) { + global $base_url; + + $pdf = $vars['pdf']; + preg_match('!!si', $vars['html'], $tpl_logo); + preg_match('!(.*?)!si', $vars['html'], $tpl_title); + preg_match('!!si', $vars['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]; + + // Make logo relative again + $logo = preg_replace("!^$base_url(.*)!sm", dirname($_SERVER['SCRIPT_FILENAME']) . '$1', $logo); + + if (!empty($logo)) { + $size = getimagesize($logo); + $ratio = $size ? ($size[0] / $size[1]) : 0; + } + } + + // set header font + $pdf->setHeaderFont($vars['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 array $vars + * An associative array containing: + * - $pdf: current TCPDF object + * + * @return object + * modified PDF object + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_pdf_tcpdf_page($vars) { + $pdf = $vars['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 array $vars + * An associative array containing: + * - $pdf: current TCPDF object + * - $html: contents of the body of the HTML from the original node + * - $font: array with the font definition (font name, styles and size) + * + * @return object + * modified PDF object + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_pdf_tcpdf_content($vars) { + $pdf = $vars['pdf']; + // set content font + $pdf->setFont($vars['font'][0], $vars['font'][1], $vars['font'][2]); + + // Remove the logo, published, breadcrumb and footer from the main content + preg_match('!(.*)!sim', $vars['html'], $matches); + $pattern = '!(?:|)!si'; + $matches[1] = preg_replace($pattern, '', $matches[1]); + + // Make CCK fields look better + $matches[1] = preg_replace('!(
.*?
)\s*!sm', '$1', $matches[1]); + $matches[1] = preg_replace('!(.*?)!si', $vars['html'], $tpl_footer); + + if (isset($tpl_footer[1])) { + $footer = trim(preg_replace('!]*?>!i', '', $tpl_footer[1])); + + // set footer font + $vars['font'][2] *= 0.8; + $pdf->setFooterFont($vars['font']); + // set footer margin + $pdf->SetFooterMargin(10); + // set footer data + $pdf->setFooterContent($footer); + } + + return $pdf; +} + +/** + * Format the TCPDF footer layout + * + * @param array $vars + * An associative array containing: + * - $pdf: current TCPDF object + * + * @return object + * modified PDF object + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_pdf_tcpdf_footer2($vars) { + $pdf = $vars['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; +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/INSTALL.txt b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/INSTALL.txt new file mode 100644 index 00000000..51c066b6 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/INSTALL.txt @@ -0,0 +1,17 @@ +wkhtmltopdf support: + wkhtmltopdf is a webkit-based tool that actually is a browser in order to + generate the PDF. Resource hungry: expect to need some 30Mb+ of RAM and + some seconds of CPU power. The static binaries may need additional + libraries in your site, which may present problems in shared hosting + environments. The best, if you can run it. + + 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. diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.admin.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.admin.inc new file mode 100644 index 00000000..7d60ffbe --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.admin.inc @@ -0,0 +1,47 @@ + 'fieldset', + '#title' => t('wkhtmltopdf options'), + ); + + $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_patterns'] = array( + '#type' => 'fieldset', + '#title' => t('Replacement patterns'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['settings']['print_pdf_filename_patterns']['descriptions'] = array( + '#theme' => 'token_tree', + '#token_types' => array('node'), + ); + } + + return system_settings_form($form); +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.drush.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.drush.inc new file mode 100644 index 00000000..dca3d299 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.drush.inc @@ -0,0 +1,53 @@ + '_print_pdf_wkhtmltopdf_drush_download_url', + ); +} + +/** + * Discover the correct URL of the package to download. + * + * @return string + * URL of the file to download, FALSE if not known + */ +function _print_pdf_wkhtmltopdf_drush_download_url() { + $ret = FALSE; + + 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; + } + + return $ret; +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.info b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.info new file mode 100644 index 00000000..d6603b75 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.info @@ -0,0 +1,13 @@ +name = "wkhtmltopdf library handler" +description = "PDF generation library using wkhtmltopdf." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print_pdf +configure = admin/config/user-interface/print/pdf/wkhtmltopdf + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.install b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.install new file mode 100644 index 00000000..6a4b7873 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.install @@ -0,0 +1,15 @@ + 'wkhtmltopdf', + 'min_version' => '0.9.6', + 'url' => 'http://code.google.com/p/wkhtmltopdf/downloads/list', + 'expand_css' => FALSE, + ); +} + +/** + * Implements hook_menu(). + */ +function print_pdf_wkhtmltopdf_menu() { + $items = array(); + + $items['admin/config/user-interface/print/pdf/wkhtmltopdf'] = array( + 'title' => 'wkhtmltopdf', + 'description' => 'Configure the wkhtmltopdf options.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('print_pdf_wkhtmltopdf_settings'), + 'access arguments' => array('administer print'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'print_pdf_wkhtmltopdf.admin.inc', + ); + + return $items; +} + +/** + * Implements hook_requirements(). + */ +function print_pdf_wkhtmltopdf_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)) { + $tool = explode('|', $print_pdf_pdf_tool); + + if (is_file($tool[1]) && is_readable($tool[1])) { + if (drupal_substr(basename($tool[1], '.exe'), 0, 11) == 'wkhtmltopdf') { + if (function_exists('is_executable') && !is_executable($tool[1])) { + $requirements['print_pdf_wkhtmltopdf'] = 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' => $tool[1])), + 'severity' => REQUIREMENT_ERROR, + ); + } + } + } + } + break; + } + return $requirements; +} + +/** + * Implements hook_pdf_tool_version(). + */ +function print_pdf_wkhtmltopdf_pdf_tool_version($pdf_tool) { + $descriptor = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')); + + $cmd = '"' . realpath($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_print_pdf_available_libs_alter(). + */ +function print_pdf_wkhtmltopdf_print_pdf_available_libs_alter(&$pdf_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('wkhtmltopdf', '!^wkhtmltopdf!'); + + foreach ($tools as $tool) { + $version = print_pdf_wkhtmltopdf_pdf_tool_version($tool); + + $pdf_tools['print_pdf_wkhtmltopdf|' . $tool] = 'wkhtmltopdf ' . $version . ' (' . $tool . ')'; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.pages.inc b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.pages.inc new file mode 100644 index 00000000..3e86f976 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/lib_handlers/print_pdf_wkhtmltopdf/print_pdf_wkhtmltopdf.pages.inc @@ -0,0 +1,85 @@ + $meta['node']), array('clear' => TRUE)); + } + + $version = print_pdf_wkhtmltopdf_pdf_tool_version($pdf_tool[1]); + + // 0.10.0 beta2 identifies itself as 0.9.9 + if (version_compare($version, '0.9.9', '>=')) { + $wkhtmltopdf_options = '--disable-local-file-access ' . $wkhtmltopdf_options; + } + elseif (version_compare($version, '0.9.6', '>=')) { + $wkhtmltopdf_options = '--disallow-local-file-access ' . $wkhtmltopdf_options; + } + else { + drupal_goto($meta['url']); + exit; + } + + // use basic http authentication to fetch included CSS, etc + if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { + $wkhtmltopdf_options .= ' --username ' . check_plain($_SERVER['PHP_AUTH_USER']) . ' --password ' . check_plain($_SERVER['PHP_AUTH_PW']); + } + + $descriptor = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'a')); + $cmd = '"' . realpath($pdf_tool[1]) . "\" --page-size $paper_size --orientation $page_orientation --dpi $dpi $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)) { + return $pdf; + } + else { + drupal_set_message(t('Unable to generate PDF file.'), 'error'); + drupal_goto($meta['url']); + return NULL; + } +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.admin.inc b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.admin.inc index f10b5c74..ef8e2c21 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.admin.inc +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.admin.inc @@ -11,17 +11,20 @@ */ /** - * Menu callback for the PDF version module settings form. + * Form constructor for the PDF version module settings form. * * @ingroup forms - * @see _print_pdf_tools() */ function print_pdf_settings() { - $pdf_tools = _print_pdf_tools(); - $current_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); - $pdf_tool_default = (in_array($current_pdf_tool, $pdf_tools)) ? $current_pdf_tool : PRINT_PDF_PDF_TOOL_DEFAULT; + $pdf_tools = array(); + drupal_alter('print_pdf_available_libs', $pdf_tools); + + if (!empty($pdf_tools)) { + $link = print_pdf_print_link(); + + $current_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); + $pdf_tool_default = array_key_exists($current_pdf_tool, $pdf_tools) ? $current_pdf_tool : PRINT_PDF_PDF_TOOL_DEFAULT; - if ($pdf_tools != -1) { $form['settings'] = array( '#type' => 'fieldset', '#title' => t('PDF options'), @@ -35,113 +38,6 @@ function print_pdf_settings() { '#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', drupal_json_decode(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' => '')), - ); - - if (module_exists('php')) { - $access = user_access('use PHP for settings'); - - 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 TRUE (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' => '')); - } - } - - $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.') . '
' . - 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' => '')), - ); - - if (module_exists('php')) { - 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 TRUE (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' => '')); - } - } - - $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'), @@ -153,21 +49,7 @@ function print_pdf_settings() { $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', - ), + '#options' => _print_pdf_paper_sizes(), '#default_value' => variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT), '#description' => t('Choose the paper size of the generated PDF.'), ); @@ -179,6 +61,35 @@ function print_pdf_settings() { '#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_cache_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Enable caching of generated PDFs'), + '#default_value' => variable_get('print_pdf_cache_enabled', PRINT_PDF_CACHE_ENABLED_DEFAULT), + ); + + $form['settings']['print_pdf_cache_lifetime'] = array( + '#type' => 'select', + '#title' => t('Cache Lifetime'), + '#options' => array( + '0' => 'None', + '10800' => '3 hours', + '21600' => '6 hours', + '43200' => '12 hours', + '64800' => '18 hours', + '86400' => '24 hours', + '129600' => '36 hours', + '172800' => '2 days', + '259200' => '3 days', + '345600' => '4 days', + '432000' => '5 days', + '518400' => '6 days', + '604800' => '7 days', + ), + '#default_value' => variable_get('print_pdf_cache_lifetime', PRINT_PDF_CACHE_LIFETIME_DEFAULT), + '#description' => t('The lifetime of cached PDFs. A cached PDF is only removed when a node is updated, deleted, or cron is run and the last access is older than this value.'), + ); + $form['settings']['print_pdf_images_via_file'] = array( '#type' => 'checkbox', '#title' => t('Access images via local file access'), @@ -191,50 +102,13 @@ function print_pdf_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')) . '
' . - 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).'), - ); - $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'] = 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."), + ); if (module_exists('token')) { $form['settings']['print_pdf_filename_patterns'] = array( '#type' => 'fieldset', @@ -255,12 +129,31 @@ function print_pdf_settings() { '#description' => t('Enabling this option will display a list of printer-friendly destination URLs at the bottom of the page.'), ); + $form['settings']['link_text'] = array( + '#type' => 'fieldset', + '#title' => t('Custom link text'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['settings']['link_text']['print_pdf_link_text_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Enable custom link text'), + '#default_value' => variable_get('print_pdf_link_text_enabled', PRINT_TYPE_LINK_TEXT_ENABLED_DEFAULT), + ); + $form['settings']['link_text']['print_pdf_link_text'] = array( + '#type' => 'textfield', + '#default_value' => variable_get('print_pdf_link_text', $link['text']), + '#description' => t('Text used in the link to the PDF version.'), + ); + $form['#validate'][] = '_print_pdf_settings_validate'; } else { + variable_set('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); + $form['settings'] = array( '#type' => 'markup', - '#markup' => '

' . t("No PDF generation tool found! Please dowload a supported PHP PDF generation tool. Check this module's INSTALL.txt for more details.") . '

', + '#markup' => '

' . t("No PDF generation tool found! Please download a supported PHP PDF generation tool. Check this module's INSTALL.txt for more details.") . '

', ); } @@ -268,78 +161,13 @@ function print_pdf_settings() { } /** - * Validate print_pdf_settings form. + * Form validation handler for print_pdf_settings(). + * + * @see print_pdf_settings() + * @ingroup forms */ 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() { - $pattern = '!^(?:dompdf_config.inc.php|tcpdf.php|wkhtmltopdf.*)$!'; - $tools = array_keys(file_scan_directory(drupal_get_path('module', 'print'), $pattern)); - $tools = array_merge($tools, array_keys(file_scan_directory(PRINT_PDF_LIB_PATH, $pattern))); - 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 { - return array_combine($tools, $tools); - } -} - -/** - * 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.'), - ); - $form['print_pdf_text']['reset'] = array( - '#type' => 'submit', - '#value' => t('Reset to defaults'), - '#submit' => array('print_pdf_strings_settings_delete'), - ); - - return system_settings_form($form); -} - -/** - * Reset button callback for text strings settings form - * - * @ingroup forms - */ -function print_pdf_strings_settings_delete() { - variable_del('print_pdf_link_text'); } diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.api.php b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.api.php new file mode 100644 index 00000000..f6c34bde --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.api.php @@ -0,0 +1,144 @@ + 'foopdf', + 'min_version' => '1.0', + 'url' => 'http://www.pdf.tool/download', + 'expand_css' => FALSE, + 'public_dirs' => array( + 'fonts', + 'cache', + 'tmp', + ), + 'tool_dirs' => array( + 'xyz', + ), + ); +} + +/** + * Find out the version of the PDF library + * + * @param string $pdf_tool + * Filename of the tool to be analysed. + * + * @return string + * version number of the library + */ +function hook_pdf_tool_version() { + require_once(DRUPAL_ROOT . '/' . $pdf_tool); + + return '1.0'; +} + +/** + * Generate a PDF version of the provided HTML. + * + * @param string $html + * HTML content of the PDF + * @param array $meta + * Meta information to be used in the PDF + * - url: original URL + * - name: author's name + * - title: Page title + * - node: node object + * @param string $paper_size + * (optional) Paper size of the generated PDF + * @param string $page_orientation + * (optional) Page orientation of the generated PDF + * + * @return + * generated PDF page, or NULL in case of error + * + * @see print_pdf_controller_html() + * @ingroup print_hooks + */ +function hook_print_pdf_generate($html, $meta, $paper_size = NULL, $page_orientation = NULL) { + $pdf = new PDF(); + $pdf->writeHTML($html); + + return $pdf->Output(); +} + +/** + * Alters the list of available PDF libraries. + * + * During the configuration of the PDF library to be used, the module needs + * to discover and display the available libraries. This function should use + * the internal _print_scan_libs() function which will scan both the module + * and the libraries directory in search of the unique file pattern that can + * be used to identify the library location. + * + * @param array $pdf_tools + * An associative array using as key the format 'module|path', and as value + * a string describing the discovered library, where: + * - module: the machine name of the module that handles this library. + * - path: the path where the library is installed, relative to DRUPAL_ROOT. + * If the recommended path is used, it begins with sites/all/libraries. + * As a recommendation, the value should contain in parantheses the path + * where the library was found, to allow the user to distinguish between + * multiple install paths of the same library version. + * + * @ingroup print_hooks + */ +function hook_print_pdf_available_libs_alter(&$pdf_tools) { + module_load_include('inc', 'print', 'includes/print'); + $tools = _print_scan_libs('foo', '!^foo.php$!'); + + foreach ($tools as $tool) { + $pdf_tools['print_pdf_foo|' . $tool] = 'foo (' . dirname($tool) . ')'; + } +} + +/** + * Alters the PDF filename. + * + * Changes the value of the PDF filename variable, just before it is used to + * create the file. When altering the variable, do not suffix it with the + * '.pdf' extension, as the module will do that automatically. + * + * @param string $pdf_filename + * current value of the pdf_filename variable, after processing tokens and + * any transliteration steps. + * @param string $path + * original alias/system path of the page being converted to PDF. + * + * @ingroup print_hooks + */ +function hook_print_pdf_filename_alter(&$pdf_filename, &$path) { + $pdf_filename = 'foo'; +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.drush.inc b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.drush.inc index 4ebe9968..c46ea22a 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.drush.inc +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.drush.inc @@ -5,32 +5,19 @@ * 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', 'http://dompdf.googlecode.com/files/dompdf_0-6-0_beta3.tar.gz'); - -// wkhtmltopdf is a binary, requiring a different download for each platform -define('WKHTMLTOPDF_AMD64_DOWNLOAD_URI', 'http://wkhtmltopdf.googlecode.com/files/wkhtmltopdf-0.11.0_rc1-static-amd64.tar.bz2'); -define('WKHTMLTOPDF_I386_DOWNLOAD_URI', 'http://wkhtmltopdf.googlecode.com/files/wkhtmltopdf-0.11.0_rc1-static-i386.tar.bz2'); -define('WKHTMLTOPDF_WIN_DOWNLOAD_URI', 'http://wkhtmltopdf.googlecode.com/files/wkhtmltox-0.11.0_rc1-installer.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(); + $pdf_libs = array(); + drush_command_invoke_all_ref('drush_pdf_libs_alter', $pdf_libs); + $items['print-pdf-download'] = array( - 'description' => 'Download a PDF library.', + 'description' => 'Download and extract a PDF library.', 'arguments' => array( - 'library' => dt('The PDF library to download. Either tcpdf, dompdf or wkhtmltopdf.'), + 'library' => dt('The PDF library to download. Available choices: !libs.', array('!libs' => implode(', ', array_keys($pdf_libs)))), ), 'options' => array( 'path' => dt('A path to the download folder. If omitted Drush will use the default location (@path).', array('@path' => 'sites/all/libraries')), @@ -42,177 +29,37 @@ function print_pdf_drush_command() { return $items; } +/** + * Implements of drush_hook_COMMAND_validate(). + */ +function drush_print_pdf_download_validate($library = NULL) { + if (is_null($library)) { + $pdf_libs = array(); + drush_command_invoke_all_ref('drush_pdf_libs_alter', $pdf_libs); + + drush_set_error('DRUSH_PDFDL_MISSING_ARG', dt("Usage: drush !cmd \nWhere is one of the following: !libs\n\nTry 'drush !cmd --help' for more information.", array('!cmd' => 'print-pdf-download', '!libs' => implode(', ', array_keys($pdf_libs))))); + } +} + /** * Download and extract PDF archive. + * + * @param string $library + * library to download */ function drush_print_pdf_download($library) { - if (isset($library)) { - $download_url = _drush_print_pdf_download_url($library); + $pdf_libs = array(); + drush_command_invoke_all_ref('drush_pdf_libs_alter', $pdf_libs); + + if (isset($library) && isset($pdf_libs[drupal_strtolower($library)])) { + $func = $pdf_libs[drupal_strtolower($library)]['callback']; + + $download_url = $func(); 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); + _print_drush_download_lib($library, $download_url); } } else { - drush_log(dt('Please specify a PDF library. Currently supported libraries are dompdf, tcpdf and wkhtmltopdf.'), 'error'); + drush_log(dt('Please specify a PDF library. Available choices: !libs.', array('!libs' => implode(', ', array_keys($pdf_libs)))), '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; - } - } - 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; -} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.info b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.info index d6725138..9a6fd674 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.info +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.info @@ -1,18 +1,13 @@ name = "PDF version" -description = "Adds the capability to export pages as PDF." -core=7.x +description = "Adds the capability to export pages as PDF. Requires a PDF library and the respective handler module." +core = 7.x package = "Printer, email and PDF versions" dependencies[] = print -files[] = print_pdf.module -files[] = print_pdf.admin.inc -files[] = print_pdf.pages.inc -files[] = print_pdf.install -files[] = print_pdf.views.inc configure = admin/config/user-interface/print/pdf -; Information added by drupal.org packaging script on 2012-09-04 -version = "7.x-1.2" +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" core = "7.x" project = "print" -datestamp = "1346768900" +datestamp = "1396426766" diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.install b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.install index c36eac51..3b138b58 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.install +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.install @@ -27,30 +27,28 @@ function print_pdf_enable() { * Implements hook_uninstall(). */ function print_pdf_uninstall() { - variable_del('print_pdf_settings'); - variable_del('print_pdf_show_link'); + variable_del('print_pdf_autoconfig'); + variable_del('print_pdf_cache_enabled'); + variable_del('print_pdf_cache_lifetime'); + variable_del('print_pdf_content_disposition'); + variable_del('print_pdf_display_sys_urllist'); + variable_del('print_pdf_filename'); + variable_del('print_pdf_images_via_file'); + variable_del('print_pdf_link_text'); + variable_del('print_pdf_link_text_enabled'); + variable_del('print_pdf_page_orientation'); + variable_del('print_pdf_paper_size'); + variable_del('print_pdf_pdf_tool'); + + variable_del('print_pdf_book_link'); + variable_del('print_pdf_link_class'); 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'); + variable_del('print_pdf_show_link'); + variable_del('print_pdf_sys_link_pages'); + variable_del('print_pdf_sys_link_visibility'); + $settings = db_query("SELECT name FROM {variable} WHERE name LIKE 'print\_pdf\_display\_%'"); foreach ($settings as $variable) { variable_del($variable->name); @@ -94,6 +92,17 @@ function print_pdf_schema() { 'size' => 'tiny', 'description' => 'Show Printer-friendly URLs list', ), + 'size' => array( + 'type' => 'varchar', + 'length' => 9, + 'description' => 'Paper size', + ), + 'orientation' => array( + 'type' => 'varchar', + 'length' => 9, + 'description' => 'Page orientation', + ), + ), 'primary key' => array('nid'), ); @@ -103,7 +112,7 @@ function print_pdf_schema() { 'fields' => array( 'path' => array( 'type' => 'varchar', - 'length' => 128, + 'length' => 255, 'not null' => TRUE, 'description' => 'Page path', ), @@ -146,12 +155,87 @@ function print_pdf_update_7000(&$sandbox) { } } +/** + * Delete old variables + */ +function print_pdf_update_7200(&$sandbox) { + variable_del('print_pdf_settings'); + + variable_del('print_pdf_node_link_pages'); + variable_del('print_pdf_node_link_visibility'); +} + +/** + * Update pdf_tool variable to new module|path format + */ +function print_pdf_update_7201(&$sandbox) { + $tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT)); + + if (count($tool) == 1) { + // Not an array yet, update variable to new format + if (preg_match('!dompdf_config.inc.php$!', $tool[0])) { + $tool[0] = 'print_pdf_dompdf|' . $tool[0]; + } + elseif (preg_match('!tcpdf.php$!', $tool[0])) { + $tool[0] = 'print_pdf_tcpdf|' . $tool[0]; + } + elseif (preg_match('!wkhtmltopdf!', $tool[0])) { + $tool[0] = 'print_pdf_wkhtmltopdf|' . $tool[0]; + } + else { + $tool[0] = PRINT_PDF_PDF_TOOL_DEFAULT; + } + + variable_set('print_pdf_pdf_tool', $tool[0]); + } +} + /** * Enable block and help area links */ -function print_pdf_update_7101(&$sandbox) { +function print_pdf_update_7202(&$sandbox) { $link_pos = variable_get('print_pdf_link_pos', drupal_json_decode('{ "link": "link", "block": "block", "help": "help" }')); $link_pos['block'] = 'block'; $link_pos['help'] = 'help'; variable_set('print_pdf_link_pos', $link_pos); } + +/** + * Add Size and Orientation fields for per content type Size and Orientation + */ +function print_pdf_update_7203(&$sandbox) { + $spec = array( + 'type' => 'varchar', + 'length' => 9, + 'description' => 'Paper size', + ); + db_add_field('print_pdf_node_conf', 'size', $spec); + $spec = array( + 'type' => 'varchar', + 'length' => 9, + 'description' => 'Page orientation', + ); + db_add_field('print_pdf_node_conf', 'orientation', $spec); +} + +/** + * Enable the PDF generation sub-module being used + */ +function print_pdf_update_7204(&$sandbox) { + // Since update_7201 already has stored the correct module in the array, use that + $tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT)); + + if (count($tool) == 2) { + module_enable(array($tool[0]), FALSE); + } +} + +/** + * Increase size of the path field in the print_pdf_page_counter table + */ +function print_pdf_update_7205(&$sandbox) { + db_drop_primary_key('print_pdf_page_counter'); + db_change_field('print_pdf_page_counter', 'path', 'path', + array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'description' => 'Page path'), + array('primary key' => array('path'))); +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.module b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.module index eaf37dbe..0cdff678 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.module +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.module @@ -7,37 +7,37 @@ * @ingroup print */ -define('PRINTPDF_PATH', 'printpdf'); - -// Defined in print.module -// define('PRINT_PDF_FORMAT', 'pdf'); - -define('PRINT_PDF_LIB_PATH', 'sites/all/libraries'); - -define('PRINT_PDF_LINK_POS_DEFAULT', '{ "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] - [node:title] - [node:changed:custom:Y-m-d]'); -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'); +define('PRINT_PDF_CACHE_ENABLED_DEFAULT', 0); +define('PRINT_PDF_CACHE_LIFETIME_DEFAULT', 86400); // 1 day + +/** + * Implements hook_print_link(). + */ +function print_pdf_print_link() { + return array( + 'format' => 'pdf', + 'text' => t('PDF version'), + 'description' => t('Display a PDF version of this page.'), + 'path' => 'printpdf', + 'class' => 'print-pdf', + 'icon' => 'pdf_icon.png', + 'module' => 'print_pdf', + ); +} + +/** + * Implements hook_print_new_window_alter(). + */ +function print_pdf_print_new_window_alter(&$new_window, $format) { + $new_window = (variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT) == 1); +} /** * Implements hook_permission(). @@ -51,81 +51,65 @@ function print_pdf_permission() { ); } -/** - * Implements hook_theme(). - */ -function print_pdf_theme() { - return array( - 'print_pdf_format_link' => array( - 'variables' => array(), - ), - 'print_pdf_dompdf_footer' => array( - 'variables' => array('html' => ''), - 'file' => 'print_pdf.pages.inc', - ), - 'print_pdf_tcpdf_header' => array( - 'variables' => array('pdf' => NULL, 'html' => '', 'font' => array()), - 'file' => 'print_pdf.pages.inc', - ), - 'print_pdf_tcpdf_page' => array( - 'variables' => array('pdf' => NULL), - 'file' => 'print_pdf.pages.inc', - ), - 'print_pdf_tcpdf_content' => array( - 'variables' => array('pdf' => NULL, 'html' => '', 'font' => array()), - 'file' => 'print_pdf.pages.inc', - ), - 'print_pdf_tcpdf_footer' => array( - 'variables' => array('pdf' => NULL, 'html' => '', 'font' => array()), - 'file' => 'print_pdf.pages.inc', - ), - 'print_pdf_tcpdf_footer2' => array( - 'variables' => array('pdf' => NULL), - 'file' => 'print_pdf.pages.inc', - ), - ); -} - /** * Implements 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; - } + $tool = explode('|', $print_pdf_pdf_tool); + $function = $tool[0] . '_pdf_tool_info'; + if (function_exists($function)) { + $info = $function(); } - if (!empty($pdf_dirs)) { - foreach ($pdf_dirs as $pdf_dir) { - $directory = 'public://' . $pdf_dir; - file_prepare_directory($directory, FILE_CREATE_DIRECTORY); + if (isset($info['public_dirs'])) { + foreach ($info['public_dirs'] as $dir) { + $directory = 'public://print_pdf/' . $tool[0] . '/' . $dir; + $wrapper = file_stream_wrapper_get_instance_by_uri($directory); + $real_directory_path = $wrapper->getDirectoryPath() . "/" . file_uri_target($directory); + $result = file_prepare_directory($real_directory_path, FILE_CREATE_DIRECTORY); + if (!$result) { + watchdog('print_pdf', 'Failed to create directory "%dir" for %tool.', array('%dir' => $directory, '%tool' => $tool[0]), WATCHDOG_CRITICAL); + } } } } + if (variable_get('print_pdf_cache_enabled', PRINT_PDF_CACHE_ENABLED_DEFAULT)) { + $directory = print_pdf_cache_dir(); + $wrapper = file_stream_wrapper_get_instance_by_uri($directory); + $real_directory_path = $wrapper->getDirectoryPath() . "/" . file_uri_target($directory); + $result = file_prepare_directory($real_directory_path, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY); + if (!$result) { + watchdog('print_pdf', 'Failed to create directory "%dir" for print_pdf cache.', array('%dir' => $directory), WATCHDOG_CRITICAL); + } + } +} + +/** + * Implements hook_flush_caches(). + */ +function print_pdf_flush_caches() { + print_pdf_cache_delete(); + + return array(); } /** * Implements hook_menu(). */ function print_pdf_menu() { + $link = print_pdf_print_link(); $items = array(); - $items[PRINTPDF_PATH] = array( + $items[$link['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( + $items[$link['path'] . '/' . $link['path']] = array( 'access callback' => FALSE, ); $items['admin/config/user-interface/print/pdf'] = array( @@ -140,51 +124,57 @@ function print_pdf_menu() { ); $items['admin/config/user-interface/print/pdf/options'] = array( 'title' => 'Options', - 'weight' => 1, + 'weight' => -1, 'type' => MENU_DEFAULT_LOCAL_TASK, ); - $items['admin/config/user-interface/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; } +/** + * Implements hook_variable_info(). + */ +function print_pdf_variable_info($options) { + $link = print_pdf_print_link(); + + $variable['print_pdf_link_text'] = array( + 'title' => t('PDF version'), + 'description' => t('Text used in the link to the PDF version.'), + 'type' => 'string', + 'default' => t($link['text']), + ); + + return $variable; +} + /** * Implements hook_block_info(). */ function print_pdf_block_info() { - $block['print_pdf-top']['info'] = t('Most PDFd'); - $block['print_pdf-top']['cache'] = DRUPAL_CACHE_GLOBAL; - return $block; + $block['print_pdf-top']['info'] = t('Most PDFd'); + $block['print_pdf-top']['cache'] = DRUPAL_CACHE_GLOBAL; + return $block; } /** * Implements hook_block_view(). */ function print_pdf_block_view($delta = 0) { - switch ($delta) { - case 'print_pdf-top': - $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) - ->fetchAll(); - if (count($result)) { - $block['content'] = '
    '; - foreach ($result as $obj) { - $block['content'] .= '
  • ' . l(_print_get_title($obj->path), $obj->path) . '
  • '; - } - $block['content'] .= '
'; + switch ($delta) { + case 'print_pdf-top': + $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) + ->fetchAll(); + if (count($result)) { + $items = array(); + foreach ($result as $obj) { + $items[] = l(_print_get_title($obj->path), $obj->path); } - break; + $block['content'] = theme('item_list', array('items' => $items, 'type' => 'ul')); } - return $block; + break; + } + return $block; } /** @@ -206,82 +196,67 @@ function print_pdf_requirements($phase) { ); } else { - if (!is_file($print_pdf_pdf_tool) || !is_readable($print_pdf_pdf_tool)) { + // Tool is defined, get some data from it's handler module + $tool = explode('|', $print_pdf_pdf_tool); + $function = $tool[0] . '_pdf_tool_info'; + if (function_exists($function)) { + $info = $function(); + } + + // Is the file there? + if (!is_file($tool[1]) || !is_readable($tool[1])) { $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)), + 'description' => $t('The currently selected PDF generation library (%file) is no longer accessible.', array('%file' => $tool[1])), 'severity' => REQUIREMENT_ERROR, ); } - elseif (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') { - if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) { - $directory = 'public://' . 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(); + else { + // Get the version number + $function = $tool[0] . '_pdf_tool_version'; + if (function_exists($function)) { + $version = $function($tool[1]); - 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 = 'public://' . 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( + if (isset($info['min_version']) && version_compare($version, $info['min_version'], '<')) { + $requirements['print_pdf_tool_version'] = 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/'))), + 'value' => $t('Unsupported %lib version', array('%lib' => $info['name'])), + 'description' => $t('The currently selected version of %lib (@version) is not supported. Please update to a !url.', + array('%lib' => $info['name'], '@version' => $version, '!url' => l($t('newer version'), $info['url']))), 'severity' => REQUIREMENT_ERROR, ); } else { - $requirements['print_pdf_tool'] = array( + $requirements['print_pdf_tool_version'] = array( 'title' => $t('Printer, email and PDF versions - PDF generation library'), - 'value' => $t('wkhtmltopdf') . ' ' . $version, + 'value' => $info['name'] . ' ' . $version, + ); + } + } + } + + // If auto-config is on, check for write access to the appropriate dirs + if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) { + $directories = array(); + if (isset($info['public_dirs'])) { + foreach ($info['public_dirs'] as $dir) { + $directories[] = 'public://print_pdf/' . $tool[0] . '/' . $dir; + } + } + if (isset($info['tool_dirs'])) { + foreach ($info['tool_dirs'] as $dir) { + $directories[] = dirname($tool[1]) . '/' . $dir; + } + } + + foreach ($directories as $dir) { + if (!is_dir($dir) || !is_writable($dir)) { + $requirements['print_pdf_tool_' . $dir] = array( + 'title' => $t('%lib directory', array('%lib' => $info['name'])), + 'value' => $t('Non-writable permissions'), + 'description' => $t('You must change the %libdir permissions to be writable, as %lib requires write-access to that directory.', array('%lib' => $info['name'], '%libdir' => $dir)), + 'severity' => REQUIREMENT_ERROR, ); } } @@ -292,87 +267,6 @@ function print_pdf_requirements($phase) { return $requirements; } -/** - * Implements hook_node_view(). - */ -function print_pdf_node_view($node, $view_mode) { - $print_pdf_link_pos = variable_get('print_pdf_link_pos', drupal_json_decode(PRINT_PDF_LINK_POS_DEFAULT)); - $print_pdf_link_use_alias = variable_get('print_pdf_link_use_alias', PRINT_PDF_LINK_USE_ALIAS_DEFAULT); - - foreach (array('node', 'comment') as $type) { - $allowed_type = print_pdf_link_allowed(array('type' => $type, 'node' => $node, 'view_mode' => $view_mode)); - 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'], - ); - } - elseif ($allowed_type === PRINT_ALLOW_NORMAL_LINK) { - $path = (($print_pdf_link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/' . $node->nid))) ? $alias : $node->nid; - - $links['print_pdf'] = array( - 'href' => PRINTPDF_PATH . '/' . $path, - 'title' => $format['text'], - 'attributes' => $format['attributes'], - 'html' => $format['html'], - 'query' => print_query_string_encode($_GET, array('q')), - ); - } - - $link_content = array( - '#theme' => 'links', - '#links' => $links, - '#attributes' => array('class' => array('links', 'inline')), - ); - - if ($type == 'node') { - - $node->content['links']['print_pdf'] = $link_content; - } - elseif (($type == 'comment') && isset($node->content['comments']['comments'])) { - foreach ($node->content['comments']['comments'] as $cid => $comment) { - if (is_numeric($cid)) { - $link_content['#links']['print_pdf']['query']['comment'] = $cid; - $node->content['comments']['comments'][$cid]['links']['print_pdf'] = $link_content; - } - } - } - } - } - - // Insert content corner links - if ((!empty($print_pdf_link_pos['corner'])) && ($view_mode == 'full')) { - $node->content['print_links']['#markup'] .= print_pdf_insert_link(NULL, $node); - } -} - -/** - * Implements hook_help(). - */ -function print_pdf_help($path, $arg) { - $print_pdf_link_pos = variable_get('print_pdf_link_pos', drupal_json_decode(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 "$link"; - } - } - } -} - /** * Implements hook_node_load(). */ @@ -382,12 +276,16 @@ function print_pdf_node_load($nodes, $types) { $ids[] = $node->nid; } - $result = db_query('SELECT nid, link, comments, url_list FROM {print_pdf_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid'); + $link = print_pdf_print_link(); + + $size = 'print_' . $link['format'] . '_size'; + $orientation = 'print_' . $link['format'] . '_orientation'; + + $result = db_query('SELECT nid, size, orientation FROM {print_pdf_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid'); foreach ($nodes as $node) { - $node->print_pdf_display = isset($result[$node->nid]) ? intval($result[$node->nid]->link) : variable_get('print_pdf_display_' . $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT); - $node->print_pdf_display_comment = isset($result[$node->nid]) ? intval($result[$node->nid]->comments) : variable_get('print_pdf_display_comment_' . $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT); - $node->print_pdf_display_urllist = isset($result[$node->nid]) ? intval($result[$node->nid]->url_list) : variable_get('print_pdf_display_urllist_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); + $node->{$size} = (isset($result[$node->nid]) && !empty($result[$node->nid]->size)) ? $result[$node->nid]->size : variable_get($size . '_' . $node->type); + $node->{$orientation} = (isset($result[$node->nid]) && !empty($result[$node->nid]->orientation)) ? $result[$node->nid]->orientation : variable_get($orientation . '_' . $node->type); } } @@ -395,13 +293,7 @@ function print_pdf_node_load($nodes, $types) { * Implements hook_node_insert(). */ function print_pdf_node_insert($node) { - 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); - } + return print_pdf_node_update($node); } /** @@ -409,169 +301,98 @@ function print_pdf_node_insert($node) { */ function print_pdf_node_update($node) { 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); + $link = print_pdf_print_link(); - _print_pdf_node_conf_modify($node->nid, $node->print_pdf_display, $node->print_pdf_display_comment, $node->print_pdf_display_urllist); + $size = 'print_' . $link['format'] . '_size'; + $orientation = 'print_' . $link['format'] . '_orientation'; + + if (!isset($node->{$size})) $node->{$size} = variable_get($size . '_' . $node->type); + if (!isset($node->{$orientation})) $node->{$orientation} = variable_get($orientation . '_' . $node->type); + + db_merge('print_pdf_node_conf') + ->key(array('nid' => $node->nid)) + ->fields(array( + 'size' => $node->{$size}, + 'orientation' => $node->{$orientation}, + )) + ->execute(); } + + print_pdf_cache_delete($node->nid); } /** * Implements hook_node_delete(). */ function print_pdf_node_delete($node) { - db_delete('print_pdf_node_conf') - ->condition('nid', $node->nid) - ->execute(); db_delete('print_pdf_page_counter') ->condition('path', 'node/' . $node->nid) ->execute(); + + print_pdf_cache_delete($node->nid); } /** * Implements 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 + // 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') || !empty($form['#node_edit_form']))) { - $form['print']['pdf_label'] = array( - '#type' => 'markup', - '#markup' => '

' . t('PDF version') . '

', + $link = print_pdf_print_link(); + + $size = 'print_' . $link['format'] . '_size'; + $orientation = 'print_' . $link['format'] . '_orientation'; + + $form['print']['print_' . $link['format']][$size] = array( + '#type' => 'select', + '#title' => t('Paper size'), + '#options' => _print_pdf_paper_sizes(TRUE), + '#description' => t('Choose the paper size of the generated PDF.'), ); - $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'), + $form['print']['print_' . $link['format']][$orientation] = array( + '#type' => 'select', + '#title' => t('Page orientation'), + '#options' => array('' => 'Unchanged', 'portrait' => t('Portrait'), 'landscape' => t('Landscape')), + '#description' => t('Choose the page orientation of the generated PDF.'), ); 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); + $form['print']['print_' . $link['format']][$size]['#default_value'] = variable_get($size . '_' . $form['#node_type']->type); + $form['print']['print_' . $link['format']][$orientation]['#default_value'] = variable_get($orientation . '_' . $form['#node_type']->type); } 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); + $form['print']['print_' . $link['format']][$size]['#default_value'] = isset($node->{$size}) ? $node->{$size} : variable_get($size . '_' . $node->type); + $form['print']['print_' . $link['format']][$orientation]['#default_value'] = isset($node->{$orientation}) ? $node->{$orientation} : variable_get($orientation . '_' . $node->type); } } } -/** - * 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_merge('print_pdf_node_conf') - ->key(array('nid' => $nid)) - ->fields(array( - 'link' => $link, - 'comments' => $comments, - 'url_list' => $url_list, - )) - ->execute(); -} - -/** - * 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 + * @param string $path + * path to be used in the link. If not specified, the current URL is used. + * @param object $node + * node object, to be used in checking node access. If the path argument is + * not provided, the path used will be node/nid. + * @param string $location + * where in the page where the link is being inserted ('link', 'corner', + * 'block', 'help'). + * + * @return bool * string with the HTML link to the printer-friendly page + * + * @ingroup print_api */ -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')); - } - else { - $query = NULL; - } - drupal_add_css(drupal_get_path('module', 'print') . '/css/printlinks.css'); - $format = theme('print_pdf_format_link'); - return '' . l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) . ''; +function print_pdf_insert_link($path = NULL, $node = NULL, $location = '') { + if (function_exists('print_ui_insert_link')) { + return print_ui_insert_link(print_pdf_print_link(), array('path' => $path, 'node' => $node, 'location' => $location)); } else { return FALSE; @@ -581,135 +402,153 @@ function print_pdf_insert_link($path = NULL, $node = NULL) { /** * Check if the link to the PDF version is allowed depending on the settings * - * @param $args + * @param array $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 + * view_mode, node, type, path + * + * @return bool + * FALSE if not allowed, TRUE otherwise */ function print_pdf_link_allowed($args) { - $view_mode = isset($args['view_mode']) ? $args['view_mode'] : ''; $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); - if ((($view_mode == 'teaser') && !variable_get('print_pdf_link_teaser', PRINT_PDF_LINK_TEASER_DEFAULT)) - || !in_array($view_mode, array('full', 'teaser', '')) || !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_query("SELECT comments FROM {print_pdf_node_conf} WHERE nid = :nid", array(':nid' => $node->nid))->fetchField(); - } - $print_display_comment = ($res && ($res[$node->nid] !== FALSE)) ? $res[$node->nid] : 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; + return (user_access('access PDF version') && (!empty($print_pdf_pdf_tool))); } /** - * Find out the version of the TCPDF library + * Implements hook_cron(). */ -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(DRUPAL_ROOT . '/' . $print_pdf_pdf_tool); +function print_pdf_cron() { + print_pdf_cache_clean(); +} - // Hide warnings, as some TCPDF constants may still be undefined - @$pdf = new TCPDF(); +/** + * Removes pdf files for nodes/paths if they are older than the lifetime. + */ +function print_pdf_cache_clean() { + $lifetime = variable_get('print_pdf_cache_lifetime', PRINT_PDF_CACHE_LIFETIME_DEFAULT); - if (method_exists($pdf, 'getTCPDFVersion')) { - return $pdf->getTCPDFVersion(); - } - elseif (defined('PDF_PRODUCER')) { - sscanf(PDF_PRODUCER, "TCPDF %s", $version); + if ($lifetime > 0) { + $files = file_scan_directory(print_pdf_cache_dir(), '!\d+\.pdf$!'); + foreach ($files as $file) { + // For all files in the cache directory, see when they were last accessed + $result = db_query("SELECT timestamp FROM {print_pdf_page_counter} WHERE path = :path", array(':path' => 'node/' . $file->name)) + ->fetchField(); - return $version; - } - else { - return 'unknown'; + // Keep the file only if the last access was within the cache max life value + if (($result === FALSE) || ($result + $lifetime < REQUEST_TIME)) { + print_pdf_cache_delete($file->name); + } + } } } /** - * Find out the version of the wkhtmltopdf library + * Returns the cache directory. + * + * @return string + * The scheme://path of the cache directory */ -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')); +function print_pdf_cache_dir() { + $scheme = 'private'; + if (!file_stream_wrapper_valid_scheme($scheme)) { + $scheme = 'temporary'; + } + return $scheme . '://print_pdf/cache'; +} - $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); +/** + * Deletes one or more files from the PDF cache directory. + * + * @param int nid + * The node ID of the page for which the cached PDF should be deleted. + * If not provided, the entire cache directory will be deleted. + */ +function print_pdf_cache_delete($nid = NULL) { + $directory = print_pdf_cache_dir(); + + if ($nid) { + $filename = $directory . '/' . $nid . '.pdf'; + if (is_file($filename)) { + file_unmanaged_delete($filename); + } + } + else { + // If no nid is provided, flush the entire cache. + if (is_dir($directory)) { + file_unmanaged_delete_recursive($directory); + } + } +} + +/** + * Displays the PDF as inline or a downloadable file. + * + * @param string $pdf + * PDF content string + * @param string $filename + * Filename of the generated PDF + * + * @return string + * The disposed PDF file + */ +function print_pdf_dispose_content($pdf, $filename) { + if (headers_sent()) { + exit('Unable to stream pdf: headers already sent'); + } + header('Cache-Control: private'); + header('Content-Type: application/pdf'); + + $content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT); + $attachment = ($content_disposition == 2) ? 'attachment' : 'inline'; + + header("Content-Disposition: $attachment; filename=\"$filename\""); + + echo $pdf; + flush(); + + return TRUE; +} + +/** + * Generate a PDF version of the provided HTML. + * + * @param string $html + * HTML content of the PDF + * @param array $meta + * Meta information to be used in the PDF + * - url: original URL + * - name: author's name + * - title: Page title + * - node: node object + * @param string $filename + * (optional) Filename of the generated PDF + * @param string $paper_size + * (optional) Paper size of the generated PDF + * @param string $page_orientation + * (optional) Page orientation of the generated PDF + * + * @return + * generated PDF page, or NULL in case of error + * + * @see print_pdf_controller() + * + * @ingroup print_api + */ +function print_pdf_generate_html($html, $meta, $filename = NULL, $paper_size = NULL, $page_orientation = NULL) { + $pdf_tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT)); + + module_load_include('inc', $pdf_tool[0], $pdf_tool[0] . '.pages'); + + $function = $pdf_tool[0] . '_print_pdf_generate'; + if (function_exists($function)) { + $pdf = $function($html, $meta, $paper_size, $page_orientation); + } + if ($filename) { + return print_pdf_dispose_content($pdf, $filename); } - return ($matches[1]); + return $pdf; } /** @@ -721,3 +560,34 @@ function print_pdf_views_api() { 'path' => drupal_get_path('module', 'print_pdf'), ); } + +/** + * Lists all possible paper sizes + * + * @return + * array of strings with the available paper sizes + */ +function _print_pdf_paper_sizes($include_default = FALSE) { + $ret = array(); + + $ret = ($include_default) ? array('' => 'Unchanged') : array(); + + $ret += 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', + ); + + return $ret; +} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.pages.inc b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.pages.inc index 50103ec7..be867d01 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.pages.inc +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.pages.inc @@ -44,12 +44,12 @@ function print_pdf_controller() { $pdf_filename = variable_get('print_pdf_filename', PRINT_PDF_FILENAME_DEFAULT); if (!empty($pdf_filename) && !empty($node)) { - $pdf_filename = token_replace($pdf_filename, array('node' => $node)); + $pdf_filename = token_replace($pdf_filename, array('node' => $node), array('clear' => TRUE)); } else { - $pdf_filename = token_replace($pdf_filename, array('site')); - if (empty($pdf_filename) || count(token_scan($pdf_filename))) { - // If there are still tokens, use a fallback solution + $pdf_filename = token_replace($pdf_filename, array('site'), array('clear' => TRUE)); + if (empty($pdf_filename)) { + // If empty, use a fallback solution $pdf_filename = str_replace('/', '_', $path); } } @@ -70,7 +70,7 @@ function print_pdf_controller() { exit; } - $nodepath = (isset($node->path) && is_string($node->path)) ? drupal_get_normal_path($node->path) : 'node/' . $path; + $nodepath = (isset($node->nid)) ? 'node/' . $node->nid : drupal_get_normal_path($path); db_merge('print_pdf_page_counter') ->key(array('path' => $nodepath)) ->fields(array( @@ -83,548 +83,98 @@ function print_pdf_controller() { drupal_exit(); } -function print_pdf_generate_path($path, $query = NULL, $cid = NULL, $pdf_filename = NULL) { +/** + * Gennerate a PDF for a given Drupal path. + * + * @param string $path + * path of the page to convert to PDF + * @param array $query + * (optional) array of key/value pairs as used in the url() function for the + * query + * @param int $cid + * (optional) comment ID of the comment to render. + * @param string $pdf_filename + * (optional) filename of the generated PDF + * @param string $view_mode + * (optional) view mode to be used when rendering the content + * + * @return + * generated PDF page, or NULL in case of error + * + * @see print_pdf_controller() + */ +function print_pdf_generate_path($path, $query = NULL, $cid = NULL, $pdf_filename = NULL, $view_mode = PRINT_VIEW_MODE) { global $base_url; - $print = print_controller($path, $query, $cid, PRINT_PDF_FORMAT); - if ($print === FALSE) { - return; - } + $link = print_pdf_print_link(); + $node = print_controller($path, $link['format'], $cid, $view_mode); + if ($node) { + // Call the current tool's hook_pdf_tool_info(), to see if we need to expand CSS + $pdf_tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT)); + $cache_enabled = variable_get('print_pdf_cache_enabled', PRINT_PDF_CACHE_ENABLED_DEFAULT); - // 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']); + $function = $pdf_tool[0] . '_pdf_tool_info'; + if (function_exists($function)) { + $info = $function(); + } + $expand = isset($info['expand_css']) ? $info['expand_css'] : FALSE; - // Send to printer option causes problems with PDF - $print['sendtoprinter'] = ''; + $html = theme('print', array('node' => $node, 'query' => $query, $expand, 'format' => $link['format'])); - $node = $print['node']; - $html = theme('print', array('print' => $print, 'type' => PRINT_PDF_FORMAT, 'node' => $node)); + // Img elements must be set to absolute + $pattern = '!<(img\s[^>]*?)>!is'; + $html = preg_replace_callback($pattern, '_print_rewrite_urls', $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); + // 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}/" . $link['path'] . '/.*?#!', '#', $html); - return print_pdf_generate_html($print, $html, $pdf_filename); -} + $meta = array( + 'node' => $node, + 'url' => url(drupal_get_path_alias(empty($node->nid) ? $node->path : "node/$node->nid"), array('absolute' => TRUE)), + ); + if (isset($node->name)) $meta['name'] = $node->name; + if (isset($node->title)) $meta['title'] = $node->title; -function print_pdf_generate_html($print, $html, $filename = NULL) { - $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); + $paper_size = isset($node->print_pdf_size) ? $node->print_pdf_size : NULL; + $page_orientation = isset($node->print_pdf_orientation) ? $node->print_pdf_orientation : NULL; - 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); - - $lang = (function_exists('language_negotiation_get_any') && language_negotiation_get_any('locale-url')) ? $language->language : ''; - - // Always convert private to local paths - $pattern = "!(]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?system/files/([^>]*?>)!is"; - $replacement = '$1file://' . realpath(variable_get('file_private_path', '')) . '/$2'; - $html = preg_replace($pattern, $replacement, $html); - if ($print_pdf_images_via_file) { - $pattern = "!(]*?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)) { - define("DOMPDF_ENABLE_PHP", FALSE); - define("DOMPDF_ENABLE_REMOTE", TRUE); - define("DOMPDF_TEMP_DIR", file_directory_temp()); - define("DOMPDF_UNICODE_ENABLED", variable_get('print_pdf_dompdf_unicode', PRINT_PDF_DOMPDF_UNICODE_DEFAULT)); - define("DOMPDF_FONT_CACHE", drupal_realpath('public://' . PRINT_PDF_DOMPDF_CACHE_DIR_DEFAULT . '/fonts/')); - } - - require_once(DRUPAL_ROOT . '/' . $print_pdf_pdf_tool); - 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('!!', '', $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', array('html' => $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('€', '€', $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); - } - - // Must get rid of tbody (dompdf goes into recursion) - $html = preg_replace('!]*?>|!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)) { - define('K_TCPDF_EXTERNAL_CONFIG', TRUE); - define('K_PATH_MAIN', dirname($_SERVER['SCRIPT_FILENAME'])); - define('K_PATH_URL', $base_url); - define('K_PATH_FONTS', $pdf_tool_path . '/fonts/'); - define('K_PATH_CACHE', drupal_realpath('public://' . PRINT_PDF_TCPDF_CACHE_DIR_DEFAULT . '/cache/')); - define('K_PATH_IMAGES', ''); - define('K_BLANK_IMAGE', $pdf_tool_path . '/images/_blank.png'); - define('K_CELL_HEIGHT_RATIO', 1.25); - 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 = "!]*?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 = "!(]*?src\s*?=\s*?['\"]?{$base_url}[^>]*?)(?:%3F|\?)[\w=&]+([^>]*?>)!is"; - $html = preg_replace($pattern, '$1$2', $html); - - require_once(DRUPAL_ROOT . '/' . $print_pdf_pdf_tool); - 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 (property_exists($print['node'], 'name')) { - $pdf->SetAuthor(strip_tags($print['node']->name)); - } - $pdf->SetCreator(variable_get('site_name', 'Drupal')); - $pdf->SetTitle(html_entity_decode($print['title'], ENT_QUOTES, 'UTF-8')); - $pdf->setPDFVersion('1.6'); - $pdf->setFontSubsetting(variable_get('print_pdf_font_subsetting', PRINT_PDF_FONT_SUBSETTING_DEFAULT)); - - if ($language->direction == LANGUAGE_RTL) { - $pdf->setRTL(TRUE); - } - - $pdf = theme('print_pdf_tcpdf_header', array('pdf' => $pdf, 'html' => $html, 'font' => $font)); - $pdf = theme('print_pdf_tcpdf_footer', array('pdf' => $pdf, 'html' => $html, 'font' => $font)); - $pdf = theme('print_pdf_tcpdf_page', array('pdf' => $pdf)); - - // add a page - $pdf->AddPage(); - - $pdf = theme('print_pdf_tcpdf_content', array('pdf' => $pdf, 'html' => $html, 'font' => $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 (!empty($print_pdf_wkhtmltopdf_options)) { - $print_pdf_wkhtmltopdf_options = token_replace($print_pdf_wkhtmltopdf_options, array('node' => $print['node'])); - } - - $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.'; + $pdf = ''; + $cachemiss = FALSE; + if ($cache_enabled && isset($node->nid)) { + // See if the file exists in the cache + $cachefile = drupal_realpath(print_pdf_cache_dir()) . '/' . $node->nid . '.pdf'; + if (is_readable($cachefile)) { + // Get the PDF content from the cached file + $pdf = file_get_contents($cachefile); + if ($pdf === FALSE) { + watchdog('print_pdf', 'Failed to read from cached file %file', array('%file' => $cached), WATCHDOG_ERROR); + } } - watchdog('print_pdf', "wkhtmltopdf (returned $retval): $error"); - } - } - - if (!empty($pdf)) { - if ($filename) { - if (headers_sent()) { - exit("Unable to stream pdf: headers already sent"); + else { + $cachemiss = TRUE; } - 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; + + // If cache is off or file is not cached, generate one from scratch + if (empty($pdf)) { + $pdf = print_pdf_generate_html($html, $meta, NULL, $paper_size, $page_orientation); + } + + if (!empty($pdf)) { + // A PDF was created, save it to cache if configured + if ($cachemiss) { + if (file_unmanaged_save_data($pdf, $cachefile, FILE_EXISTS_REPLACE) == FALSE) { + watchdog('print_pdf', 'Failed to write to "%f".', array('%f' => $filename), WATCHDOG_ERROR); + } + } + + return $pdf_filename ? print_pdf_dispose_content($pdf, $pdf_filename) : $pdf; } } else { - drupal_set_message(t('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($vars) { - preg_match('!!si', $vars['html'], $tpl_footer); - $html = str_replace($tpl_footer[0], '', $vars['html']); - - $text = ''; - - return str_replace("", "" . $text, $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($vars) { - $pdf = $vars['pdf']; - preg_match('!!si', $vars['html'], $tpl_logo); - preg_match('!(.*?)!si', $vars['html'], $tpl_title); - preg_match('!!si', $vars['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($vars['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($vars) { - $pdf = $vars['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($vars) { - $pdf = $vars['pdf']; - // set content font - $pdf->setFont($vars['font'][0], $vars['font'][1], $vars['font'][2]); - - preg_match('!(.*)!sim', $vars['html'], $matches); - $pattern = '!(?:|)!si'; - $matches[1] = preg_replace($pattern, '', $matches[1]); - - // Make CCK fields look better - $matches[1] = preg_replace('!(
.*?
)\s*!sm', '$1', $matches[1]); - $matches[1] = preg_replace('!(.*?)!si', $vars['html'], $tpl_footer); - $footer = trim(preg_replace('!]*?>!i', '', $tpl_footer[1])); - - // set footer font - $vars['font'][2] *= 0.8; - $pdf->setFooterFont($vars['font']); - // set footer margin - $pdf->SetFooterMargin(10); - // set footer data - $pdf->SetFooterData($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($vars) { - $pdf = $vars['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; -} diff --git a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.views.inc b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.views.inc index f3dc6905..847c389a 100644 --- a/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.views.inc +++ b/sites/all/modules/contrib/admin/print/print_pdf/print_pdf.views.inc @@ -33,7 +33,7 @@ function print_pdf_views_data() { 'left_field' => 'nid', 'field' => 'path', // 'type' => 'INNER', - 'handler' => 'print_pdf_join_page_counter', + 'handler' => 'print_join_page_counter', ); // print_pdf_node_conf fields @@ -85,6 +85,34 @@ function print_pdf_views_data() { 'handler' => 'views_handler_sort', ), ); + $data['print_pdf_node_conf']['size'] = array( + 'title' => t('PDF: Paper size'), + 'help' => t('Configured PDF paper size'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); + $data['print_pdf_node_conf']['orientation'] = array( + 'title' => t('PDF: Page orientation'), + 'help' => t('Configured PDF page orientation.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ); // print_pdf_page_counter fields diff --git a/sites/all/modules/contrib/admin/print/css/printlinks-rtl.css b/sites/all/modules/contrib/admin/print/print_ui/css/print_ui.theme-rtl.css similarity index 75% rename from sites/all/modules/contrib/admin/print/css/printlinks-rtl.css rename to sites/all/modules/contrib/admin/print/print_ui/css/print_ui.theme-rtl.css index 852b0e3a..62b82fc8 100644 --- a/sites/all/modules/contrib/admin/print/css/printlinks-rtl.css +++ b/sites/all/modules/contrib/admin/print/print_ui/css/print_ui.theme-rtl.css @@ -1,14 +1,13 @@ - .print-link { /* Use these for links above the content */ text-align: left; /* Use these for links in a corner of the content */ /* - float:left; + float: left; */ } -.print_html, .print_mail, .print_pdf { +.print_html, .print_mail, .print_pdf, .print_epub { margin-left: 0; margin-right: 1em; } @@ -21,7 +20,3 @@ img.print-icon-margin { padding-left: 4px; } - -label.printmail-label { - float: right; -} diff --git a/sites/all/modules/contrib/admin/print/css/printlinks.css b/sites/all/modules/contrib/admin/print/print_ui/css/print_ui.theme.css similarity index 69% rename from sites/all/modules/contrib/admin/print/css/printlinks.css rename to sites/all/modules/contrib/admin/print/print_ui/css/print_ui.theme.css index 4547cc51..d0649ec2 100644 --- a/sites/all/modules/contrib/admin/print/css/printlinks.css +++ b/sites/all/modules/contrib/admin/print/print_ui/css/print_ui.theme.css @@ -1,4 +1,3 @@ - .print-link { /* Use these for links above the content */ display: block; @@ -6,17 +5,17 @@ padding-bottom: 0.5em; /* Use these for links in a corner of the content */ /* - position:relative; + position: relative; bottom: 0.5em; - float:right; + float: right; */ } -div#block-print-print-links span { +div#block-print-ui-print-links span { display: block; } -.print_html, .print_mail, .print_pdf { +.print_html, .print_mail, .print_pdf, .print_epub { margin-left: 1em; } @@ -31,8 +30,3 @@ img.print-icon { img.print-icon-margin { padding-right: 4px; } - -label.printmail-label { - width: 175px; - float: left; -} diff --git a/sites/all/modules/contrib/admin/print/print_ui/print_ui.admin.inc b/sites/all/modules/contrib/admin/print/print_ui/print_ui.admin.inc new file mode 100644 index 00000000..60c6133b --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_ui/print_ui.admin.inc @@ -0,0 +1,191 @@ + 'fieldset', + '#title' => t('Link options'), + ); + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + $format = $link['format']; + + $form['settings']['checkboxes']['link_pos']['print_' . $format . '_link_pos'] = array( + '#type' => 'checkboxes', + '#title' => t('Link location'), + '#default_value' => variable_get('print_' . $format . '_link_pos', drupal_json_decode(PRINT_UI_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 version pages. The Links area is usually below the node content, whereas the Content corner is placed in the upper-right corner of the node content (these apply only in node pages). The Help area is used for system pages. Enabling the block area link will allow links of this format in the provided links module. Unselect all options to disable the link. Even if the link is disabled, you can still go to %path where nid is the numeric id of the node.', array('%path' => $link['path'] . '/nid')), + ); + + $form['settings']['checkboxes']['link_teaser']['print_' . $format . '_link_teaser'] = array( + '#type' => 'checkbox', + '#title' => t('Display link in teaser'), + '#default_value' => variable_get('print_' . $format . '_link_teaser', PRINT_UI_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, + ); + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + $format = $link['format']; + + $form['settings']['adv_link']['show_link']['print_' . $format . '_show_link'] = array( + '#type' => 'radios', + '#title' => t('Link style'), + '#default_value' => variable_get('print_' . $format . '_show_link', PRINT_UI_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']['link_use_alias']['print_' . $format . '_link_use_alias'] = array( + '#type' => 'checkbox', + '#title' => t('Use URL alias instead of node ID'), + '#default_value' => variable_get('print_' . $format . '_link_use_alias', PRINT_UI_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']['link_class']['print_' . $format . '_link_class'] = array( + '#type' => 'textfield', + '#title' => t('Link class'), + '#default_value' => variable_get('print_' . $format . '_link_class', $link['class']), + '#size' => 20, + '#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']['sys_link_visibility']['print_' . $format . '_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_' . $format . '_sys_link_visibility', PRINT_UI_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']['sys_link_pages']['print_' . $format . '_sys_link_pages'] = array( + '#type' => 'textarea', + '#default_value' => variable_get('print_' . $format . '_sys_link_pages', PRINT_UI_SYS_LINK_PAGES_DEFAULT), + '#rows' => 3, + '#description' => t('Setting this option will add a link on pages created by Drupal or the enabled modules.') . '
' . + 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' => '')), + ); + + if (module_exists('php')) { + $access = user_access('use PHP for settings'); + + if ($form['settings']['adv_link']['sys_link_visibility']['print_' . $format . '_sys_link_visibility']['#default_value'] == 2 && !$access) { + $form['settings']['adv_link']['sys_link_visibility']['print_' . $format . '_sys_link_visibility'] = array('#type' => 'value', '#value' => 2); + $form['settings']['adv_link']['sys_link_pages']['print_' . $format . '_sys_link_pages'] = array('#type' => 'value', '#value' => $form['settings']['adv_link']['print_' . $format . '_sys_link_pages']['#default_value']); + } + elseif ($access) { + $form['settings']['adv_link']['sys_link_visibility']['print_' . $format . '_sys_link_visibility']['#options'][] = t('Show if the following PHP code returns TRUE (PHP-mode, experts only).'); + $form['settings']['adv_link']['sys_link_pages']['print_' . $format . '_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' => '')); + } + } + + $form['settings']['adv_link']['book_link']['print_' . $format . '_book_link'] = array( + '#type' => 'radios', + '#title' => t('Link in book hierarchy nodes'), + '#default_value' => variable_get('print_' . $format . '_book_link', PRINT_UI_BOOK_LINK_DEFAULT), + '#options' => array(t('No link'), t('Current page and sub-pages'), t('Current page only')), + ); + } + } + + $form['#theme'] = 'print_ui_settings'; + + return system_settings_form($form); +} + +/** + * Returns HTML for the link settings page. + * + * @param array $variables + * An associative array containing: + * - form: A render element representing the form. + * + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_ui_settings($variables) { + $form = $variables['form']; + $header = array(''); + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $header[] = array('data' => $link['format'], 'class' => 'checkbox'); + } + } + + foreach (element_children($form['settings']) as $group) { + $rows = array(); + foreach (element_children($form['settings'][$group]) as $elem) { + $row = array(); + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + $format = $link['format']; + + $item = $form['settings'][$group][$elem]['print_' . $format . '_' . $elem]; + + if (empty($row)) { + // Start row, fill title and description + $row_desc = array( + '#type' => 'item', + '#markup' => isset($item['#title']) ? $item['#title'] : '', + '#description' => isset($item['#description']) ? $item['#description'] : '', + ); + + $row[] = array('data' => drupal_render($row_desc), 'class' => array('')); + } + + $item['#title_display'] = 'invisible'; + $item['#description'] = ''; + + $class = ($item['#type'] == 'checkbox') ? 'checkbox' : ''; + + $row[] = array('data' => drupal_render($item), 'class' => array($class)); + } + } + $rows[] = $row; + } + + $form['settings'][$group]['#children'] = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'permissions'))); + } + + $output = drupal_render_children($form); + + return $output; +} diff --git a/sites/all/modules/contrib/admin/print/print_ui/print_ui.api.php b/sites/all/modules/contrib/admin/print/print_ui/print_ui.api.php new file mode 100644 index 00000000..75a6d753 --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_ui/print_ui.api.php @@ -0,0 +1,101 @@ + 'foo', + 'text' => t('Foo version'), + 'description' => t('Display the foo version of this page.'), + 'path' => 'printfoo', + 'class' => 'print-foo', + 'icon' => 'foo_icon.png', + 'module' => 'print_foo', + ); +} + +/** + * Checks if the link is allowed according to the appropriate sub-module. + * + * Normally checks if the user holds the required access permission, but can + * be used for extra checks, such as the proper module configuration, etc. + * + * @param array $args + * An associative array containing: + * - path: path to the non-node page being displayed. + * - node: path to the node beign displayed. + * - view_mode: current view mode of the node being displayed. + * - type: 'node' or 'comment'. + * + * @return bool + * FALSE if not allowed, TRUE otherwise + * + * @ingroup print_hooks + */ +function hook_link_allowed($args) { + return (user_access('access foo')); +} + +/** + * Checks if the link is allowed according to the appropriate sub-module. + * + * Normally checks if the user holds the required access permission, but can + * be used for extra checks, such as the proper module configuration, etc. + * + * @param array $args + * An associative array containing: + * - path: path to the non-node page being displayed. + * - node: path to the node beign displayed. + * - view_mode: current view mode of the node being displayed. + * - type: 'node' or 'comment'. + * + * @ingroup print_hooks + */ +function hook_print_new_window_alter(&$new_window, $format) { + if ($format == 'foo') { + $new_window = variable_get('print_foo_new_windo', FALSE); + } +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/sites/all/modules/contrib/admin/print/print_ui/print_ui.info b/sites/all/modules/contrib/admin/print/print_ui/print_ui.info new file mode 100644 index 00000000..77944aeb --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_ui/print_ui.info @@ -0,0 +1,13 @@ +name = "Printer-friendly pages UI" +description = "Manages the printer-friendly versions link display conditions. Without this module, those links are not displayed." +core = 7.x +package = "Printer, email and PDF versions" +dependencies[] = print +configure = admin/config/user-interface/print/ui + +; Information added by Drupal.org packaging script on 2014-04-02 +version = "7.x-2.0" +core = "7.x" +project = "print" +datestamp = "1396426766" + diff --git a/sites/all/modules/contrib/admin/print/print_ui/print_ui.install b/sites/all/modules/contrib/admin/print/print_ui/print_ui.install new file mode 100644 index 00000000..54c1aecc --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_ui/print_ui.install @@ -0,0 +1,22 @@ +fields(array( + 'weight' => 1, + )) + ->condition('type', 'module') + ->condition('name', 'print_ui') + ->execute(); +} diff --git a/sites/all/modules/contrib/admin/print/print_ui/print_ui.module b/sites/all/modules/contrib/admin/print/print_ui/print_ui.module new file mode 100644 index 00000000..3affdb3c --- /dev/null +++ b/sites/all/modules/contrib/admin/print/print_ui/print_ui.module @@ -0,0 +1,770 @@ + array( + 'title' => t('Node-specific configuration'), + 'description' => t('Enable access to the per-node settings.'), + ), + ); +} + +/** + * Implements hook_theme(). + */ +function print_ui_theme() { + return array( + 'print_ui_format_link' => array( + 'variables' => array('format' => '', 'location' => ''), + ), + 'print_ui_settings' => array( + 'render element' => 'form', + 'file' => 'print_ui.admin.inc', + ), + ); +} + +/** + * Implements hook_menu(). + */ +function print_ui_menu() { + $items = array(); + $items['admin/config/user-interface/print/ui'] = array( + 'title' => 'Links', + 'description' => 'Configure the print module links.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('print_ui_settings'), + 'access arguments' => array('administer print'), + 'weight' => 9, + 'type' => MENU_LOCAL_TASK, + 'file' => 'print_ui.admin.inc', + ); + + return $items; +} + +/** + * Implements hook_block_info(). + */ +function print_ui_block_info() { + $block['print-links']['info'] = t('Printer, email and PDF versions'); + $block['print-links']['cache'] = DRUPAL_CACHE_PER_PAGE; + return $block; +} + +/** + * Implements hook_block_view(). + */ +function print_ui_block_view($delta = '') { + $block = array(); + + switch ($delta) { + case 'print-links': + $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 (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $link_pos = variable_get('print_' . $link['format'] . '_link_pos', drupal_json_decode(PRINT_UI_LINK_POS_DEFAULT)); + + if (!(empty($link_pos['block']))) { + $links = print_ui_insert_link($link, array('node' => $node, 'location' => 'block')); + if (!empty($links)) { + $block['content'] .= $links; + } + } + } + } + break; + } + return $block; +} + +/** + * Implements hook_help(). + */ +function print_ui_help($path, $arg) { + $links = ''; + + if (($path !== 'node/%') && ($path !== 'node/%/revisions/%/view')) { + static $output = FALSE; + + if ($output === FALSE) { + $output = TRUE; + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $link_pos = variable_get('print_' . $link['format'] . '_link_pos', drupal_json_decode(PRINT_UI_LINK_POS_DEFAULT)); + + if (!empty($link_pos['help'])) { + $links .= print_ui_insert_link($link, array('location' => 'help')); + } + } + } + if ($links) { + return "$links"; + } + } + } +} + +/** + * Implements hook_node_view_alter(). + */ +function print_ui_node_view_alter(&$build) { + if (isset($build['links']['book']['#links']['book_printer'])) { + $book_link = variable_get('print_html_book_link', PRINT_UI_BOOK_LINK_DEFAULT); + + if ($book_link) { + $link = print_print_link(); + $link_pos = variable_get('print_html_link_pos', drupal_json_decode(PRINT_UI_LINK_POS_DEFAULT)); + + if (!empty($link_pos['link'])) { + $format = theme('print_ui_format_link', array('format' => 'html', 'location' => 'link')); + + switch ($book_link) { + case 1: + $path = $build['links']['book']['#links']['book_printer']['href']; + break; + case 2: + $link_use_alias = variable_get('print_html_link_use_alias', PRINT_UI_LINK_USE_ALIAS_DEFAULT); + $path = ($link_use_alias && ($alias = drupal_lookup_path('alias', 'node/' . $build['#node']->nid))) ? $alias : $build['#node']->nid; + break; + } + + $build['links']['book']['#links']['book_printer'] = array( + 'href' => $link['path'] . '/' . $path, + 'title' => $format['text'], + 'attributes' => $format['attributes'], + 'html' => $format['html'], + ); + } + else { + unset($build['links']['book']['#links']['book_printer']); + } + } + } +} + +/** + * Implements hook_node_view(). + */ +function print_ui_node_view($node, $view_mode) { + $corner_markup = ''; + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $link_pos = variable_get('print_' . $link['format'] . '_link_pos', drupal_json_decode(PRINT_UI_LINK_POS_DEFAULT)); + $link_use_alias = variable_get('print_' . $link['format'] . '_link_use_alias', PRINT_UI_LINK_USE_ALIAS_DEFAULT); + + if (!preg_match('!^node/[\d]*/revisions/[\d]*/view$!', $_GET['q'])) { + // Not a revision, use node->nid to build the path + $path = (($link_use_alias) && ($alias = drupal_lookup_path('alias', 'node/' . $node->nid))) ? $alias : $node->nid; + } + else { + // This is a node revision, replace only the node component + $path = preg_replace('!^node/!', '', $_GET['q']); + } + $path = $link['path'] . '/' . $path; + + foreach (array('node', 'comment') as $type) { + $allowed_type = print_ui_link_allowed($link, array('type' => $type, 'node' => $node, 'view_mode' => $view_mode)); + if ($allowed_type) { + drupal_add_css(drupal_get_path('module', 'print_ui') . '/css/print_ui.theme.css'); + $links = array(); + $format = theme('print_ui_format_link', array('format' => $link['format'], 'location' => 'link')); + + // Show book link + if ($allowed_type === PRINT_UI_ALLOW_BOOK_LINK) { + $path = $link['path'] . '/book/export/html/' . $node->nid; + + $links['book_' . $link['format']] = array( + 'href' => $path, + 'title' => $format['text'], + 'attributes' => $format['attributes'], + 'html' => $format['html'], + ); + } + elseif ($allowed_type === PRINT_UI_ALLOW_NORMAL_LINK) { + $links['print_' . $link['format']] = array( + 'href' => $path, + 'title' => $format['text'], + 'attributes' => $format['attributes'], + 'html' => $format['html'], + 'query' => _print_ui_query_string_encode($_GET, array('q')), + ); + } + + $link_content = array( + '#theme' => 'links', + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + + // If it's a node, and configured to show the link, but it's not the html version of a book then show it + if (($type == 'node') && !empty($link_pos['link']) && !(isset($node->book) && ($link['format'] == 'html'))) { + $node->content['links']['print_' . $link['format']] = $link_content; + } + elseif (($type == 'comment') && isset($node->content['comments']['comments'])) { + foreach ($node->content['comments']['comments'] as $cid => $comment) { + if (is_numeric($cid)) { + $link_content['#links']['print_' . $link['format']]['query']['comment'] = $cid; + $node->content['comments']['comments'][$cid]['links']['print_' . $link['format']] = $link_content; + } + } + } + } + } + + if (!empty($link_pos['corner'])) { + $corner_markup .= print_ui_insert_link($link, array('node' => $node, 'path' => $path, 'location' => 'corner')); + } + } + } + + if (($view_mode == 'full') && (!empty($corner_markup))) { + // Insert content corner links + $node->content['print_links'] = array( + '#prefix' => '', + '#markup' => $corner_markup, + '#suffix' => '', + '#weight' => -101, + ); + } +} + +/** + * Implements hook_node_load(). + */ +function print_ui_node_load($nodes, $types) { + $ids = array(); + foreach ($nodes as $node) { + $ids[] = $node->nid; + } + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $display = 'print_' . $link['format'] . '_display'; + $display_comment = 'print_' . $link['format'] . '_display_comment'; + $display_urllist = 'print_' . $link['format'] . '_display_urllist'; + + $result = db_query('SELECT nid, link, comments, url_list FROM {' . $module . '_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid'); + + foreach ($nodes as $node) { + $node->{$display} = isset($result[$node->nid]) ? intval($result[$node->nid]->link) : variable_get($display . '_' . $node->type, PRINT_UI_TYPE_SHOW_LINK_DEFAULT); + $node->{$display_comment} = isset($result[$node->nid]) ? intval($result[$node->nid]->comments) : variable_get($display_comment . '_' . $node->type, PRINT_UI_TYPE_COMMENT_LINK_DEFAULT); + $node->{$display_urllist} = isset($result[$node->nid]) ? intval($result[$node->nid]->url_list) : variable_get($display_urllist . '_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); + } + } + } +} + +/** + * Implements hook_node_insert(). + */ +function print_ui_node_insert($node) { + return print_ui_node_update($node); +} + +/** + * Implements hook_node_update(). + */ +function print_ui_node_update($node) { + if (user_access('administer print') || user_access('node-specific print configuration')) { + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $display = 'print_' . $link['format'] . '_display'; + $display_comment = 'print_' . $link['format'] . '_display_comment'; + $display_urllist = 'print_' . $link['format'] . '_display_urllist'; + + if (!isset($node->{$display}) || $node->{$display} === NULL) { + $node->{$display} = variable_get($display . '_' . $node->type, PRINT_UI_TYPE_SHOW_LINK_DEFAULT); + } + if (!isset($node->{$display_comment}) || $node->{$display_comment} === NULL) { + $node->{$display_comment} = variable_get($display_comment . '_' . $node->type, PRINT_UI_TYPE_COMMENT_LINK_DEFAULT); + } + if (!isset($node->{$display_urllist}) || $node->{$display_urllist} === NULL) { + $node->{$display_urllist} = variable_get($display_urllist . '_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); + } + + db_merge($module . '_node_conf') + ->key(array('nid' => $node->nid)) + ->fields(array( + 'link' => $node->{$display}, + 'comments' => $node->{$display_comment}, + 'url_list' => $node->{$display_urllist}, + )) + ->execute(); + } + } + } +} + +/** + * Implements hook_node_delete(). + */ +function print_ui_node_delete($node) { + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + db_delete($module . '_node_conf') + ->condition('nid', $node->nid) + ->execute(); + } + } +} + +/** + * Implements hook_form_alter(). + */ +function print_ui_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') || !empty($form['#node_edit_form']))) { + $form['print'] = array( + '#type' => 'fieldset', + '#title' => t('Printer, email and PDF versions'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => PRINT_UI_TYPE_FIELDS_WEIGHT, + '#group' => 'additional_settings', + ); + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + $form['print']['print_' . $link['format']] = array( + '#type' => 'fieldset', + '#title' => check_plain($link['text']), + '#collapsible' => TRUE, + ); + + $display = 'print_' . $link['format'] . '_display'; + $display_comment = 'print_' . $link['format'] . '_display_comment'; + $display_urllist = 'print_' . $link['format'] . '_display_urllist'; + + $form['print']['print_' . $link['format']][$display] = array( + '#type' => 'checkbox', + '#title' => t('Show link'), + ); + $form['print']['print_' . $link['format']][$display_comment] = array( + '#type' => 'checkbox', + '#title' => t('Show link in individual comments'), + ); + $form['print']['print_' . $link['format']][$display_urllist] = array( + '#type' => 'checkbox', + '#title' => t('Show Printer-friendly URLs list'), + ); + + if ($form_id == 'node_type_form') { + $form['print']['print_' . $link['format']][$display]['#default_value'] = variable_get($display . '_' . $form['#node_type']->type, PRINT_UI_TYPE_SHOW_LINK_DEFAULT); + $form['print']['print_' . $link['format']][$display_comment]['#default_value'] = variable_get($display_comment . '_' . $form['#node_type']->type, PRINT_UI_TYPE_COMMENT_LINK_DEFAULT); + $form['print']['print_' . $link['format']][$display_urllist]['#default_value'] = variable_get($display_urllist . '_' . $form['#node_type']->type, PRINT_TYPE_URLLIST_DEFAULT); + } + else { + $node = $form['#node']; + $form['print']['print_' . $link['format']][$display]['#default_value'] = isset($node->{$display}) ? $node->{$display} : variable_get($display . '_' . $node->type, PRINT_UI_TYPE_SHOW_LINK_DEFAULT); + $form['print']['print_' . $link['format']][$display_comment]['#default_value'] = isset($node->{$display_comment}) ? $node->{$display_comment} : variable_get($display_comment . '_' . $node->type, PRINT_UI_TYPE_COMMENT_LINK_DEFAULT); + $form['print']['print_' . $link['format']][$display_urllist]['#default_value'] = isset($node->{$display_urllist}) ? $node->{$display_urllist} : variable_get($display_urllist . '_' . $node->type, PRINT_TYPE_URLLIST_DEFAULT); + } + } + } + } +} + +/** + * Auxiliary function to fill the Printer-friendly link attributes + * + * @param string $title + * text to displayed by the link when hovering over it with the mouse + * @param string $class + * class attribute to be used in the link + * @param bool $new_window + * if TRUE opens the target page in a new window + * + * @return array + * An associative array containing: + * - title: text to be used when hovering over the link. + * - class: CSS class of the link tag. + * - target: used for opening a new window with the non-javascript method + * - onclick: open a new window, with the javascript method + * - rel: SEO-related attribute indicating that the printer-friendly version + * should not be indexed by search engine robots. + */ +function _print_ui_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'] = array($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; +} + +/** + * Format the Printer-friendly link + * + * @return array + * An associative array containing: + * - text: The content of the link + * - html: TRUE if the text contains HTML tags, FALSE if it's plain text + * - attributes: several attributes of the link tag (title, class, target, + * onclick, rel) + * + * @see _print_ui_fill_attributes() + * @ingroup themeable + * @ingroup print_themeable + */ +function theme_print_ui_format_link($vars) { + $format = $vars['format']; + + foreach (module_implements('print_link') as $module) { + $function = $module . '_print_link'; + if (function_exists($function)) { + $link = call_user_func_array($function, array()); + + if ($link['format'] == $format) { + $link_class = variable_get('print_' . $link['format'] . '_link_class', $link['class']); + + $new_window = FALSE; + $func = $module . '_print_new_window_alter'; + if (function_exists($func)) { + $func($new_window, $link['format']); + } + + $show_link = variable_get('print_' . $link['format'] . '_show_link', PRINT_UI_SHOW_LINK_DEFAULT); + $link_text = filter_xss(variable_get('print_' . $link['format'] . '_link_text', $link['text'])); + + if ($show_link >= 2) { + $img = drupal_get_path('module', $module) . '/icons/' . $link['icon']; + switch ($show_link) { + case 2: + $text = theme('image', array('path' => $img, 'width' => '16px', 'height' => '16px', 'alt' => $link_text, 'title' => $link_text, 'attributes' => array('class' => array('print-icon')))); + break; + case 3: + $text = theme('image', array('path' => $img, 'width' => '16px', 'height' => '16px', 'alt' => $link_text, 'title' => $link_text, 'attributes' => array('class' => array('print-icon', 'print-icon-margin')))) . $link_text; + break; + } + $html = TRUE; + } + else { + $text = $link_text; + $html = FALSE; + } + + return array( + 'text' => $text, + 'html' => $html, + 'attributes' => _print_ui_fill_attributes($link['description'], strip_tags($link_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 array $link + * array returned by the hook_print_link() call. + * @param array $args + * Array of optional arguments: + * - node: node object, to be used in checking node access. If the path + * argument is not provided, the path used will be node/nid. + * - path: path to be used in the link. If not specified, the current URL + * is used. + * - location: the location in the page where the link is being inserted + * ('link', 'corner', 'block', 'help'). + * + * @return string + * string with the HTML link to the printer-friendly page + */ +function print_ui_insert_link($link, $args = array()) { + $node = isset($args['node']) ? $args['node'] : NULL; + $path = isset($args['path']) ? $args['path'] : NULL; + $location = isset($args['location']) ? $args['location'] : ''; + + if ($node !== NULL) { + $nid = $node->nid; + if ($path === NULL) { + $path = 'node/' . $nid; + } + $allowed_type = print_ui_link_allowed($link, array('node' => $node)); + } + else { + if ($path === NULL) { + $nid = preg_replace('!^node/([\d]+)!', '$1', $_GET['q']); + $path = $_GET['q']; + } + else { + $nid = NULL; + } + $allowed_type = print_ui_link_allowed($link, array('path' => $path)); + } + + if ($allowed_type) { + if ($nid !== NULL) { + if ($allowed_type === PRINT_UI_ALLOW_BOOK_LINK) { + $path = 'book/export/html/' . $nid; + } + else { + if (variable_get('print_' . $link['format'] . '_link_use_alias', PRINT_UI_LINK_USE_ALIAS_DEFAULT) && ($alias = drupal_lookup_path('alias', $path))) { + $path = $alias; + } + else { + $path = $nid; + } + } + $path = $link['path'] . '/' . $path; + $query = _print_ui_query_string_encode($_GET, array('q')); + } + else { + $query = NULL; + } + drupal_add_css(drupal_get_path('module', 'print_ui') . '/css/print_ui.theme.css'); + $format = theme('print_ui_format_link', array('format' => $link['format'], 'location' => $location)); + return '' . l($format['text'], $path, array('attributes' => $format['attributes'], 'query' => $query, 'absolute' => TRUE, 'html' => $format['html'])) . ''; + } + else { + return FALSE; + } +} + +/** + * Check if the link to the PF version is allowed depending on the settings + * + * @param array $link + * array returned by the hook_print_link() call. + * @param array $args + * array containing the possible parameters: + * view_mode, node, type, path + * + * @return + * FALSE if not allowed + * PRINT_UI_ALLOW_NORMAL_LINK if a normal link is allowed + * PRINT_UI_ALLOW_BOOK_LINK if a link is allowed in a book node + */ +function print_ui_link_allowed($link, $args) { + if (isset($args['view_mode'])) { + $view_mode = $args['view_mode']; + if ((($view_mode == 'teaser') && !variable_get('print_' . $link['format'] . '_link_teaser', PRINT_UI_LINK_TEASER_DEFAULT)) + || !in_array($view_mode, array('full', 'teaser'))) { + // If the teaser link is disabled + return FALSE; + } + } + $link_allowed_func = $link['module'] . '_link_allowed'; + if (function_exists($link_allowed_func)) { + if (!$link_allowed_func($args)) { + // If the format-specific function disallows the link + 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 + if (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[$link['format']][$node->nid])) { + $res[$link['format']][$node->nid] = db_query("SELECT comments FROM {" . $link['module'] . "_node_conf} WHERE nid = :nid", array(':nid' => $node->nid))->fetchField(); + } + $display_comment = ($res && ($res[$link['format']][$node->nid] !== FALSE)) ? $res[$link['format']][$node->nid] : variable_get('print_' . $link['format'] . '_display_comment_' . $node_type, PRINT_UI_TYPE_COMMENT_LINK_DEFAULT); + if ($display_comment) { + return PRINT_UI_ALLOW_NORMAL_LINK; + } + } + else { + // Node link + $display = 'print_' . $link['format'] . '_display'; + if (isset($node->{$display}) && !$node->{$display}) { + // Link for this node is disabled + return FALSE; + } + elseif (isset($node->book)) { + // Node is a book; + $book_link = variable_get('print_' . $link['format'] . '_book_link', PRINT_UI_BOOK_LINK_DEFAULT); + switch ($book_link) { + case 1: + if (user_access('access printer-friendly version')) { + return PRINT_UI_ALLOW_BOOK_LINK; + } + break; + case 2: + return PRINT_UI_ALLOW_NORMAL_LINK; + } + } + else { + return PRINT_UI_ALLOW_NORMAL_LINK; + } + } + } + else { + // 'System' page + $sys_link_visibility = variable_get('print_' . $link['format'] . '_sys_link_visibility', PRINT_UI_SYS_LINK_VISIBILITY_DEFAULT); + $sys_link_pages = variable_get('print_' . $link['format'] . '_sys_link_pages', PRINT_UI_SYS_LINK_PAGES_DEFAULT); + + return _print_ui_page_match($sys_link_visibility, $_GET['q'], $sys_link_pages); + } + return FALSE; +} + +/** + * Check if the provided page is enabled according to the visibility settings + * + * @param int $visibility + * current visibility settings: + * 0 for show on every page except the listed pages + * 1 for show on only the listed pages + * @param string $path + * current path + * @param string $pages + * list of pages + * + * @return bool + * TRUE if it is enabled, FALSE otherwise + */ +function _print_ui_page_match($visibility, $path, $pages) { + if ($pages) { + if ($visibility == 2) { + if (module_exists('php')) { + return php_eval($pages); + } + else { + return FALSE; + } + } + $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; + } +} + +/** + * Parse an array into a valid urlencoded query string. + * + * Modified from drupal_query_string_encode to prevent re-encoding of + * encoded original. (see #301192) + * + * @param array $query + * The array to be processed e.g. $_GET + * @param array $exclude + * The array filled with keys to be excluded. + * @param string $parent + * The be used in recursive calls. + * + * @return string + * urlencoded string which can be appended to/as the URL query string + */ +function _print_ui_query_string_encode($query, $exclude = array(), $parent = '') { + $params = array(); + foreach ($query as $key => $value) { + if (in_array($key, $exclude, TRUE)) { + continue; + } + + if (is_array($value)) { + $params[$key] = _print_ui_query_string_encode($value, $exclude, $key); + } + else { + $params[$key] = $value; + } + } + + return empty($params) ? NULL : $params; +} diff --git a/sites/all/modules/contrib/admin/print/tests/print_basic.test b/sites/all/modules/contrib/admin/print/tests/print_basic.test index 795cca51..03068384 100644 --- a/sites/all/modules/contrib/admin/print/tests/print_basic.test +++ b/sites/all/modules/contrib/admin/print/tests/print_basic.test @@ -53,7 +53,7 @@ class PrintBasicTest extends DrupalWebTestCase { global $base_url, $base_root, $_print_urls; // Must require it, since this function gets called via Drupal's dynamic loading - require_once(DRUPAL_ROOT . '/' . drupal_get_path('module', 'print') . '/print.pages.inc'); + module_load_include('inc', 'print', 'print.pages'); variable_set('print_urls_anchors', 1); diff --git a/sites/all/modules/contrib/admin/rules_link/rules_link.admin.inc b/sites/all/modules/contrib/admin/rules_link/rules_link.admin.inc index 2a09f2f4..a1112eda 100644 --- a/sites/all/modules/contrib/admin/rules_link/rules_link.admin.inc +++ b/sites/all/modules/contrib/admin/rules_link/rules_link.admin.inc @@ -411,7 +411,7 @@ function rules_link_form_submit(&$form, &$form_state) { /** * Form function for the rules link components. */ -function rules_link_component_form($form, $form_state, $entity_type, $rules_link) { +function rules_link_component_form($form, &$form_state, $entity_type, $rules_link) { $form = array(); $form_state['rules_link'] = $rules_link; @@ -428,10 +428,16 @@ function rules_link_component_form($form, $form_state, $entity_type, $rules_link unset($form['condition_set']['negate']); $form['condition_set']['#tree'] = TRUE; - $rule_set = rules_link_load_rules_set($rules_link); $rule_set->form($form['rule_set'], $form_state, array('show settings' => TRUE)); + // Correct the state setup - default ruleset form doesn't expect this structure + $form['rule_set']['settings']['access']['permissions']['#states'] = array( + 'visible' => array( + ':input[name="rule_set[settings][access][access_exposed]"]' => array('checked' => TRUE), + ), + ); + $form['rule_set']['elements']['#caption'] = ''; $form['rule_set']['#tree'] = TRUE; @@ -492,6 +498,14 @@ function rules_link_component_form_submit(&$form, &$form_state) { $form_state['rules_link_rules_set']->save(rules_link_get_rules_set_name($form_state['rules_link']), 'rules_link'); } + // Save the permission matrix if access is exposed + if (isset($form_state['values']['rule_set']['settings']['access']) && !empty($form_state['values']['rule_set']['settings']['access']['access_exposed'])) { + // Save the permission matrix. + foreach ($form_state['values']['rule_set']['settings']['access']['permissions']['matrix']['checkboxes'] as $rid => $value) { + user_role_change_permissions($rid, $value); + } + } + // If an additional variable was added, then disable 'show link in entity'. if (count($rules_set_vars) > 1) { $form_state['rules_link']->settings['entity_link'] = FALSE; diff --git a/sites/all/modules/contrib/admin/rules_link/rules_link.info b/sites/all/modules/contrib/admin/rules_link/rules_link.info index f5be5775..c9c9803f 100644 --- a/sites/all/modules/contrib/admin/rules_link/rules_link.info +++ b/sites/all/modules/contrib/admin/rules_link/rules_link.info @@ -8,9 +8,9 @@ files[] = rules_link.views.inc files[] = rules_link.admin.inc files[] = rules_link.test -; Information added by drupal.org packaging script on 2013-10-01 -version = "7.x-1.0-beta5+0-dev" +; Information added by Drupal.org packaging script on 2014-08-27 +version = "7.x-1.1" core = "7.x" project = "rules_link" -datestamp = "1380626278" +datestamp = "1409148229" diff --git a/sites/all/modules/contrib/admin/rules_link/rules_link.module b/sites/all/modules/contrib/admin/rules_link/rules_link.module index 87596a76..ca631f5c 100644 --- a/sites/all/modules/contrib/admin/rules_link/rules_link.module +++ b/sites/all/modules/contrib/admin/rules_link/rules_link.module @@ -282,14 +282,14 @@ function rules_link_rules_link_delete($link) { function rules_link_get_token($content_id) { // Anonymous users get a less secure token, since it must be the same for all // anonymous users on the entire site to work with page caching. - return ($GLOBALS['user']->uid) ? drupal_get_token($content_id) : md5(drupal_get_private_key() . $content_id); + return ($GLOBALS['user']->uid) ? drupal_get_token($content_id) : drupal_hmac_base64($content_id, drupal_get_private_key() . drupal_get_hash_salt()); } /** * Checks if the given token is correct. */ function rules_link_check_token($token, $content_id) { - return rules_link_get_token($content_id) == $token; + return rules_link_get_token($content_id) === $token; } function rules_link_get_paramters($rules_link) { @@ -351,7 +351,7 @@ function rules_link_trigger_form($form, &$form_state, $rules_link, $entity_id) { '#type' => 'hidden', '#value' => $entity_id, ); - return confirm_form($form, $rules_link->getSettingTranslation('confirm_question'), '', $rules_link->getSettingTranslation('confirm_description')); + return confirm_form($form, filter_xss_admin($rules_link->getSettingTranslation('confirm_question')), '', filter_xss_admin($rules_link->getSettingTranslation('confirm_description'))); } /** @@ -470,7 +470,6 @@ function template_preprocess_rules_link(&$variables) { } $variables['href'] = check_plain(url($variables['href'], $variables['options'])); - $variables['title'] = check_plain($variables['title']); $variables['attr'] = drupal_attributes($variables['attr']); } diff --git a/sites/all/modules/contrib/admin/rules_link/rules_link_i18n.info b/sites/all/modules/contrib/admin/rules_link/rules_link_i18n.info index d57f8050..ef1f937d 100644 --- a/sites/all/modules/contrib/admin/rules_link/rules_link_i18n.info +++ b/sites/all/modules/contrib/admin/rules_link/rules_link_i18n.info @@ -5,9 +5,9 @@ dependencies[] = i18n_string package = Multilingual - Internationalization core = 7.x -; Information added by drupal.org packaging script on 2013-10-01 -version = "7.x-1.0-beta5+0-dev" +; Information added by Drupal.org packaging script on 2014-08-27 +version = "7.x-1.1" core = "7.x" project = "rules_link" -datestamp = "1380626278" +datestamp = "1409148229" diff --git a/sites/all/modules/contrib/dev/ctools/API.txt b/sites/all/modules/contrib/dev/ctools/API.txt index e0441d62..b698b798 100644 --- a/sites/all/modules/contrib/dev/ctools/API.txt +++ b/sites/all/modules/contrib/dev/ctools/API.txt @@ -3,6 +3,9 @@ Current API Version: 2.0.8 Please note that the API version is an internal number and does not match release numbers. It is entirely possible that releases will not increase the API version number, and increasing this number too often would burden contrib module maintainers who need to keep up with API changes. This file contains a log of changes to the API. +API Version 2.0.9 +Changed import permissions to use the new 'use ctools import' permission. + API Version 2.0.8 Introduce ctools_class_add(). Introduce ctools_class_remove(). diff --git a/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info b/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info index d27ea9ab..fd355450 100644 --- a/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info +++ b/sites/all/modules/contrib/dev/ctools/bulk_export/bulk_export.info @@ -3,10 +3,12 @@ description = Performs bulk exporting of data objects known about by Chaos tools core = 7.x dependencies[] = ctools package = Chaos tool suite +version = CTOOLS_MODULE_VERSION -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" + +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/css/modal.css b/sites/all/modules/contrib/dev/ctools/css/modal.css index d9f44e26..def374be 100644 --- a/sites/all/modules/contrib/dev/ctools/css/modal.css +++ b/sites/all/modules/contrib/dev/ctools/css/modal.css @@ -89,6 +89,10 @@ div.ctools-modal-content .form-checkboxes { clear: left; } +div.ctools-modal-content .vertical-tabs-panes > fieldset { + clear: none; +} + div.ctools-modal-content .resizable-textarea { width: auto; margin-left: 15em; diff --git a/sites/all/modules/contrib/dev/ctools/ctools.info b/sites/all/modules/contrib/dev/ctools/ctools.info index 8a7b0b60..3283454b 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools.info +++ b/sites/all/modules/contrib/dev/ctools/ctools.info @@ -2,13 +2,16 @@ name = Chaos tools description = A library of helpful tools by Merlin of Chaos. core = 7.x package = Chaos tool suite +version = CTOOLS_MODULE_VERSION files[] = includes/context.inc +files[] = includes/css-cache.inc files[] = includes/math-expr.inc files[] = includes/stylizer.inc +files[] = tests/css_cache.test -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/ctools.install b/sites/all/modules/contrib/dev/ctools/ctools.install index 1f961f15..e96c7432 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools.install +++ b/sites/all/modules/contrib/dev/ctools/ctools.install @@ -37,10 +37,22 @@ function ctools_requirements($phase) { } /** - * Implements hook_schemea + * Implements hook_schema(). */ function ctools_schema() { - return ctools_schema_2(); + return ctools_schema_3(); +} + +/** + * Version 3 of the CTools schema. + */ +function ctools_schema_3() { + $schema = ctools_schema_2(); + + // update the 'obj' field to be 128 bytes long: + $schema['ctools_object_cache']['fields']['obj']['length'] = 128; + + return $schema; } /** @@ -141,6 +153,21 @@ function ctools_schema_1() { return $schema; } +/** + * Implements hook_install(). + */ +function ctools_install() { + // Activate our custom cache handler for the CSS cache. + variable_set('cache_class_cache_ctools_css', 'CToolsCssCache'); +} + +/** + * Implements hook_uninstall(). + */ +function ctools_uninstall() { + variable_del('cache_class_cache_ctools_css'); +} + /** * Enlarge the ctools_object_cache.name column to prevent truncation and weird * errors. @@ -217,3 +244,22 @@ function ctools_update_6008() { ) ); } + +/** + * Enable the custom CSS cache handler. + */ +function ctools_update_7000() { + variable_set('cache_class_cache_ctools_css', 'CToolsCssCache'); +} + +/** + * Increase the length of the ctools_object_cache.obj column. + */ +function ctools_update_7001() { + db_change_field('ctools_object_cache', 'obj', 'obj', array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => TRUE, + 'description' => 'The type of the object this cache is attached to; this essentially represents the owner so that several sub-systems can use this cache.', + )); +} diff --git a/sites/all/modules/contrib/dev/ctools/ctools.module b/sites/all/modules/contrib/dev/ctools/ctools.module index f014e74d..3e8cc88f 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools.module +++ b/sites/all/modules/contrib/dev/ctools/ctools.module @@ -9,7 +9,21 @@ * must be implemented in the module file. */ -define('CTOOLS_API_VERSION', '2.0.7'); +define('CTOOLS_API_VERSION', '2.0.8'); + +/** + * The current working ctools version. + * + * In a release, it should be 7.x-1.x, which should match what drush make will + * create. In a dev format, it should be 7.x-1.(x+1)-dev, which will allow + * modules depending on new features in ctools to depend on ctools > 7.x-1.x. + * + * To define a specific version of CTools as a dependency for another module, + * simply include a dependency line in that module's info file, e.g.: + * ; Requires CTools v7.x-1.4 or newer. + * dependencies[] = ctools (>=1.4) + */ +define('CTOOLS_MODULE_VERSION', '7.x-1.7'); /** * Test the CTools API version. @@ -298,7 +312,7 @@ function ctools_break_phrase($str) { /** * Set a token/value pair to be replaced later in the request, specifically in - * ctools_preprocess_page(). + * ctools_page_token_processing(). * * @param $token * The token to be replaced later, during page rendering. This should @@ -367,6 +381,59 @@ function ctools_set_no_blocks($blocks = FALSE) { $status = $blocks; } +/** + * Wrapper function to create UUIDs via ctools, falls back on UUID module + * if it is enabled. This code is a copy of uuid.inc from the uuid module. + * @see http://php.net/uniqid#65879 + */ + +function ctools_uuid_generate() { + if (!module_exists('uuid')) { + ctools_include('uuid'); + + $callback = drupal_static(__FUNCTION__); + + if (empty($callback)) { + if (function_exists('uuid_create') && !function_exists('uuid_make')) { + $callback = '_ctools_uuid_generate_pecl'; + } + elseif (function_exists('com_create_guid')) { + $callback = '_ctools_uuid_generate_com'; + } + else { + $callback = '_ctools_uuid_generate_php'; + } + } + return $callback(); + } + else { + return uuid_generate(); + } +} + +/** + * Check that a string appears to be in the format of a UUID. + * @see http://drupal.org/project/uuid + * + * @param $uuid + * The string to test. + * + * @return + * TRUE if the string is well formed. + */ +function ctools_uuid_is_valid($uuid = '') { + if (empty($uuid)) { + return FALSE; + } + if (function_exists('uuid_is_valid') || module_exists('uuid')) { + return uuid_is_valid($uuid); + } + else { + ctools_include('uuid'); + return uuid_is_valid($uuid); + } +} + /** * Add an array of classes to the body. * @@ -483,6 +550,19 @@ function ctools_menu() { return $items; } +/** + * Implements hook_permission(). + */ +function ctools_permission() { + return array( + 'use ctools import' => array( + 'title' => t('Use CTools importer'), + 'description' => t('The import functionality allows users to execute arbitrary PHP code, so extreme caution must be taken.'), + 'restrict access' => TRUE, + ), + ); +} + /** * Implementation of hook_cron. Clean up old caches. */ @@ -493,19 +573,12 @@ function ctools_cron() { } /** - * Ensure the CTools CSS cache is flushed whenever hook_flush_caches is invoked. + * Implements hook_flush_caches(). */ function ctools_flush_caches() { - // Do not actually flush caches if running on cron. Drupal uses this hook - // in an inconsistent fashion and it does not necessarily mean to *flush* - // caches when running from cron. Instead it's just getting a list of cache - // tables and may not do any flushing. - if (!empty($GLOBALS['locks']['cron'])) { - return; - } - - ctools_include('css'); - ctools_css_flush_caches(); + // Only return the CSS cache bin if it has been activated, to avoid + // drupal_flush_all_caches() from trying to truncate a non-existing table. + return variable_get('cache_class_cache_ctools_css', FALSE) ? array('cache_ctools_css') : array(); } /** @@ -585,7 +658,26 @@ function ctools_preprocess_node(&$vars) { } } + +/** + * Implements hook_page_alter(). + * + * Last ditch attempt to remove sidebar regions if the "no blocks" + * functionality has been activated. + * + * @see ctools_block_list_alter(). + */ function ctools_page_alter(&$page) { + $check = drupal_static('ctools_set_no_blocks', TRUE); + if (!$check) { + foreach ($page as $region_id => $region) { + // @todo -- possibly we can set configuration for this so that users can + // specify which blocks will not get rendered. + if (strpos($region_id, 'sidebar') !== FALSE) { + unset($page[$region_id]); + } + } + } $page['#post_render'][] = 'ctools_page_token_processing'; } @@ -601,15 +693,15 @@ function ctools_page_token_processing($children, $elements) { list($type, $argument) = $key; switch ($type) { case 'variable': - $tokens[$token] = isset($variables[$argument]) ? $variables[$argument] : ''; + $tokens[$token] = isset($elements[$argument]) ? $elements[$argument] : ''; break; case 'callback': if (is_string($argument) && function_exists($argument)) { - $tokens[$token] = $argument($variables); + $tokens[$token] = $argument($elements); } if (is_array($argument) && function_exists($argument[0])) { $function = array_shift($argument); - $argument = array_merge(array(&$variables), $argument); + $argument = array_merge(array(&$elements), $argument); $tokens[$token] = call_user_func_array($function, $argument); } break; @@ -733,6 +825,15 @@ function ctools_js_load($js) { return 0; } +/** + * Provides the default value for %ctools_js. + * + * This allows drupal_valid_path() to work with %ctools_js. + */ +function ctools_js_to_arg($arg) { + return empty($arg) || $arg == '%' ? 'nojs' : $arg; +} + /** * Menu _load hook. * @@ -852,11 +953,25 @@ function ctools_block_list_alter(&$blocks) { } /** - * Implement hook_modules_enabled to clear static caches for detecting new plugins + * Implements hook_modules_enabled(). + * + * Clear caches for detecting new plugins. */ function ctools_modules_enabled($modules) { ctools_include('plugins'); ctools_get_plugins_reset(); + cache_clear_all('ctools_plugin_files:', 'cache', TRUE); +} + +/** + * Implements hook_modules_disabled(). + * + * Clear caches for removing disabled plugins. + */ +function ctools_modules_disabled($modules) { + ctools_include('plugins'); + ctools_get_plugins_reset(); + cache_clear_all('ctools_plugin_files:', 'cache', TRUE); } /** diff --git a/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info b/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info index 10192538..d7ec175d 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_access_ruleset/ctools_access_ruleset.info @@ -2,11 +2,12 @@ name = Custom rulesets description = Create custom, exportable, reusable access rulesets for applications like Panels. core = 7.x package = Chaos tool suite +version = CTOOLS_MODULE_VERSION dependencies[] = ctools -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info b/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info index 03ccb341..bc1a213d 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_ajax_sample/ctools_ajax_sample.info @@ -1,12 +1,13 @@ name = Chaos Tools (CTools) AJAX Example description = Shows how to use the power of Chaos AJAX. package = Chaos tool suite +version = CTOOLS_MODULE_VERSION dependencies[] = ctools core = 7.x -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info b/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info index d9c45673..2b2d04bb 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.info @@ -2,11 +2,12 @@ name = Custom content panes description = Create custom, exportable, reusable content panes for applications like Panels. core = 7.x package = Chaos tool suite +version = CTOOLS_MODULE_VERSION dependencies[] = ctools -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.module b/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.module index a2e8ee24..3e316a91 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.module +++ b/sites/all/modules/contrib/dev/ctools/ctools_custom_content/ctools_custom_content.module @@ -36,6 +36,26 @@ function ctools_custom_content_ctools_plugin_directory($module, $plugin) { } } +/** + * Implements hook_get_pane_links_alter(). + */ +function ctools_custom_content_get_pane_links_alter(&$links, $pane, $content_type) { + if ($pane->type == 'custom') { + if(!isset($pane->configuration['name'])) { + $name_of_pane = $pane->subtype; + } + else { + $name_of_pane = $pane->configuration['name']; + } + + $links['top']['edit_custom_content'] = array( + 'title' => t('Edit custom content pane'), + 'href' => url('admin/structure/ctools-content/list/' . $name_of_pane . '/edit', array('absolute' => TRUE)), + 'attributes' => array('target' => array('_blank')), + ); + } +} + /** * Create callback for creating a new CTools custom content type. * diff --git a/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info b/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info index e4fa5343..f9158762 100644 --- a/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info +++ b/sites/all/modules/contrib/dev/ctools/ctools_plugin_example/ctools_plugin_example.info @@ -1,15 +1,16 @@ name = Chaos Tools (CTools) Plugin Example description = Shows how an external module can provide ctools plugins (for Panels, etc.). package = Chaos tool suite +version = CTOOLS_MODULE_VERSION dependencies[] = ctools dependencies[] = panels dependencies[] = page_manager dependencies[] = advanced_help core = 7.x -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/help/context-content.html b/sites/all/modules/contrib/dev/ctools/help/context-content.html index 8af5df43..c1c6a356 100644 --- a/sites/all/modules/contrib/dev/ctools/help/context-content.html +++ b/sites/all/modules/contrib/dev/ctools/help/context-content.html @@ -116,6 +116,10 @@ The first form will always have required configuration added to it. These forms
required context [Optional]
Either a ctools_context_required or ctools_context_optional or array of contexts for this content. If omitted, no contexts are used.
+ +
create content access [Optional]
+ +
An optional callback to determine if a user can access this subtype. The callback will receive two arguments, the type and subtype.

Rendered content

diff --git a/sites/all/modules/contrib/dev/ctools/help/export.html b/sites/all/modules/contrib/dev/ctools/help/export.html index 3a774e82..ce24cad9 100644 --- a/sites/all/modules/contrib/dev/ctools/help/export.html +++ b/sites/all/modules/contrib/dev/ctools/help/export.html @@ -156,6 +156,9 @@ function mymodule_schema() {
to hook code callback
Function used to generate an export for the bulk export process. This is only necessary if the export is more complicated than simply listing the fields. Defaults to $module . '_' . $table . '_to_hook_code'. +
boolean
+
Explicitly indicate if a table field contains a boolean or not. The Schema API does not model the +difference between a tinyint and a boolean type. Boolean values are stored in tinyint fields. This may cause mismatch errors when exporting a non-boolean value from a tinyint field. Add this to a tinyint field if it contains boolean data and can be exported. Defaults to TRUE.
create callback
CRUD callback to use to create a new exportable item in memory. If not provided, the default function will be used. The single argument is a boolean used to determine if defaults should be set on the object. This object will not be written to the database by this callback.
diff --git a/sites/all/modules/contrib/dev/ctools/help/plugins-creating.html b/sites/all/modules/contrib/dev/ctools/help/plugins-creating.html index 29a9014f..23237058 100644 --- a/sites/all/modules/contrib/dev/ctools/help/plugins-creating.html +++ b/sites/all/modules/contrib/dev/ctools/help/plugins-creating.html @@ -24,6 +24,17 @@ The following information can be specified for each plugin type:
cache table
Defaults to: 'cache'
If 'cache' is TRUE, then this value specifies the cache table where the cached plugin information will be stored.
+
classes
+
Defaults to: array()
+
An array of class identifiers(i.e. plugin array keys) which a plugin of this type uses to provide classes to the CTools autoloader. For example, if classes is set to array('class'), then CTools will search each $plugin['class'] for a class to autoload. Depending of the plugin structure, a class identifier may be either:
+
+
- a file name:
+
the file which holds the class with the name structure as: [filename].[class].php
+
in this case the class name can be different than the class identifier
+
- the class name:
+
if the class is in the same file as the $plugin
+
the plugin .inc file can have a different name than the class identifier
+
defaults
Defaults to: array()
An array of defaults that should be added to each plugin; this can be used to ensure that every plugin has the basic data necessary. These defaults will not ovewrite data supplied by the plugin. This could also be a function name, in which case the callback will be used to provide defaults. NOTE, however, that the callback-based approach is deprecated as it is redundant with the 'process' callback, and as such will be removed in later versions. Consequently, you should only use the array form for maximum cross-version compatibility.
diff --git a/sites/all/modules/contrib/dev/ctools/includes/ajax.inc b/sites/all/modules/contrib/dev/ctools/includes/ajax.inc index bb17bea2..96f5068f 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/ajax.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/ajax.inc @@ -49,6 +49,34 @@ function ctools_ajax_text_button($text, $dest, $alt, $class = '', $type = 'use-a return l($text, $dest, array('html' => TRUE, 'attributes' => array('class' => array($type, $class), 'title' => $alt))); } +/** + * Render an icon and related text as a link. This will automatically apply an AJAX class + * to the link and add the appropriate javascript to make this happen. + * + * Note: 'html' => true so be sure any text is vetted! Chances are these kinds of buttons will + * not use user input so this is a very minor concern. + * + * @param $text + * The text that will be displayed as the link. + * @param $image + * The icon image to include in the link. + * @param $dest + * The destination of the link. + * @param $alt + * The title text of the link. + * @param $class + * Any class to apply to the link. @todo this should be a options array. + * @param $type + * A type to use, in case a different behavior should be attached. Defaults + * to ctools-use-ajax. + */ +function ctools_ajax_icon_text_button($text, $image, $dest, $alt, $class = '', $type = 'use-ajax') { + drupal_add_library('system', 'drupal.ajax'); + $rendered_image = theme('image', array('path' => $image)); + $link_content = $rendered_image . "" . $text . ""; + return l($link_content, $dest, array('html' => TRUE, 'attributes' => array('class' => array($type, $class), 'title' => $alt))); +} + /** * Set a single property to a value, on all matched elements. * diff --git a/sites/all/modules/contrib/dev/ctools/includes/content.inc b/sites/all/modules/contrib/dev/ctools/includes/content.inc index 890ec23a..b4660b43 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/content.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/content.inc @@ -244,6 +244,7 @@ function ctools_content_prepare_subtype(&$subtype, $plugin) { * The content as rendered by the plugin. This content should be an array * with the following possible keys: * - title: The safe to render title of the content. + * - title_heading: The title heading. * - content: The safe to render HTML content. * - links: An array of links associated with the content suitable for * theme('links'). @@ -299,6 +300,7 @@ function ctools_content_render($type, $subtype, $conf, $keywords = array(), $arg $keywords['%title'] = empty($content->title) ? '' : $content->title; $content->original_title = $keywords['%title']; $content->title = $conf['override_title_text']; + $content->title_heading = isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2'; } if (!empty($content->title)) { @@ -504,8 +506,26 @@ function ctools_content_configure_form_defaults($form, &$form_state) { '#size' => 35, '#id' => 'override-title-textfield', '#dependency' => array('override-title-checkbox' => array(1)), - '#dependency_type' => 'disable', + '#dependency_type' => 'hidden', ); + $form['override_title_heading'] = array( + '#type' => 'select', + '#default_value' => isset($conf['override_title_heading']) ? $conf['override_title_heading'] : 'h2', + '#options' => array( + 'h1' => t('h1'), + 'h2' => t('h2'), + 'h3' => t('h3'), + 'h4' => t('h4'), + 'h5' => t('h5'), + 'h6' => t('h6'), + 'div' => t('div'), + 'span' => t('span'), + ), + '#id' => 'override-title-heading', + '#dependency' => array('override-title-checkbox' => array(1)), + '#dependency_type' => 'hidden', + ); + $form['aligner_stop'] = array( '#markup' => '', ); @@ -536,6 +556,7 @@ function ctools_content_configure_form_defaults_submit(&$form, &$form_state) { if (isset($form_state['values']['override_title'])) { $form_state['conf']['override_title'] = $form_state['values']['override_title']; $form_state['conf']['override_title_text'] = $form_state['values']['override_title_text']; + $form_state['conf']['override_title_heading'] = $form_state['values']['override_title_heading']; } } @@ -687,6 +708,11 @@ function ctools_content_get_available_types($contexts = NULL, $has_content = FAL } } + // Check if the content type provides an access callback. + if (isset($subtype['create content access']) && function_exists($subtype['create content access']) && !$subtype['create content access']($plugin, $subtype)) { + continue; + } + // If we made it through all the tests, then we can use this content. $available[$id][$subtype_id] = $subtype; } diff --git a/sites/all/modules/contrib/dev/ctools/includes/content.menu.inc b/sites/all/modules/contrib/dev/ctools/includes/content.menu.inc index 93884fce..f7f93406 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/content.menu.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/content.menu.inc @@ -23,68 +23,157 @@ function ctools_content_menu(&$items) { /** * Helper function for autocompletion of entity titles. */ -function ctools_content_autocomplete_entity($type, $string = '') { - $entity = entity_get_info($type); +function ctools_content_autocomplete_entity($entity_type, $string = '') { if ($string != '') { - // @todo verify the query logic here, it's untested. - // Set up the query - $query = db_select($entity['base table'], 'b'); - if ($entity['entity keys']['label']) { - $query->fields('b', array($entity['entity keys']['id'], $entity['entity keys']['label']))->range(0, 10); - } - else { - $query->fields('b', array($entity['entity keys']['id']))->range(0, 10); + $entity_info = entity_get_info($entity_type); + + if (!module_exists('entity')) { + module_load_include('inc', 'ctools', 'includes/entity-access'); + _ctools_entity_access($entity_info, $entity_type); } + // We must query all ids, because if every one of the 10 don't have access + // the user may never be able to autocomplete a node title. $preg_matches = array(); + $matches = array(); $match = preg_match('/\[id: (\d+)\]/', $string, $preg_matches); if (!$match) { $match = preg_match('/^id: (\d+)/', $string, $preg_matches); } + // If an ID match was found, use that ID rather than the whole string. if ($match) { - $query->condition('b.' . $entity['entity keys']['id'], $preg_matches[1]); - } - elseif ($entity['entity keys']['label']) { - $query->condition('b.' . $entity['entity keys']['label'], '%' . db_like($string) . '%', 'LIKE'); - } - - $matches = array(); - if ($type == 'node') { - if (!user_access('bypass node access')) { - // If the user is able to view their own unpublished nodes, allow them - // to see these in addition to published nodes. - if (user_access('view own unpublished content')) { - $query->condition(db_or() - ->condition('b.status', NODE_PUBLISHED) - ->condition('b.uid', $GLOBALS['user']->uid) - ); - } - else { - // If not, restrict the query to published nodes. - $query->condition('b.status', NODE_PUBLISHED); - } - } - - $query->addTag('node_access'); - $query->join('users', 'u', 'b.uid = u.uid'); - $query->addField('u', 'name', 'name'); - - foreach ($query->execute() as $nodeish) { - $name = empty($nodeish->name) ? variable_get('anonymous', t('Anonymous')) : check_plain($nodeish->name); - $matches[$nodeish->title . " [id: $nodeish->nid]"] = '' . check_plain($nodeish->title) . ' (' . t('by @user', array('@user' => $name)) . ')'; - } + $entity_id = $preg_matches[1]; + $results = _ctools_getReferencableEntities($entity_type, $entity_info, $entity_id, '=', 1); } else { - foreach ($query->execute() as $item) { - $id = $item->{$entity['entity keys']['id']}; - if ($entity['entity keys']['label']) { - $matches[$item->{$entity['entity keys']['label']} . " [id: $id]"] = '' . check_plain($item->{$entity['entity keys']['label']}) . ''; - } - else { - $matches["[id: $id]"] = '' . check_plain($item->{$entity['entity keys']['id']}) . ''; - } + // We cannot find results if the entity doesn't have a label to search. + if (!isset($entity_info['entity keys']['label'])) { + drupal_json_output(array("[id: NULL]" => '' . t('Entity Type !entity_type does not support autocomplete search.', array('!entity_type' => $entity_type)) . '')); + return; } + $results = _ctools_getReferencableEntities($entity_type, $entity_info, $string, 'LIKE', 10); } + foreach ($results as $entity_id => $result) { + $matches[$result['label'] . " [id: $entity_id]"] = '' . check_plain($result['label']) . ''; + $matches[$result['label'] . " [id: $entity_id]"] .= isset($result['bundle']) ? ' (' . check_plain($result['bundle']) . ')' : ''; + } + drupal_json_output($matches); } } + +/* + * Use well known/tested entity reference code to build our search query + * From EntityReference_SelectionHandler_Generic class + */ +function _ctools_buildQuery($entity_type, $entity_info, $match = NULL, $match_operator = 'CONTAINS') { + $base_table = $entity_info['base table']; + $label_key = $entity_info['entity keys']['label']; + $query = db_select($base_table) + ->fields($base_table, array($entity_info['entity keys']['id'])); + + if (isset($match)) { + if (isset($label_key)) { + $query->condition($base_table . '.' . $label_key, '%' . $match . '%', $match_operator); + } + // This should never happen, but double check just in case. + else { + return array(); + } + } + // Add a generic entity access tag to the query. + $query->addTag('ctools'); + + // We have to perform two checks. First check is a query alter (with tags) + // in an attempt to only return results that have access. However, this is + // not full-proof since entities many not implement hook_access query tag. + // This is why we have a second check after entity load, before we display + // the label of an entity. + if ($entity_type == 'comment') { + // Adding the 'comment_access' tag is sadly insufficient for comments: core
 + // requires us to also know about the concept of 'published' and
 + // 'unpublished'.
 + if (!user_access('administer comments')) { + $query->condition('comment.status', COMMENT_PUBLISHED); + } + + // Join to a node if the user does not have node access bypass permissions
 + // to obey node published permissions
 + if (!user_access('bypass node access')) { + $node_alias = $query->innerJoin('node', 'n', '%alias.nid = comment.nid'); + $query->condition($node_alias . '.status', NODE_PUBLISHED); + } + $query->addTag('node_access'); + } + else { + $query->addTag($entity_type . '_access'); + } + + // Add the sort option. + if (isset($label_key)) { + $query->orderBy($base_table . '.' . $label_key, 'ASC'); + } + + return $query; +} + +/** + * Private function to get referencable entities. Based on code from the + * Entity Reference module. + */ +function _ctools_getReferencableEntities($entity_type, $entity_info, $match = NULL, $match_operator = 'LIKE', $limit = 0) { + global $user; + $account = $user; + $options = array(); + // We're an entity ID, return the id + if (is_numeric($match) && $match_operator == '=') { + if ($entity = array_shift(entity_load($entity_type, array($match)))) { + if (isset($entity_info['access callback']) && function_exists($entity_info['access callback'])) { + if ($entity_info['access callback']('view', $entity, $account, $entity_type)) { + $label = entity_label($entity_type, $entity); + return array( + $match => array( + 'label' => !empty($label) ? $label : $entity->{$entity_info['entity keys']['id']}, + 'bundle' => !empty($entity_info['entity keys']['bundle']) ? check_plain($entity->{$entity_info['entity keys']['bundle']}) : NULL, + ), + ); + } + } + } + // If you don't have access, or an access callback or a valid entity, just + // Return back the Entity ID. + return array( + $match => array( + 'label' => $match, + 'bundle' => NULL, + ), + ); + } + + // We have matches, build a query to fetch the result. + if ($query = _ctools_buildQuery($entity_type, $entity_info, $match, $match_operator)) { + if ($limit > 0) { + $query->range(0, $limit); + } + + $results = $query->execute(); + + if (!empty($results)) { + foreach ($results as $record) { + $entities = entity_load($entity_type, array($record->{$entity_info['entity keys']['id']})); + $entity = array_shift($entities); + if (isset($entity_info['access callback']) && function_exists($entity_info['access callback'])) { + if ($entity_info['access callback']('view', $entity, $account, $entity_type)) { + $label = entity_label($entity_type, $entity); + $options[$record->{$entity_info['entity keys']['id']}] = array( + 'label' => !empty($label) ? $label : $entity->{$entity_info['entity keys']['id']}, + 'bundle' => !empty($entity_info['entity keys']['bundle']) ? check_plain($entity->{$entity_info['entity keys']['bundle']}) : NULL, + ); + } + } + } + } + return $options; + } + return array(); +} diff --git a/sites/all/modules/contrib/dev/ctools/includes/context-admin.inc b/sites/all/modules/contrib/dev/ctools/includes/context-admin.inc index 7e5cd02b..11205474 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/context-admin.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/context-admin.inc @@ -376,11 +376,11 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke 'path' => "ctools/context/ajax/add/$mechanism/$type/$cache_key/$name/%step", 'show cancel' => TRUE, 'default form' => 'ctools_edit_context_form_defaults', - 'auto caching' => TRUE, + 'auto cache' => TRUE, 'cache mechanism' => $mechanism, 'cache key' => $cache_key, // This is stating what the cache will be referred to in $form_state - 'cache storage' => 'object', + 'cache location' => 'object', ); if ($type == 'requiredcontext') { @@ -416,12 +416,20 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke ctools_cache_operation($mechanism, $cache_key, 'finalize', $object); // Very irritating way to update the form for our contexts. - $arg_form_state = array('values' => array()); + $arg_form_state = form_state_defaults() + array( + 'values' => array(), + 'process_input' => FALSE, + 'complete form' => array(), + ); + + $rel_form_state = $arg_form_state; $arg_form = array( '#post' => array(), '#programmed' => FALSE, '#tree' => FALSE, + '#parents' => array(), + '#array_parents' => array(), ); // Build a chunk of the form to merge into the displayed form @@ -446,6 +454,8 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke '#post' => array(), '#programmed' => FALSE, '#tree' => FALSE, + '#parents' => array(), + '#array_parents' => array(), ); $rel_form['relationship'] = array( @@ -460,7 +470,7 @@ function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_ke $output = array(); if (!empty($available_relationships)) { ctools_context_add_item_table_buttons('relationship', $mechanism, $rel_form, $available_relationships); - $rel_form = form_builder('dummy_form_id', $rel_form, $arg_form_state); + $rel_form = form_builder('dummy_form_id', $rel_form, $rel_form_state); $output[] = ajax_command_replace('div#ctools-relationships-table div.buttons', drupal_render($rel_form)); } @@ -551,11 +561,11 @@ function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_k 'path' => "ctools/context/ajax/configure/$mechanism/$type/$cache_key/$position/%step", 'show cancel' => TRUE, 'default form' => 'ctools_edit_context_form_defaults', - 'auto caching' => TRUE, + 'auto cache' => TRUE, 'cache mechanism' => $mechanism, 'cache key' => $cache_key, // This is stating what the cache will be referred to in $form_state - 'cache storage' => 'object', + 'cache location' => 'object', ); if ($type == 'requiredcontext') { @@ -582,8 +592,16 @@ function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_k $output = array(); $output[] = ctools_modal_command_dismiss(); + $arg_form_state = form_state_defaults() + array( + 'values' => array(), + 'process_input' => FALSE, + 'complete form' => array(), + ); + $arg_form = array( '#post' => array(), + '#parents' => array(), + '#array_parents' => array(), '#programmed' => FALSE, '#tree' => FALSE, ); diff --git a/sites/all/modules/contrib/dev/ctools/includes/context-task-handler.inc b/sites/all/modules/contrib/dev/ctools/includes/context-task-handler.inc index 37aa6df0..21ceea5d 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/context-task-handler.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/context-task-handler.inc @@ -161,7 +161,7 @@ function ctools_context_handler_render_handler($task, $subtask, $handler, $conte 'query' => $info['query'], 'fragment' => $info['fragment'], ); - return drupal_goto($info['destination'], $options, $info['response code']); + drupal_goto($info['destination'], $options, $info['response code']); // @todo -- should other response codes be supported here? } } diff --git a/sites/all/modules/contrib/dev/ctools/includes/context.inc b/sites/all/modules/contrib/dev/ctools/includes/context.inc index 93be748f..6628b5f9 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/context.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/context.inc @@ -169,7 +169,12 @@ class ctools_context_required { function select($contexts, $context) { if (!is_array($contexts)) { - $contexts = array($contexts); + if (is_object($contexts) && $contexts instanceof ctools_context) { + $contexts = array($contexts->id => $contexts); + } + else { + $contexts = array($contexts); + } } // If we had requested a $context but that $context doesn't exist @@ -328,13 +333,15 @@ function _ctools_context_selector($contexts, $required, $default, $num = 0) { $title = $num ? t('Context %count', array('%count' => $num)) : t('Context'); } - return array( + $form = array( '#type' => 'select', '#options' => $options, '#title' => $title, '#default_value' => $default, ); } + + return $form; } /** @@ -1400,8 +1407,7 @@ function ctools_get_relevant_access_plugins($contexts) { * Create a context for the logged in user. */ function ctools_access_get_loggedin_context() { - global $user; - $context = ctools_context_create('entity:user', $user); + $context = ctools_context_create('entity:user', array('type' => 'current'), TRUE); $context->identifier = t('Logged in user'); $context->keyword = 'viewer'; $context->id = 0; @@ -1588,7 +1594,9 @@ function ctools_access_add_restrictions($settings, $contexts) { $required_context = isset($plugin['required context']) ? $plugin['required context'] : array(); $context = isset($test['context']) ? $test['context'] : array(); $contexts = ctools_context_select($contexts, $required_context, $context); - $function($test['settings'], $contexts); + if ($contexts !== FALSE) { + $function($test['settings'], $contexts); + } } } } diff --git a/sites/all/modules/contrib/dev/ctools/includes/css-cache.inc b/sites/all/modules/contrib/dev/ctools/includes/css-cache.inc new file mode 100644 index 00000000..d88160b5 --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/includes/css-cache.inc @@ -0,0 +1,52 @@ +key(array('cid' => $id)) ->fields(array( - 'cid' => $id, 'filename' => $filename, 'css' => $css, 'filter' => intval($filter), diff --git a/sites/all/modules/contrib/dev/ctools/includes/entity-access.inc b/sites/all/modules/contrib/dev/ctools/includes/entity-access.inc new file mode 100644 index 00000000..972cf13b --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/includes/entity-access.inc @@ -0,0 +1,150 @@ +nid); + if ($node->vid !== $default_revision->vid) { + return _node_revision_access($node, $op, $account); + } + else { + return node_access($op, $node, $account); + } + } + // No node is provided. Check for access to all nodes. + if (user_access('bypass node access', $account)) { + return TRUE; + } + if (!user_access('access content', $account)) { + return FALSE; + } + if ($op == 'view' && node_access_view_all_nodes($account)) { + return TRUE; + } + return FALSE; +} + +/** + * Access callback for the user entity. + */ +function ctools_metadata_user_access($op, $entity = NULL, $account = NULL, $entity_type) { + $account = isset($account) ? $account : $GLOBALS['user']; + // Grant access to the users own user account and to the anonymous one. + if (isset($entity) && $op != 'delete' && (($entity->uid == $account->uid && $entity->uid) || (!$entity->uid && $op == 'view'))) { + return TRUE; + } + if (user_access('administer users', $account) || user_access('access user profiles', $account) && $op == 'view' && $entity->status) { + return TRUE; + } + return FALSE; +} + +/** + * Access callback for the comment entity. + */ +function ctools_metadata_comment_access($op, $entity = NULL, $account = NULL) { + // When determining access to a comment, if comment has an associated node, + // the user must be able to view the node in order to access the comment. + if (isset($entity->nid)) { + if (!node_access('view', node_load($entity->nid), $account)) { + return FALSE; + } + } + + // Comment administrators are allowed to perform all operations on all + // comments. + if (user_access('administer comments', $account)) { + return TRUE; + } + + // Unpublished comments can never be accessed by non-admins. + if (isset($entity->status) && $entity->status == COMMENT_NOT_PUBLISHED) { + return FALSE; + } + + if (user_access('access comments', $account) && $op == 'view') { + return TRUE; + } + return FALSE; +} + +/** + * Access callback for the taxonomy entities. + */ +function ctools_metadata_taxonomy_access($op, $entity = NULL, $account = NULL, $entity_type) { + if ($entity_type == 'taxonomy_vocabulary') { + return user_access('administer taxonomy', $account); + } + if (user_access('administer taxonomy', $account) || user_access('access content', $account) && $op == 'view') { + return TRUE; + } + return FALSE; +} diff --git a/sites/all/modules/contrib/dev/ctools/includes/export.inc b/sites/all/modules/contrib/dev/ctools/includes/export.inc index 0b2ef46d..0b85c2ef 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/export.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/export.inc @@ -945,7 +945,13 @@ function ctools_export_object($table, $object, $indent = '', $identifier = NULL, else { $value = $object->$field; if ($info['type'] == 'int') { - $value = (isset($info['size']) && $info['size'] == 'tiny') ? (bool) $value : (int) $value; + if (isset($info['size']) && $info['size'] == 'tiny') { + $info['boolean'] = (!isset($info['boolean'])) ? $schema['export']['boolean'] : $info['boolean']; + $value = ($info['boolean']) ? (bool) $value : (int) $value; + } + else { + $value = (int) $value; + } } $output .= $indent . '$' . $identifier . '->' . $field . ' = ' . ctools_var_export($value, $indent) . ";\n"; @@ -967,7 +973,12 @@ function ctools_export_object($table, $object, $indent = '', $identifier = NULL, * that it's easily available. */ function ctools_export_get_schema($table) { - $cache = &drupal_static(__FUNCTION__); + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__); + } + $cache = &$drupal_static_fast['cache']; + if (empty($cache[$table])) { $schema = drupal_get_schema($table); @@ -1003,6 +1014,7 @@ function ctools_export_get_schema($table) { 'cache defaults' => FALSE, 'default cache bin' => 'cache', 'export type string' => 'type', + 'boolean' => TRUE, ); // If the export definition doesn't have the "primary key" then the CRUD diff --git a/sites/all/modules/contrib/dev/ctools/includes/fields.inc b/sites/all/modules/contrib/dev/ctools/includes/fields.inc index 162262c7..f379f5e9 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/fields.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/fields.inc @@ -79,6 +79,19 @@ function ctools_fields_get_field_formatter_settings_form($field, $formatter_type $instance = ctools_fields_fake_field_instance($field['field_name'], $view_mode, $formatter_type, $conf['formatter_settings']); $settings_form = $function($field, $instance, $view_mode, $form, $form_state); if ($settings_form) { + // Allow other modules to alter the formatter settings form. + $context = array( + 'module' => $formatter['module'], + 'formatter' => $formatter, + 'field' => $field, + 'instance' => $instance, + 'view_mode' => $view_mode, + 'form' => $form, + 'form_state' => $form_state, + ); + drupal_alter('field_formatter_settings_form', $settings_form, $context); + + $settings_form['#tree'] = TRUE; $form['ctools_field_list']['#value'][] = $field; $form += $settings_form; } diff --git a/sites/all/modules/contrib/dev/ctools/includes/modal.inc b/sites/all/modules/contrib/dev/ctools/includes/modal.inc index dfde0ac0..ee969aba 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/modal.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/modal.inc @@ -187,18 +187,32 @@ function ctools_modal_text_button($text, $dest, $alt, $class = '') { /** * Wrap a form so that we can use it properly with AJAX. Essentially if the * form wishes to render, it automatically does that, otherwise it returns - * so we can see submission results. + * the render array so we can see submission results. + + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * An associative array containing the current state of the form. + * If the 'reset_html_ids' key is set to TRUE, it will prevent HTML IDs in + * forms from being incremented. * - * @return + * @return mixed * The output of the form, if it was rendered. If $form_state['ajax'] * is set, this will use ctools_modal_form_render so it will be * a $command object suitable for ajax_render already. * - * The return will be NULL if the form was successfully submitted unless - * you specifically set re_render = TRUE. If ajax is set the - * form will never be redirected. + * If the form was not rendered, the raw render array will be returned. + * + * If ajax is set the form will never be redirected. */ function ctools_modal_form_wrapper($form_id, &$form_state) { + // Since this will run again on form rebuild while still in the modal, prevent + // form IDs from being incremented. + // @todo https://drupal.org/node/1305882 + if (!empty($form_state['reset_html_ids']) && !empty($_POST['ajax_html_ids'])) { + unset($_POST['ajax_html_ids']); + } + // This won't override settings already in. $form_state += array( 're_render' => FALSE, @@ -206,7 +220,7 @@ function ctools_modal_form_wrapper($form_id, &$form_state) { ); $output = drupal_build_form($form_id, $form_state); - if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) { + if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) { return ctools_modal_form_render($form_state, $output); } diff --git a/sites/all/modules/contrib/dev/ctools/includes/plugins.inc b/sites/all/modules/contrib/dev/ctools/includes/plugins.inc index 0363fcb2..eadb68f7 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/plugins.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/plugins.inc @@ -214,7 +214,12 @@ function ctools_plugin_api_get_hook($owner, $api) { function ctools_get_plugins($module, $type, $id = NULL) { // Store local caches of plugins and plugin info so we don't have to do full // lookups everytime. - $plugins = &drupal_static('ctools_plugins', array()); + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['plugins'] = &drupal_static('ctools_plugins', array()); + } + $plugins = &$drupal_static_fast['plugins']; + $info = ctools_plugin_get_plugin_type_info(); // Bail out noisily if an invalid module/type combination is requested. @@ -343,8 +348,13 @@ function ctools_get_plugins($module, $type, $id = NULL) { * name and each inner array keyed on plugin type name. */ function ctools_plugin_get_plugin_type_info($flush = FALSE) { - $info_loaded = &drupal_static('ctools_plugin_type_info_loaded', FALSE); - $all_type_info = &drupal_static('ctools_plugin_type_info', array()); + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['info_loaded'] = &drupal_static('ctools_plugin_type_info_loaded', FALSE); + $drupal_static_fast['all_type_info'] = &drupal_static('ctools_plugin_type_info', array()); + } + $info_loaded = &$drupal_static_fast['info_loaded']; + $all_type_info = &$drupal_static_fast['all_type_info']; // Only trigger info loading once. if ($info_loaded && !$flush) { @@ -418,25 +428,15 @@ function ctools_plugin_load_includes($info, $filename = NULL) { // store static of plugin arrays for reference because they can't be reincluded. static $plugin_arrays = array(); - // If we're being asked for all plugins of a type, skip any caching - // we may have done because this is an admin task and it's ok to - // spend the extra time. - if (!isset($filename)) { - $all_files[$info['module']][$info['type']] = NULL; - } - if (!isset($all_files[$info['module']][$info['type']])) { - // If a filename was set, we will try to load our list of files from - // cache. This is considered normal operation and we try to reduce - // the time spent finding files. - if (isset($filename)) { - $cache = cache_get("ctools_plugin_files:$info[module]:$info[type]"); - if ($cache) { - $all_files[$info['module']][$info['type']] = $cache->data; - } + $cache = cache_get("ctools_plugin_files:$info[module]:$info[type]"); + if ($cache) { + $all_files[$info['module']][$info['type']] = $cache->data; } - - if (!isset($all_files[$info['module']][$info['type']])) { + // Do not attempt any file scan even if the cached entry was empty. + // A NULL entry here would mean the plugin just does not exists, and we + // cannot afford to run file scan on production sites normal run. + elseif (!isset($all_files[$info['module']][$info['type']])) { $all_files[$info['module']][$info['type']] = array(); // Load all our plugins. $directories = ctools_plugin_get_directories($info); @@ -678,7 +678,7 @@ function ctools_plugin_process($info, $module, $identifier, $path, $file = NULL, if (!function_exists($function)) { return NULL; } - $result = $function(); + $result = $function($info); if (!isset($result) || !is_array($result)) { return NULL; } diff --git a/sites/all/modules/contrib/dev/ctools/includes/utility.inc b/sites/all/modules/contrib/dev/ctools/includes/utility.inc index 9795dd86..82fc1471 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/utility.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/utility.inc @@ -29,16 +29,3 @@ function ctools_passthrough($module, $type, &$items) { } } } - -/** - * Implementation of hook_theme_registry_alter() - */ -function ctools_theme_registry_alter(&$registry) { - // Move this one last last last so it can catch changes made by modules and themes. - $key = array_search('ctools_preprocess_page', $registry['page']['preprocess functions']); - if ($key) { - unset($registry['page']['preprocess functions'][$key]); - } - $registry['page']['preprocess functions'][] = 'ctools_preprocess_page'; -} - diff --git a/sites/all/modules/contrib/dev/ctools/includes/uuid.inc b/sites/all/modules/contrib/dev/ctools/includes/uuid.inc new file mode 100644 index 00000000..b0567d34 --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/includes/uuid.inc @@ -0,0 +1,67 @@ + theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail)), + '#markup' => theme(array('ctools_wizard_trail__' . $form_info['id'], 'ctools_wizard_trail'), array('trail' => $trail, 'form_info' => $form_info)), '#weight' => -1000, ); } diff --git a/sites/all/modules/contrib/dev/ctools/includes/wizard.theme.inc b/sites/all/modules/contrib/dev/ctools/includes/wizard.theme.inc index 304906c0..c1a26468 100644 --- a/sites/all/modules/contrib/dev/ctools/includes/wizard.theme.inc +++ b/sites/all/modules/contrib/dev/ctools/includes/wizard.theme.inc @@ -7,19 +7,16 @@ function ctools_wizard_theme(&$theme) { $theme['ctools_wizard_trail'] = array( - 'variables' => array('trail' => NULL), + 'variables' => array('trail' => NULL, 'form_info' => NULL, 'divider' => ' » '), 'file' => 'includes/wizard.theme.inc', ); } /** - * Themable display of the 'breadcrumb' trail to show the order of the - * forms. + * Themable display of the 'breadcrumb' trail to show the order of the forms. */ function theme_ctools_wizard_trail($vars) { - $trail = $vars['trail']; - if (!empty($trail)) { - return '
' . implode(' » ', $trail) . '
'; + if (!empty($vars['trail'])) { + return '
' . implode($vars['divider'], $vars['trail']) . '
'; } } - diff --git a/sites/all/modules/contrib/dev/ctools/js/collapsible-div.js b/sites/all/modules/contrib/dev/ctools/js/collapsible-div.js index da9bff9e..134151c3 100644 --- a/sites/all/modules/contrib/dev/ctools/js/collapsible-div.js +++ b/sites/all/modules/contrib/dev/ctools/js/collapsible-div.js @@ -212,6 +212,7 @@ content.slideToggle(100, afterToggle); } + $container.toggleClass('ctools-collapsed'); toggle.toggleClass('ctools-toggle-collapsed'); // If we're supposed to remember the state of this class, do so. diff --git a/sites/all/modules/contrib/dev/ctools/js/dependent.js b/sites/all/modules/contrib/dev/ctools/js/dependent.js index e9e2447c..f74ec81b 100644 --- a/sites/all/modules/contrib/dev/ctools/js/dependent.js +++ b/sites/all/modules/contrib/dev/ctools/js/dependent.js @@ -40,7 +40,7 @@ Drupal.CTools.dependent.autoAttach = function() { // Clear active bindings and triggers. for (i in Drupal.CTools.dependent.activeTriggers) { - $(Drupal.CTools.dependent.activeTriggers[i]).unbind('change'); + $(Drupal.CTools.dependent.activeTriggers[i]).unbind('change.ctools-dependent'); } Drupal.CTools.dependent.activeTriggers = []; Drupal.CTools.dependent.activeBindings = {}; @@ -194,7 +194,7 @@ } } - $(trigger_id).change(function() { + $(trigger_id).bind('change.ctools-dependent', function() { // Trigger the internal change function // the attr('id') is used because closures are more confusing changeTrigger(trigger_id, bind_id); @@ -215,7 +215,7 @@ // is a sort of hacked one that's faster but much less flexible. $("select.ctools-master-dependent") .once('ctools-dependent') - .change(function() { + .bind('change.ctools-dependent', function() { var val = $(this).val(); if (val == 'all') { $('.ctools-dependent-all').show(0); @@ -225,7 +225,7 @@ $('.ctools-dependent-' + val).show(0); } }) - .trigger('change'); + .trigger('change.ctools-dependent'); } } })(jQuery); diff --git a/sites/all/modules/contrib/dev/ctools/js/modal.js b/sites/all/modules/contrib/dev/ctools/js/modal.js index 831649fc..37908cf3 100644 --- a/sites/all/modules/contrib/dev/ctools/js/modal.js +++ b/sites/all/modules/contrib/dev/ctools/js/modal.js @@ -99,6 +99,11 @@ $('span.modal-title', Drupal.CTools.Modal.modal).html(Drupal.CTools.Modal.currentSettings.loadingText); Drupal.CTools.Modal.modalContent(Drupal.CTools.Modal.modal, settings.modalOptions, settings.animation, settings.animationSpeed); $('#modalContent .modal-content').html(Drupal.theme(settings.throbberTheme)); + + // Position autocomplete results based on the scroll position of the modal. + $('#modalContent .modal-content').delegate('input.form-autocomplete', 'keyup', function() { + $('#autocomplete').css('top', $(this).position().top + $(this).outerHeight() + $(this).offsetParent().filter('#modal-content').scrollTop()); + }); }; /** @@ -222,7 +227,11 @@ // AJAX submits specified in this manner automatically submit to the // normal form action. element_settings.url = Drupal.CTools.Modal.findURL(this); + if (element_settings.url == '') { + element_settings.url = $(this).closest('form').attr('action'); + } element_settings.event = 'click'; + element_settings.setClick = true; var base = $this.attr('id'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); @@ -249,6 +258,10 @@ $('input[type=submit], button', this).click(function(event) { Drupal.ajax[base].element = this; this.form.clk = this; + // Stop autocomplete from submitting. + if (Drupal.autocompleteSubmit && !Drupal.autocompleteSubmit()) { + return false; + } // An empty event means we were triggered via .click() and // in jquery 1.4 this won't trigger a submit. if (event.bubbles == undefined) { @@ -282,7 +295,10 @@ // content. This is helpful for allowing users to see error messages at the // top of a form, etc. $('#modal-content').html(response.output).scrollTop(0); - Drupal.attachBehaviors(); + + // Attach behaviors within a modal dialog. + var settings = response.settings || ajax.settings || Drupal.settings; + Drupal.attachBehaviors('#modalContent', settings); } /** @@ -363,9 +379,9 @@ css.filter = 'alpha(opacity=' + (100 * css.opacity) + ')'; content.hide(); - // if we already ahve a modalContent, remove it - if ( $('#modalBackdrop')) $('#modalBackdrop').remove(); - if ( $('#modalContent')) $('#modalContent').remove(); + // If we already have modalContent, remove it. + if ($('#modalBackdrop').length) $('#modalBackdrop').remove(); + if ($('#modalContent').length) $('#modalContent').remove(); // position code lifted from http://www.quirksmode.org/viewport/compatibility.html if (self.pageYOffset) { // all except Explorer @@ -405,12 +421,17 @@ return true; } } - if( $(target).filter('*:visible').parents('#modalContent').size()) { - // allow the event only if target is a visible child node of #modalContent + + if ($(target).is('#modalContent, body') || $(target).filter('*:visible').parents('#modalContent').length) { + // Allow the event only if target is a visible child node + // of #modalContent. return true; } - if ( $('#modalContent')) $('#modalContent').get(0).focus(); - return false; + else { + $('#modalContent').focus(); + } + + event.preventDefault(); }; $('body').bind( 'focus', modalEventHandler ); $('body').bind( 'keypress', modalEventHandler ); @@ -461,6 +482,16 @@ // Move and resize the modalBackdrop and modalContent on resize of the window modalContentResize = function(){ + + // position code lifted from http://www.quirksmode.org/viewport/compatibility.html + if (self.pageYOffset) { // all except Explorer + var wt = self.pageYOffset; + } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict + var wt = document.documentElement.scrollTop; + } else if (document.body) { // all other Explorers + var wt = document.body.scrollTop; + } + // Get our heights var docHeight = $(document).height(); var docWidth = $(document).width(); @@ -470,7 +501,7 @@ // Get where we should move content to var modalContent = $('#modalContent'); - var mdcTop = ( winHeight / 2 ) - ( modalContent.outerHeight() / 2); + var mdcTop = wt + ( winHeight / 2 ) - ( modalContent.outerHeight() / 2); var mdcLeft = ( winWidth / 2 ) - ( modalContent.outerWidth() / 2); // Apply the changes diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.admin.inc b/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.admin.inc index 3dce041a..0f164fe5 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.admin.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.admin.inc @@ -14,7 +14,7 @@ function page_manager_list_page($js = NULL) { // Prevent this page from showing up when random other links fail. if ($js && $js != 'ajax' && $js != 'nojs') { - return drupal_not_found(); + return MENU_NOT_FOUND; } // TRUE if 'ajax', FALSE if otherwise. @@ -62,7 +62,7 @@ function page_manager_list_page($js = NULL) { if (isset($input['op']) && $input['op'] == t('Reset')) { unset($_SESSION['page_manager']['#admin']); if (!$js) { - return drupal_goto($_GET['q']); + drupal_goto($_GET['q']); } // clear everything but form id, form build id and form token: $keys = array_keys($input); @@ -95,6 +95,7 @@ function page_manager_list_page($js = NULL) { $header = array( array('data' => t('Type'), 'class' => array('page-manager-page-type')), + array('data' => t('Module'), 'class' => array('page-manager-page-module')), array('data' => t('Name'), 'class' => array('page-manager-page-name')), array('data' => t('Title'), 'class' => array('page-manager-page-title')), array('data' => t('Path'), 'class' => array('page-manager-page-path')), @@ -175,9 +176,18 @@ function page_manager_get_pages($tasks, &$pages, $task_id = NULL) { $row = array('data' => array(), 'class' => $class, 'title' => strip_tags($task['admin description'])); $type = isset($task['admin type']) ? $task['admin type'] : t('System'); + if (isset($task['module'])) { + $module = $task['module']; + } + elseif (isset($task['subtask']->export_module)) { + $module = $task['subtask']->export_module; + } + else { + $module = ''; + } $pages['types'][$type] = $type; $row['data']['type'] = array('data' => $type, 'class' => array('page-manager-page-type')); - + $row['data']['module'] = array('data' => $module, 'class' => array('page-manager-page-module')); $row['data']['name'] = array('data' => $task_name, 'class' => array('page-manager-page-name')); $row['data']['title'] = array('data' => $task['admin title'], 'class' => array('page-manager-page-title')); $row['data']['path'] = array('data' => $visible_path, 'class' => array('page-manager-page-path')); @@ -401,7 +411,7 @@ function page_manager_list_pages_form_submit(&$form, &$form_state) { * Render the edit page for a a page, custom or system. */ function page_manager_edit_page($page) { - drupal_set_title($page->subtask['admin title']); + drupal_set_title($page->subtask['admin title'], PASS_THROUGH); // Provide and process the save page form before anything else. $form_state = array('page' => &$page); $built_form = drupal_build_form('page_manager_save_page_form', $form_state); @@ -464,7 +474,7 @@ function page_manager_edit_page_operation() { return; } - drupal_set_title($page->subtask['admin title']); + drupal_set_title($page->subtask['admin title'], PASS_THROUGH); return $output; } @@ -577,8 +587,8 @@ function page_manager_get_operations($page, $operations = NULL) { ), ); - // Restrict variant import to users who can already execute arbitrary PHP - if (user_access('use PHP for settings')) { + // Restrict variant import due to security implications. + if (user_access('use ctools import')) { $result['actions']['children']['import'] = array( 'title' => t('Import variant'), 'description' => t('Add a new variant to this page from code exported from another page.'), @@ -930,7 +940,7 @@ function _page_manager_get_operation_content($js, &$page, $active, $operation, $ $output = drupal_render($built_form); $title = empty($form_state['title']) ? $operation['title'] : $form_state['title']; $titles[] = $title; - $title = implode(' » ', array_filter($titles)); + $title = implode(' » ', array_filter($titles)); // If there are messages for the form, render them. if ($messages = theme('status_messages')) { @@ -1308,6 +1318,7 @@ function page_manager_handler_add_submit(&$form, &$form_state) { else { $handler->conf['title'] = $plugin['title']; } + $handler->conf['name'] = $form_state['values']['name']; $cache->new_handler = $handler; // Figure out which forms to present them with @@ -1398,6 +1409,21 @@ function page_manager_handler_add_form($form, $form_state, $features = array()) '#title' => t('Title'), '#description' => t('Administrative title of this variant. If you leave blank it will be automatically assigned.'), ); + + $form['name'] = array( + '#type' => 'machine_name', + '#title' => t('Machine name'), + '#required' => FALSE, + '#description' => t("A unique machine-readable name for this variant. It must only contain lowercase letters, numbers, and underscores. This name will be used when exporting the variant. If left empty the variant's name will be used instead."), + '#size' => 32, + '#maxlength' => 32, + '#machine_name' => array( + 'exists' => 'page_manager_handler_check_machine_name', + 'source' => array('title'), + ), + '#field_prefix' => '' . $form_state['task_name'] . '__', + '#field_suffix' => '‎', + ); } $form['handler'] = array( @@ -1436,6 +1462,15 @@ function page_manager_handler_add_form($form, $form_state, $features = array()) return $form; } +/* + * Check if handler's machine-name is unique + */ +function page_manager_handler_check_machine_name($name, $element, $form_state) { + $name = $form_state['task_name'] . '__' . $name; + + return count(ctools_export_load_object('page_manager_handlers', 'names', array($name))); +} + /** * Rearrange the order of variants. */ @@ -1446,15 +1481,16 @@ function page_manager_handler_import($form, &$form_state) { '#description' => t('Enter the name of the new variant.'), ); - if (user_access('use PHP for settings')) { + if (user_access('use ctools import')) { $form['object'] = array( '#type' => 'textarea', '#title' => t('Paste variant code here'), '#rows' => 15, ); } - // Users ordinarily can't get here without the PHP block visibility perm. - // In case they somehow do, though, disable the form widget for extra safety. + // Users ordinarily can't get here without the 'import' permission, due to + // security implications. In case they somehow do, though, disable the form + // widget for extra safety. else { $form['shoveoff'] = array( '#markup' => '
' . t('You do not have sufficient permissions to perform this action.') . '
', @@ -1468,7 +1504,7 @@ function page_manager_handler_import($form, &$form_state) { * Make sure that an import actually provides a handler. */ function page_manager_handler_import_validate($form, &$form_state) { - if (!user_access('use PHP for settings')) { + if (!user_access('use ctools import')) { form_error($form['shoveoff'], t('You account permissions do not permit you to import.')); return; } diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.info b/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.info index 76095ff1..c34099ed 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.info +++ b/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.info @@ -3,10 +3,11 @@ description = Provides a UI and API to manage pages within the site. core = 7.x dependencies[] = ctools package = Chaos tool suite +version = CTOOLS_MODULE_VERSION -; Information added by drupal.org packaging script on 2013-04-03 -version = "7.x-1.3" +; Information added by Drupal.org packaging script on 2015-03-18 +version = "7.x-1.7" core = "7.x" project = "ctools" -datestamp = "1365013512" +datestamp = "1426696183" diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.module b/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.module index da99a578..70237520 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.module +++ b/sites/all/modules/contrib/dev/ctools/page_manager/page_manager.module @@ -213,6 +213,30 @@ function page_manager_menu_alter(&$items) { } } + // Override the core node revisions display to use the configured Page + // display handler. + if (!variable_get('page_manager_node_view_disabled', TRUE) && isset($items['node/%node/revisions/%/view'])) { + // Abstract the basic settings. + $item = array( + // Handle the page arguments. + 'load arguments' => array(3), + 'page arguments' => array(1, TRUE), + + // Replace the normal node_show call with Page Manager's node view. + 'page callback' => 'page_manager_node_view_page', + + // Provide the correct path to the Page Manager file. + 'file' => 'node_view.inc', + 'file path' => drupal_get_path('module', 'page_manager') . '/plugins/tasks', + ); + // Re-build the menu item using the normal values from node.module. + $items['node/%node/revisions/%/view'] = array( + 'title' => 'Revisions', + 'access callback' => '_node_revision_access', + 'access arguments' => array(1), + ) + $item; + } + return $items; } @@ -416,16 +440,17 @@ function page_manager_cache_load($task_name) { */ function page_manager_handler_get_name($task_name, $handlers, $handler) { $base = str_replace('-', '_', $task_name); - // Generate a unique name. Unlike most named objects, we don't let people choose - // names for task handlers because they mostly don't make sense. - $base .= '_' . $handler->handler; + // Optional machine name. + if (!empty($handler->conf['name'])) { + $name = $base . '__' . $handler->conf['name']; + } - // Once we have a base, check to see if it is used. If it is, start counting up. - $name = $base; - $count = 1; - // If taken - while (isset($handlers[$name])) { - $name = $base . '_' . ++$count; + // If no machine name was provided, generate a unique name. + else { + $base .= '__' . $handler->handler; + + // Use the ctools uuid generator to generate a unique id. + $name = $base . '_' . ctools_uuid_generate(); } return $name; diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/cache/page_manager_context.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/cache/page_manager_context.inc new file mode 100644 index 00000000..2f01b560 --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/cache/page_manager_context.inc @@ -0,0 +1,70 @@ + t('Page manager context'), + 'cache get' => 'page_manager_cache_page_manager_context_cache_get', + 'cache set' => 'page_manager_cache_page_manager_context_cache_set', + 'cache finalize' => 'page_manager_cache_page_manager_context_cache_finalize', + + // We don't support a clear because the general uses of clear have no effect + // on us. +); + +function page_manager_cache_page_manager_context_cache_get($data, $key) { + $page = page_manager_get_page_cache($data); + if ($page) { + if (!empty($page->context_cache[$key])) { + return $page->context_cache[$key]; + } + else { + ctools_include('context-task-handler'); + if ($key == 'temp') { + $handler = $page->new_handler; + } + else { + $handler = $page->handlers[$key]; + } + return ctools_context_handler_get_task_object($page->task, $page->subtask, $handler); + } + } +} + +function page_manager_cache_page_manager_context_cache_set($data, $key, $object) { + $page = page_manager_get_page_cache($data); + if ($page) { + $page->context_cache[$key] = $object; + return page_manager_set_page_cache($page); + } +} + +/** + * Copy temporary data from the page manager cache + */ +function page_manager_cache_page_manager_context_cache_finalize($data, $key, $object) { + // Statically cached so there shouldn't be any worries. It's an object so + // referencing ensures that we'll get the right one. + $page = page_manager_get_page_cache($data); + if ($page) { + if ($key == 'temp') { + $handler = $page->new_handler; + } + else { + $handler = $page->handlers[$key]; + } + $handler->conf['contexts'] = $object->contexts; + $handler->conf['relationships'] = $object->relationships; + + if (isset($page->context_cache[$key])) { + unset($page->context_cache[$key]); + } + return page_manager_set_page_cache($page); + } +} diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/task_handlers/http_response.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/task_handlers/http_response.inc index e5c01414..c4eba8e2 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/task_handlers/http_response.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/task_handlers/http_response.inc @@ -216,6 +216,9 @@ function page_manager_http_response_title($handler, $task, $subtask) { * General settings for the panel */ function page_manager_http_response_edit_settings($form, &$form_state) { + ctools_include('page_manager.admin', 'page_manager', ''); + ctools_include('export', 'ctools'); + $conf = $form_state['handler']->conf; $form['title'] = array( '#type' => 'textfield', @@ -224,6 +227,23 @@ function page_manager_http_response_edit_settings($form, &$form_state) { '#description' => t('Administrative title of this variant.'), ); + $name = isset($conf['name']) ? $conf['name'] : FALSE; + $form['name'] = array( + '#type' => 'machine_name', + '#title' => t('Machine name'), + '#required' => FALSE, + '#default_value' => $name, + '#description' => t("A unique machine-readable name for this variant. It must only contain lowercase letters, numbers, and underscores. This name will be used when exporting the variant. If left empty the variant's name will be used instead."), + '#size' => 32, + '#maxlength' => 32, + '#machine_name' => array( + 'exists' => 'page_manager_handler_check_machine_name', + 'source' => array('title'), + ), + '#field_prefix' => '' . $form_state['task_name'] . '__', + '#field_suffix' => '‎', + ); + $form['code'] = array( '#title' => t('Response code'), '#type' => 'select', @@ -244,7 +264,33 @@ function page_manager_http_response_edit_settings($form, &$form_state) { } function page_manager_http_response_edit_settings_submit($form, &$form_state) { + $machine_name = $form_state['handler']->name; + $name = $form_state['task_name'] . '__' . $form_state['values']['name']; + + // If new name doesn't equal machine name, we need to update and redirect. + if ($machine_name !== $name) { + $form_state['handler']->name = $name; + // If there's a trail, we need to replace it for redirection. + if (isset($form_state['trail'])) { + $form_state['new trail'] = $form_state['trail']; + $delta = array_search($machine_name, $form_state['new trail']); + $form_state['new trail'][$delta] = $name; + } + // If handler id is set, replace it. + if ($form_state['handler_id']) { + $form_state['handler_id'] = $name; + } + // If we're defining a new custom handler, move page handler to new name. + if (isset($form_state['page']->handlers[$machine_name]) && isset($form_state['page']->handler_info[$machine_name])) { + $form_state['page']->handlers[$name] = $form_state['page']->handlers[$machine_name]; + unset($form_state['page']->handlers[$machine_name]); + $form_state['page']->handler_info[$name] = $form_state['page']->handler_info[$machine_name]; + unset($form_state['page']->handler_info[$machine_name]); + } + } + $form_state['handler']->conf['title'] = $form_state['values']['title']; + $form_state['handler']->conf['name'] = $form_state['values']['name']; $form_state['handler']->conf['code'] = $form_state['values']['code']; $form_state['handler']->conf['destination'] = $form_state['values']['destination']; } diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/comment_reply.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/comment_reply.inc index 0fcf9e2a..ffbafe46 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/comment_reply.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/comment_reply.inc @@ -67,7 +67,7 @@ function page_manager_comment_reply_page($node, $pid = NULL){ } $output = ctools_context_handler_render($task, '', $contexts, array($node, $pid)); - if ($output != FALSE) { + if ($output !== FALSE) { return $output; } diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_edit.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_edit.inc index 844cd5b3..e0585e80 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_edit.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_edit.inc @@ -126,7 +126,7 @@ function page_manager_node_add($type) { 'language' => LANGUAGE_NONE, ); - drupal_set_title(t('Create @name', array('@name' => $types[$type]->name))); + drupal_set_title(t('Create @name', array('@name' => $types[$type]->name)), PASS_THROUGH); return page_manager_node_edit($node); } diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_view.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_view.inc index b8a7e0c9..ad754e0e 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_view.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/node_view.inc @@ -78,6 +78,10 @@ function page_manager_node_view_menu_alter(&$items, $task) { * node view, which is node_page_view(). */ function page_manager_node_view_page($node) { + // Prep the node to be displayed so all of the regular hooks are triggered. + // Also save the output for later, in case it is needed. + $default_output = node_page_view($node); + // Load my task plugin $task = page_manager_get_task('node_view'); @@ -85,32 +89,26 @@ function page_manager_node_view_page($node) { ctools_include('context'); ctools_include('context-task-handler'); - // We need to mimic Drupal's behavior of setting the node title here. - drupal_set_title($node->title); - $uri = entity_uri('node', $node); - // Set the node path as the canonical URL to prevent duplicate content. - drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE); - // Set the non-aliased path as a default shortlink. - drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE); + // Load all contexts. $contexts = ctools_context_handler_get_task_contexts($task, '', array($node)); + // Build the full output using the configured CTools plugin. $output = ctools_context_handler_render($task, '', $contexts, array($node->nid)); - if ($output != FALSE) { + if ($output !== FALSE) { node_tag_new($node); return $output; } - $function = 'node_page_view'; + // Try loading an override plugin. foreach (module_implements('page_manager_override') as $module) { $call = $module . '_page_manager_override'; if (($rc = $call('node_view')) && function_exists($rc)) { - $function = $rc; - break; + return $rc($node); } } - // Otherwise, fall back. - return $function($node); + // Otherwise, fall back to the default output generated by node_page_view(). + return $default_output; } /** diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.admin.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.admin.inc index 69ac02de..7c560fb8 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.admin.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.admin.inc @@ -38,7 +38,7 @@ function page_manager_page_menu(&$items, $task) { ) + $base; if ($access_callback == 'user_access') { $items['admin/structure/pages/import']['access callback'] = 'ctools_access_multiperm'; - $items['admin/structure/pages/import']['access arguments'][] = 'use PHP for settings'; + $items['admin/structure/pages/import']['access arguments'][] = 'use ctools import'; } // AJAX callbacks for argument modal. @@ -237,7 +237,7 @@ function page_manager_page_add_subtask($task_name = NULL, $step = NULL) { if ($task_name) { $page = page_manager_get_page_cache($task_name); if (empty($page)) { - return drupal_not_found(); + return MENU_NOT_FOUND; } $form_info['path'] = "admin/structure/pages/add/$task_name/%step"; @@ -443,7 +443,7 @@ function page_manager_page_form_basic($form, &$form_state) { '#type' => 'checkbox', '#default_value' => !empty($page->make_frontpage), '#title' => t('Make this your site home page.'), - '#description' => t('To set this panel as your home page you must create a unique path name with no % placeholders in the path. The site home page is currently set to %homepage on the !siteinfo configuration form.', array('!siteinfo' => l(t('Site Information'), 'admin/settings/site-information'), '%homepage' => '/' . $frontpage)), + '#description' => t('To set this panel as your home page you must create a unique path name with no % placeholders in the path. The site home page is currently set to %homepage on the !siteinfo configuration form.', array('!siteinfo' => l(t('Site Information'), 'admin/config/system/site-information'), '%homepage' => '/' . $frontpage)), ); $form['admin_paths'] = array( '#type' => 'checkbox', @@ -769,12 +769,12 @@ function page_manager_page_form_menu($form, &$form_state) { ); } $form['menu']['parent']['weight'] = array( - '#title' => t('Tab weight'), + '#title' => t('Parent weight'), '#type' => 'textfield', '#default_value' => $menu['parent']['weight'], '#size' => 5, - '#description' => t('If the parent menu item is a tab, enter the weight of the tab. The lower the number, the more to the left it will be.'), - '#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('tab')), + '#description' => t('Enter the weight of the parent item. The lower the number, the more to the left it will be.'), + '#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('tab', 'normal')), '#dependency_count' => 2, ); diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.inc index 6223c733..6a8545d1 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/page.inc @@ -321,7 +321,7 @@ function page_manager_page_execute($subtask_id) { ctools_include('context-task-handler'); $output = ctools_context_handler_render($task, $subtask, $contexts, $args); if ($output === FALSE) { - return drupal_not_found(); + return MENU_NOT_FOUND; } return $output; diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/term_view.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/term_view.inc index e2765708..37259b95 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/term_view.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/term_view.inc @@ -138,7 +138,7 @@ function page_manager_term_view_page($term, $depth = NULL) { $contexts = ctools_context_handler_get_task_contexts($task, '', array($term, $depth)); if (empty($contexts)) { - return drupal_not_found(); + return MENU_NOT_FOUND; } // Build the full output using the configured CTools plugin. @@ -151,7 +151,7 @@ function page_manager_term_view_page($term, $depth = NULL) { foreach (module_implements('page_manager_override') as $module) { $call = $module . '_page_manager_override'; if (($rc = $call('term_view')) && function_exists($rc)) { - return $rc($node); + return $rc($term, $depth); } } diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_edit.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_edit.inc index 6d0135de..0b11bf01 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_edit.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_edit.inc @@ -97,8 +97,8 @@ function page_manager_user_edit_page($account, $category = 'account') { $output = ctools_context_handler_render($task, '', $contexts, array($account->uid)); if (is_array($output)) { $output = drupal_render($output); - } - if ($output != FALSE) { + } + if ($output !== FALSE) { return $output; } @@ -119,7 +119,7 @@ function page_manager_user_edit_page($account, $category = 'account') { //call drupal_build_form. $form_state = array(); $form_id = 'user_profile_form'; - $args = array($account); + $args = array($account, $category); $form_state['build_info']['args'] = $args; form_load_include($form_state, 'inc', 'user', 'user.pages'); $output = drupal_build_form($form_id, $form_state); diff --git a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_view.inc b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_view.inc index dfb40817..c428384a 100644 --- a/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_view.inc +++ b/sites/all/modules/contrib/dev/ctools/page_manager/plugins/tasks/user_view.inc @@ -81,7 +81,7 @@ function page_manager_user_view_page($account) { user_build_content($account); $output = ctools_context_handler_render($task, '', $contexts, array($account->uid)); - if ($output != FALSE) { + if ($output !== FALSE) { return $output; } diff --git a/sites/all/modules/contrib/dev/ctools/plugins/access/book.inc b/sites/all/modules/contrib/dev/ctools/plugins/access/book.inc new file mode 100644 index 00000000..4b4f7eaa --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/plugins/access/book.inc @@ -0,0 +1,94 @@ + t("Book: node is in a book"), + 'description' => t('Control access based upon a node belonging to a book.'), + 'callback' => 'ctools_book_node_ctools_access_check', + 'default' => array('book' => array()), + 'settings form' => 'ctools_book_node_ctools_access_settings', + 'settings form submit' => 'ctools_book_node_ctools_access_settings_submit', + 'summary' => 'ctools_book_node_ctools_access_summary', + 'required context' => new ctools_context_required(t('Node'), 'node'), + ); +} + +/** + * Settings form for the 'by book_node' access plugin. + */ +function ctools_book_node_ctools_access_settings($form, &$form_state, $conf) { + $options = array( + 'any' => t('In any book'), + ); + $books = book_get_books(); + foreach ($books as $bid => $book) { + $options[$bid] = $book['title']; + } + $form['settings']['book'] = array( + '#title' => t('Book'), + '#type' => 'checkboxes', + '#options' => $options, + '#description' => t('Pass only if the node belongs to one of the selected books'), + '#default_value' => $conf['book'], + '#required' => TRUE, + ); + return $form; +} + +/** + * Check for access. + */ +function ctools_book_node_ctools_access_check($conf, $context) { + // As far as I know there should always be a context at this point, but this + // is safe. + if (empty($context) || empty($context->data) || empty($context->data->book)) { + return FALSE; + } + + if ($conf['book']['any']) { + return !empty($context->data->book); + } + + foreach ($conf['book'] as $bid => $value) { + if ($bid == 'any') { + continue; + } + if ($value && ($bid == $context->data->book['bid'])) { + return TRUE; + } + } + + return FALSE; +} + +/** + * Provide a summary description based upon the checked node_languages. + */ +function ctools_book_node_ctools_access_summary($conf, $context) { + if ($conf['book']['any']) { + return t('@identifier belongs to a book', array('@identifier' => $context->identifier)); + } + + $books = array(); + foreach ($conf['book'] as $bid => $value) { + if ($value) { + $node = node_load($bid); + $books[] = $node->title; + } + } + + if (count($books) == 1) { + return t('@identifier belongs to the book "@book"', array('@book' => $books[0], '@identifier' => $context->identifier)); + } + + return t('@identifier belongs in multiple books', array('@identifier' => $context->identifier)); +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/access/entity_field_value.inc b/sites/all/modules/contrib/dev/ctools/plugins/access/entity_field_value.inc index e5857d89..fa94a481 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/access/entity_field_value.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/access/entity_field_value.inc @@ -16,8 +16,8 @@ $plugin = array( 'get child' => 'ctools_entity_field_value_ctools_access_get_child', 'get children' => 'ctools_entity_field_value_ctools_access_get_children', ); -function ctools_entity_field_value_ctools_access_get_child($plugin, $parent, $child) { +function ctools_entity_field_value_ctools_access_get_child($plugin, $parent, $child) { $plugins = &drupal_static(__FUNCTION__, array()); if (empty($plugins[$parent . ':' . $child])) { list($entity_type, $bundle_type, $field_name) = explode(':', $child); @@ -48,7 +48,6 @@ function ctools_entity_field_value_ctools_access_get_children($plugin, $parent) } function _ctools_entity_field_value_ctools_access_get_child($plugin, $parent, $entity_type, $bundle_type, $field_name, $entity = NULL, $bundle = NULL, $field = NULL) { - // check that the entity, bundle and field arrays have a value. // If not, load theme using machine names. if (empty($entity)) { @@ -86,12 +85,34 @@ function ctools_entity_field_value_ctools_access_settings($form, &$form_state, $ $instance = $instances[$field_name]; $field = field_info_field_by_id($instance['field_id']); foreach ($field['columns'] as $column => $attributes) { - $columns[] = _field_sql_storage_columnname($field_name, $column); + $columns[$column] = _field_sql_storage_columnname($field_name, $column); } ctools_include('fields'); $entity = (object)array( $entity_info['entity keys']['bundle'] => $bundle_type, ); + + foreach ($columns as $column => $sql_column) { + if (isset($conf[$sql_column])) { + if (is_array($conf[$sql_column])) { + foreach ($conf[$sql_column] as $delta => $conf_value) { + if (is_numeric($delta)) { + if (is_array($conf_value)) { + $entity->{$field_name}[LANGUAGE_NONE][$delta][$column] = $conf_value[$column]; + } + else { + $entity->{$field_name}[LANGUAGE_NONE][$delta][$column] = $conf_value; + } + } + } + } + else { + $entity->{$field_name}[LANGUAGE_NONE][0][$column] = $conf[$sql_column]; + } + } + } + + $form['#parents'] = array('settings'); $langcode = field_valid_language(NULL); $form['settings'] += (array) ctools_field_invoke_field($instance, 'form', $entity_type, $entity, $form, $form_state, array('default' => TRUE, 'language' => $langcode)); // weight is really not important once this is populated and will only interfere with the form layout. @@ -99,26 +120,9 @@ function ctools_entity_field_value_ctools_access_settings($form, &$form_state, $ unset($form['settings'][$element]['#weight']); } - // Need more logic here to handle compound fields. - foreach ($columns as $column) { - if (isset($conf[$column]) && is_array($conf[$column])) { - foreach ($conf[$column] as $delta => $conf_value) { - if (is_numeric($delta) && is_array($conf_value)) { - $form['settings'][$field_name][LANGUAGE_NONE][$delta]['value']['#default_value'] = $conf_value['value']; - } - } - } - else { - $form['settings'][$field_name][LANGUAGE_NONE]['#default_value'] = $conf[$column]; - } - } - return $form; } -/** - * Compress the entity bundles allowed to the minimum. - */ function ctools_entity_field_value_ctools_access_settings_submit($form, &$form_state) { $plugin = $form_state['plugin']; list($parent, $entity_type, $bundle_type, $field_name) = explode(':', $plugin['name']); @@ -128,17 +132,82 @@ function ctools_entity_field_value_ctools_access_settings_submit($form, &$form_s $instance = $instances[$field_name]; $field = field_info_field_by_id($instance['field_id']); foreach ($field['columns'] as $column => $attributes) { - $columns[] = _field_sql_storage_columnname($field_name, $column); + $columns[$column] = _field_sql_storage_columnname($field_name, $column); } + $items = _ctools_entity_field_value_get_proper_form_items($field, $form_state['values']['settings'][$field_name][$langcode], array_keys($columns)); + foreach ($columns as $column => $sql_column) { + $column_items = _ctools_entity_field_value_filter_items_by_column($items, $column); + $form_state['values']['settings'][$sql_column] = $column_items; + } + $form_state['values']['settings'][$field_name][$langcode] = $items; +} + +function _ctools_entity_field_value_get_proper_form_items($field, $form_items, $columns) { + $items = array(); + + if (!is_array($form_items)) { // Single value item. + foreach ($columns as $column) { + $items[0][$column] = $form_items; + } + return $items; + } + + foreach ($form_items as $delta => $value) { + $item = array(); + if (is_numeric($delta)) { // Array of field values. + if (!is_array($value)) { // Single value in array. + foreach ($columns as $column) { + $item[$column] = $value; + } + } + else { // Value has colums. + foreach ($columns as $column) { + $item[$column] = isset($value[$column]) ? $value[$column] : ''; + } + } + } + $items[] = $item; + } + + // Check if $form_items is an array of columns. + $item = array(); + $has_columns = FALSE; foreach ($columns as $column) { - $form_state['values']['settings'][$column] = $form_state['input']['settings'][$field_name][$langcode]; + if (isset($form_items[$column])) { + $has_columns = TRUE; + $item[$column] = $form_items[$column]; + } + else { + $item[$column] = ''; + } } + if ($has_columns) { + $items[] = $item; + } + + // Remove empty values. + $items = _field_filter_items($field, $items); + return $items; +} + +function _ctools_entity_field_value_filter_items_by_column($items, $column) { + $column_items = array(); + foreach ($items as $delta => $values) { + $column_items[$delta] = isset($values[$column]) ? $values[$column] : ''; + } + return $column_items; } /** * Check for access. */ function ctools_entity_field_value_ctools_access_check($conf, $context, $plugin) { + if ((!is_object($context)) || (empty($context->data))) { + // If the context doesn't exist -- for example, a newly added entity + // reference is used as a pane visibility criteria -- we deny access. + return FALSE; + } + list($parent, $entity_type, $bundle_type, $field_name) = explode(':', $plugin['name']); if ($field_items = field_get_items($entity_type, $context->data, $field_name)) { @@ -160,16 +229,27 @@ function ctools_entity_field_value_ctools_access_check($conf, $context, $plugin) // Check field value. foreach ($field_items as $field_value) { - foreach ($field_value as $field_column => $value) { - // Iterate through config values. - foreach ($conf_value_array as $conf_value) { + // Iterate through config values. + foreach ($conf_value_array as $conf_value) { + $match = FALSE; + foreach ($field_value as $field_column => $value) { // Check access only for stored in config column values. - if (isset($conf_value[$field_column]) && $value == $conf_value[$field_column]) { - return TRUE; + if (isset($conf_value[$field_column])) { + if ($value == $conf_value[$field_column]) { + $match = TRUE; + } + else { + $match = FALSE; + break; + } } } + if ($match) { + return TRUE; + } } } + return FALSE; } } @@ -178,7 +258,7 @@ function ctools_entity_field_value_ctools_access_check($conf, $context, $plugin) function _ctools_entity_field_value_ctools_access_get_conf_field_values($values, $langcode = LANGUAGE_NONE) { if (!is_array($values) || !isset($values[$langcode])) { - return; + return NULL; } $conf_values = array(); @@ -201,41 +281,130 @@ function ctools_entity_field_value_ctools_access_summary($conf, $context, $plugi $entity = (object)array( $entity_info['entity keys']['bundle'] => $bundle_type, ); - $string = ''; $keys = array(); - $values = array(); + $value_keys = array(); + $keyed_elements = array(); foreach ($field['columns'] as $column => $attributes) { $conf_key = _field_sql_storage_columnname($field_name, $column); - if (count($field['columns']) > 1) { - // Add some sort of handling for compound fields - } - else { - if (isset($conf[$conf_key])) { - $entity->{$field_name}[LANGUAGE_NONE][] = array($column => $conf[$conf_key]); + $keyed_elements["@{$column}_value"] = array(); + + if (isset($conf[$conf_key])) { + if (is_array($conf[$conf_key])) { + $i = 0; + foreach ($conf[$conf_key] as $conf_value) { + if (!is_array($conf_value)) { + $entity->{$field_name}[LANGUAGE_NONE][$i][$column] = $conf_value; + $keyed_elements["@{$column}_value"][$i] = array('#markup' => $conf_value); + } + elseif (isset($conf_value[$column])) { + $entity->{$field_name}[LANGUAGE_NONE][$i][$column] = $conf_value[$column]; + $keyed_elements["@{$column}_value"][$i] = array('#markup' => $conf_value[$column]); + } + $i++; + } + } + else { + $entity->{$field_name}[LANGUAGE_NONE][0][$column] = $conf[$conf_key]; + $keyed_elements["@{$column}_value"][0] = array('#markup' => $conf[$conf_key]); } } - $string .= " @{$column} equals @{$column}_value"; - $keys['@' . $column] = $column; - $values["@{$column}_value"] = $conf[$conf_key]; - } - $view_mode = 'full'; - $null = NULL; - $options = array('language' => LANGUAGE_NONE); - ctools_include('fields'); - $display = field_get_display($instance, $view_mode, $entity); - if (isset($display['module'])) { - $display['type'] = 'list_default'; - $function = $display['module'] . '_field_formatter_view'; - $items = isset($entity->{$field_name}[LANGUAGE_NONE]) ? $entity->{$field_name}[LANGUAGE_NONE] : array(); - if (function_exists($function)) { - $elements = $function($entity_type, $entity, $field, $instance, LANGUAGE_NONE, $items, $display); - } - $value_keys = array_keys($values); - foreach ($value_keys as $key => $value) { - $values[$value] = isset($elements[$key]['#markup']) ? $elements[$key]['#markup'] : ''; - } - } - $values = array_merge($keys, $values); - return t($string, $values); -} + $keys['@' . $column] = $column; + $value_keys[] = "@{$column}_value"; + } + $elements = array(); + $items = isset($entity->{$field_name}[LANGUAGE_NONE]) ? $entity->{$field_name}[LANGUAGE_NONE] : array(); + $view_mode = 'full'; + ctools_include('fields'); + $display = field_get_display($instance, $view_mode, $entity); + if (!isset($display['module'])) { + $display['module'] = $field['module']; + } + if (isset($display['module'])) { + // Choose simple formatter for well known cases. + switch ($display['module']) { + case 'text': + $display['type'] = 'text_default'; + break; + + case 'list': + $display['type'] = 'list_default'; + if ($field['type'] == 'list_boolean') { + $allowed_values = list_allowed_values($field, $instance, $entity_type, $entity); + foreach ($items as $item) { + if (isset($allowed_values[$item['value']])) { + if ($allowed_values[$item['value']] == '') { + $display['type'] = 'list_key'; + break; + } + } + else { + $display['type'] = 'list_key'; + } + } + } + break; + + case 'taxonomy': + $display['type'] = 'taxonomy_term_reference_plain'; + break; + + case 'entityreference': + $display['type'] = 'entityreference_label'; + break; + + default : + // Use field instance formatter setting. + break; + } + + $function = $display['module'] . '_field_formatter_view'; + if (function_exists($function)) { + $entity_group = array(0 => $entity); + $item_group = array(0 => $items); + $instance_group = array(0 => $instance); + field_default_prepare_view($entity_type, $entity_group, $field, $instance_group, LANGUAGE_NONE, $item_group, $display); + $elements = $function($entity_type, $entity, $field, $instance, LANGUAGE_NONE, $item_group[0], $display); + } + } + if (count($elements) > 0) { + foreach ($field['columns'] as $column => $attributes) { + if (count($field['columns']) == 1) { + $keyed_elements["@{$column}_value"] = $elements; + } + } + } + $values = array(); + foreach ($value_keys as $key) { + $output = array(); + $elements = $keyed_elements[$key]; + if (is_array($elements)) { + foreach ($elements as $element_key => $element) { + if (is_numeric($element_key)) { + $value_str= strip_tags(drupal_render($element)); + if (strlen($value_str) > 0) { + $output[] = $value_str; + } + } + } + } + else { + $value_str = strip_tags(drupal_render($elements)); + if (strlen($value_str) > 0) { + $output[] = $value_str; + } + } + $value = implode(', ', $output); + if ($value !== '') { + $values[$key] = implode(', ', $output); + } + } + $string = ''; + $value_count = count($values); + foreach ($keys as $key_name => $column) { + if (isset($values[$key_name . '_value'])) { + $string .= ($value_count > 1) ? " @{$column} = @{$column}_value" : "@{$column}_value"; + } + } + return t('@field is set to "!value"', array('@field' => $instance['label'], '!value' => format_string($string, array_merge($keys, $values)))); +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/access/node_comment.inc b/sites/all/modules/contrib/dev/ctools/plugins/access/node_comment.inc new file mode 100644 index 00000000..915ee20e --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/plugins/access/node_comment.inc @@ -0,0 +1,31 @@ + t("Node: comments are open"), + 'description' => t('Control access by the nodes comment status.'), + 'callback' => 'ctools_node_comment_ctools_access_check', + 'summary' => 'ctools_node_comment_ctools_access_summary', + 'required context' => new ctools_context_required(t('Node'), 'node'), +); + +/** + * Checks for access. + */ +function ctools_node_comment_ctools_access_check($conf, $context) { + return (!empty($context->data) && $context->data->comment == 2); +} + +/** + * Provides a summary description based upon the checked node_status. + */ +function ctools_node_comment_ctools_access_summary($conf, $context) { + return t('Returns true if the nodes comment status is "open".'); +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/access/string_length.inc b/sites/all/modules/contrib/dev/ctools/plugins/access/string_length.inc index 2bad6afb..91abf227 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/access/string_length.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/access/string_length.inc @@ -59,7 +59,7 @@ function ctools_string_length_ctools_access_check($conf, $context) { return $length < $conf['length']; case '<=': return $length <= $conf['length']; - case '==': + case '=': return $length == $conf['length']; case '!=': return $length != $conf['length']; @@ -68,6 +68,8 @@ function ctools_string_length_ctools_access_check($conf, $context) { case '>=': return $length >= $conf['length']; } + // Invalid Operator sent, return FALSE. + return FALSE; } /** diff --git a/sites/all/modules/contrib/dev/ctools/plugins/access/term_vocabulary.inc b/sites/all/modules/contrib/dev/ctools/plugins/access/term_vocabulary.inc index 644600fc..b003138d 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/access/term_vocabulary.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/access/term_vocabulary.inc @@ -17,7 +17,11 @@ $plugin = array( 'settings form' => 'ctools_term_vocabulary_ctools_access_settings', 'settings form submit' => 'ctools_term_vocabulary_ctools_access_settings_submit', 'summary' => 'ctools_term_vocabulary_ctools_access_summary', - 'required context' => new ctools_context_required(t('Vocabulary'), array('taxonomy_term', 'terms', 'taxonomy_vocabulary')), + 'required context' => new ctools_context_required(t('Vocabulary'), array( + 'taxonomy_term', + 'terms', + 'taxonomy_vocabulary' + )), ); /** @@ -27,15 +31,17 @@ function ctools_term_vocabulary_ctools_access_settings($form, &$form_state, $con $options = array(); $vocabularies = taxonomy_get_vocabularies(); foreach ($vocabularies as $voc) { - $options[$voc->vid] = check_plain($voc->name); + $options[$voc->machine_name] = check_plain($voc->name); } - $form['settings']['vids'] = array( + _ctools_term_vocabulary_ctools_access_map_vids($conf); + + $form['settings']['machine_name'] = array( '#type' => 'checkboxes', '#title' => t('Vocabularies'), '#options' => $options, '#description' => t('Only the checked vocabularies will be valid.'), - '#default_value' => $conf['vids'], + '#default_value' => $conf['machine_name'], ); return $form; } @@ -44,7 +50,7 @@ function ctools_term_vocabulary_ctools_access_settings($form, &$form_state, $con * Compress the term_vocabularys allowed to the minimum. */ function ctools_term_vocabulary_ctools_access_settings_submit($form, &$form_state) { - $form_state['values']['settings']['vids'] = array_filter($form_state['values']['settings']['vids']); + $form_state['values']['settings']['machine_name'] = array_filter($form_state['values']['settings']['machine_name']); } /** @@ -53,11 +59,13 @@ function ctools_term_vocabulary_ctools_access_settings_submit($form, &$form_stat function ctools_term_vocabulary_ctools_access_check($conf, $context) { // As far as I know there should always be a context at this point, but this // is safe. - if (empty($context) || empty($context->data) || empty($context->data->vid)) { + if (empty($context) || empty($context->data) || empty($context->data->vocabulary_machine_name)) { return FALSE; } - if (array_filter($conf['vids']) && empty($conf['vids'][$context->data->vid])) { + _ctools_term_vocabulary_ctools_access_map_vids($conf); + + if (array_filter($conf['machine_name']) && empty($conf['machine_name'][$context->data->vocabulary_machine_name])) { return FALSE; } @@ -73,15 +81,47 @@ function ctools_term_vocabulary_ctools_access_summary($conf, $context) { } $vocabularies = taxonomy_get_vocabularies(); + _ctools_term_vocabulary_ctools_access_map_vids($conf); + $names = array(); - foreach (array_filter($conf['vids']) as $vid) { - $names[] = check_plain($vocabularies[$vid]->name); + if (!empty($conf['machine_name'])) { + foreach (array_filter($conf['machine_name']) as $machine_name) { + foreach ($vocabularies as $vocabulary) { + if ($vocabulary->machine_name === $machine_name) { + $names[] = check_plain($vocabulary->name); + continue; + } + } + } } if (empty($names)) { return t('@identifier is any vocabulary', array('@identifier' => $context->identifier)); } - return format_plural(count($names), '@identifier vocabulary is "@vids"', '@identifier vocabulary is one of "@vids"', array('@vids' => implode(', ', $names), '@identifier' => $context->identifier)); + return format_plural(count($names), '@identifier vocabulary is "@machine_names"', '@identifier vocabulary is one of "@machine_names"', array( + '@machine_names' => implode(', ', $names), + '@identifier' => $context->identifier + )); } +/** + * Helper function to map the vids from old features to the new machine_name. + * + * Add the machine_name key to $conf if the vids key exist. + * + * @param array $conf + * The configuration of this plugin. + */ +function _ctools_term_vocabulary_ctools_access_map_vids(&$conf) { + if (!empty($conf['vids'])) { + $conf['machine_name'] = array(); + $vocabularies = taxonomy_get_vocabularies(); + foreach ($conf['vids'] as $vid) { + $machine_name = $vocabularies[$vid]->machine_name; + $conf['machine_name'][$machine_name] = $vocabularies[$vid]->machine_name; + } + } +} + + diff --git a/sites/all/modules/contrib/dev/ctools/plugins/arguments/entity_id.inc b/sites/all/modules/contrib/dev/ctools/plugins/arguments/entity_id.inc index 451d444c..3063fefd 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/arguments/entity_id.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/arguments/entity_id.inc @@ -3,7 +3,7 @@ /** * @file * - * Plugin to provide an argument handler for all entity ids + * Plugin to provide an argument handler for all entity ids. */ /** @@ -16,6 +16,10 @@ $plugin = array( 'context' => 'ctools_argument_entity_id_context', 'get child' => 'ctools_argument_entity_id_get_child', 'get children' => 'ctools_argument_entity_id_get_children', + 'default' => array( + 'entity_id' => '', + ), + 'placeholder form' => 'ctools_argument_entity_id_ctools_argument_placeholder', ); function ctools_argument_entity_id_get_child($plugin, $parent, $child) { @@ -37,6 +41,7 @@ function ctools_argument_entity_id_get_children($original_plugin, $parent) { $plugins[$plugin_id] = $plugin; } drupal_alter('ctools_entity_contexts', $plugins); + return $plugins; } @@ -56,15 +61,87 @@ function ctools_argument_entity_id_context($arg = NULL, $conf = NULL, $empty = F return ctools_context_create('entity:' . $entity_type, $arg); } + // Trim spaces and other garbage. + $arg = trim($arg); + if (!is_numeric($arg)) { + $preg_matches = array(); + $match = preg_match('/\[id: (\d+)\]/', $arg, $preg_matches); + if (!$match) { + $match = preg_match('/^id: (\d+)/', $arg, $preg_matches); + } + + if ($match) { + $id = $preg_matches[1]; + } + if (isset($id) && is_numeric($id)) { + return ctools_context_create('entity:' . $entity_type, $id); + } return FALSE; } - $entity = entity_load($entity_type, array($arg)); - if (!$entity) { + $entities = entity_load($entity_type, array($arg)); + if (empty($entities)) { return FALSE; } - return ctools_context_create('entity:' . $entity_type, $entity[$arg]); + return ctools_context_create('entity:' . $entity_type, reset($entities)); } +function ctools_argument_entity_id_settings_form(&$form, &$form_state, $conf) { + $plugin = &$form_state['plugin']; + + $form['settings']['entity'] = array( + '#title' => t('Enter the title or ID of a @entity entity', array('@entity' => $plugin['keyword'])), + '#type' => 'textfield', + '#maxlength' => 512, + '#autocomplete_path' => 'ctools/autocomplete/' . $plugin['keyword'], + '#weight' => -10, + ); + + if (!empty($conf['entity_id'])) { + $info = entity_load($plugin['keyword'], array($conf['entity_id'])); + $info = $info[$conf['entity_id']]; + if ($info) { + $entity = entity_get_info($plugin['keyword']); + $uri = entity_uri($plugin['keyword'], $info); + if (is_array($uri) && $entity['entity keys']['label']) { + $link = l(t("'%title' [%type id %id]", array('%title' => $info->{$entity['entity keys']['label']}, '%type' => $plugin['keyword'], '%id' => $conf['entity_id'])), $uri['path'], array('attributes' => array('target' => '_blank', 'title' => t('Open in new window')), 'html' => TRUE)); + } + elseif (is_array($uri)) { + $link = l(t("[%type id %id]", array('%type' => $plugin['keyword'], '%id' => $conf['entity_id'])), $uri['path'], array('attributes' => array('target' => '_blank', 'title' => t('Open in new window')), 'html' => TRUE)); + } + elseif ($entity['entity keys']['label']) { + $link = l(t("'%title' [%type id %id]", array('%title' => $info->{$entity['entity keys']['label']}, '%type' => $plugin['keyword'], '%id' => $conf['entity_id'])), file_create_url($uri), array('attributes' => array('target' => '_blank', 'title' => t('Open in new window')), 'html' => TRUE)); + } + else { + $link = t("[%type id %id]", array('%type' => $plugin['keyword'], '%id' => $conf['entity_id'])); + } + $form['settings']['entity']['#description'] = t('Currently set to !link', array('!link' => $link)); + } + } + + $form['settings']['entity_id'] = array( + '#type' => 'value', + '#value' => isset($conf['entity_id']) ? $conf['entity_id'] : '', + ); + + $form['settings']['entity_type'] = array( + '#type' => 'value', + '#value' => $plugin['keyword'], + ); + + return $form; +} + +function ctools_argument_entity_id_ctools_argument_placeholder($conf) { + $conf = array( + '#title' => t('Enter the title or ID of a @entity entity', array('@entity' => $conf['keyword'])), + '#type' => 'textfield', + '#maxlength' => 512, + '#autocomplete_path' => 'ctools/autocomplete/' . $conf['keyword'], + '#weight' => -10, + ); + + return $conf; +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/arguments/rid.inc b/sites/all/modules/contrib/dev/ctools/plugins/arguments/rid.inc index dd30848e..2661153b 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/arguments/rid.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/arguments/rid.inc @@ -39,7 +39,7 @@ function ctools_argument_rid_context($arg = NULL, $conf = NULL, $empty = FALSE) return FALSE; } - $nid = db_query('SELECT nid FROM {node_revisions} WHERE vid = :vid', array(':vid' => $arg))->fetchField(); + $nid = db_query('SELECT nid FROM {node_revision} WHERE vid = :vid', array(':vid' => $arg))->fetchField(); $node = node_load($nid, $arg); if (!$node) { return FALSE; diff --git a/sites/all/modules/contrib/dev/ctools/plugins/cache/export_ui.inc b/sites/all/modules/contrib/dev/ctools/plugins/cache/export_ui.inc new file mode 100644 index 00000000..53483a53 --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/plugins/cache/export_ui.inc @@ -0,0 +1,39 @@ + t('Export UI wizard cache'), + 'cache get' => 'ctools_cache_export_ui_cache_get', + 'cache set' => 'ctools_cache_export_ui_cache_set', + // Some operations use a 'finalize' but that really just means set + // for us, since we're not using temporary storage for subsystems. + 'cache finalize' => 'ctools_cache_export_ui_cache_set', +); + +function ctools_cache_export_ui_cache_get($plugin_name, $key) { + ctools_include('export-ui'); + $plugin = ctools_get_export_ui($plugin_name); + $handler = ctools_export_ui_get_handler($plugin); + if ($handler) { + $item = $handler->edit_cache_get($key); + if (!$item) { + $item = ctools_export_crud_load($handler->plugin['schema'], $key); + } + return $item; + } +} + +function ctools_cache_export_ui_cache_set($plugin_name, $key, $item) { + ctools_include('export-ui'); + $plugin = ctools_get_export_ui($plugin_name); + $handler = ctools_export_ui_get_handler($plugin); + if ($handler) { + return $handler->edit_cache_set_key($item, $key); + } +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/cache/simple.inc b/sites/all/modules/contrib/dev/ctools/plugins/cache/simple.inc new file mode 100644 index 00000000..570398ba --- /dev/null +++ b/sites/all/modules/contrib/dev/ctools/plugins/cache/simple.inc @@ -0,0 +1,51 @@ + t('Simple'), + 'cache get' => 'ctools_cache_simple_cache_get', + 'cache set' => 'ctools_cache_simple_cache_set', + 'cache clear' => 'ctools_cache_simple_cache_clear', +); + +function ctools_cache_simple_cache_get($data, $key) { + ctools_include('object-cache'); + + // Ensure that if there is somehow no data, we at least don't stomp on other + // people's caches. + if (empty($data)) { + $data = 'simple_cache_plugin'; + } + + return ctools_object_cache_get($data, $key); +} + +function ctools_cache_simple_cache_set($data, $key, $object) { + ctools_include('object-cache'); + + // Ensure that if there is somehow no data, we at least don't stomp on other + // people's caches. + if (empty($data)) { + $data = 'simple_cache_plugin'; + } + + return ctools_object_cache_set($data, $key, $object); +} + +function ctools_cache_simple_cache_clear($data, $key) { + ctools_include('object-cache'); + + // Ensure that if there is somehow no data, we at least don't stomp on other + // people's caches. + if (empty($data)) { + $data = 'simple_cache_plugin'; + } + + return ctools_object_cache_clear($data, $key); +} diff --git a/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc b/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc index 9d55e8ac..4d4c31c3 100644 --- a/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc +++ b/sites/all/modules/contrib/dev/ctools/plugins/content_types/block/block.inc @@ -40,6 +40,11 @@ function ctools_block_content_type_content_type($subtype_id) { * of the form "$module . '_ctools_block_info'". */ function ctools_block_content_type_content_types() { + $types = &drupal_static(__FUNCTION__); + if (isset($types)) { + return $types; + } + $types = array(); foreach (module_implements('block_info') as $module) { $module_blocks = module_invoke($module, 'block_info'); @@ -143,27 +148,32 @@ function ctools_block_content_type_render($subtype, $conf) { $block = module_invoke($module, 'block_view', $delta); if (!empty($info)) { + // Valid PHP function names cannot contain hyphens. + $block_delta = str_replace('-', '_', $delta); + // Allow modules to modify the block before it is viewed, via either // hook_block_view_alter() or hook_block_view_MODULE_DELTA_alter(). - drupal_alter(array('block_view', "block_view_{$module}_{$delta}"), $block, $info); + drupal_alter(array('block_view', "block_view_{$module}_{$block_delta}"), $block, $info); } - $block = (object) $block; if (empty($block)) { return; } + $block = (object) $block; $block->module = $module; $block->delta = $delta; - if ($module == 'block' && !empty($info) && isset($info->title)) { - $block->title = $info->title; - } - else if (isset($block->subject)) { - $block->title = $block->subject; - } - else { - $block->title = NULL; + if (!isset($block->title)) { + if ($module == 'block' && !empty($info) && isset($info->title)) { + $block->title = $info->title; + } + else if (isset($block->subject)) { + $block->title = $block->subject; + } + else { + $block->title = NULL; + } } if (module_exists('block') && user_access('administer blocks')) { @@ -286,13 +296,18 @@ function ctools_block_content_type_admin_info($subtype, $conf) { list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf); $block = (object) module_invoke($module, 'block_view', $delta); - // Sanitize the block because "; + simplenews_subscribe_user($xss_mail, $this->getRandomNewsletter(), FALSE); + $this->drupalGet('admin/people/simplenews'); + $this->assertNoRaw($xss_mail); + $this->assertRaw(check_plain($xss_mail)); + + $xss_subscriber = simplenews_subscriber_load_by_mail($xss_mail); + $this->drupalGet('admin/people/simplenews/users/edit/' . $xss_subscriber->snid); + $this->assertNoRaw($xss_mail); + $this->assertRaw(check_plain($xss_mail)); } /** @@ -1611,7 +1627,7 @@ class SimpleNewsI18nTestCase extends SimplenewsTestCase { /** * Implementation of getInfo(). */ - function getInfo() { + static function getInfo() { return array( 'name' => t('Simplenews I18n'), 'description' => t('Translation of newsletter categories'), @@ -2019,7 +2035,7 @@ class SimplenewsSendTestCase extends SimplenewsTestCase { /** * Implementation of getInfo(). */ - function getInfo() { + static function getInfo() { return array( 'name' => t('Sending newsletters'), 'description' => t('Creating and sending of newsletters, different send processes (with/without cron, send on publish)'), @@ -2546,7 +2562,7 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase { /** * Implementation of getInfo(). */ - function getInfo() { + static function getInfo() { return array( 'name' => t('Source tests'), 'description' => t('Tests for the new source interfaces and concepts.'), @@ -2929,7 +2945,7 @@ class SimplenewsSourceTestCase extends SimplenewsTestCase { */ class SimplenewsUnitTest extends DrupalUnitTestCase { - function getInfo() { + static function getInfo() { return array( 'name' => 'Unit tests', 'description' => 'Unit tests for certain functions.', diff --git a/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_content_access_integration/logintoboggan_content_access_integration.info b/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_content_access_integration/logintoboggan_content_access_integration.info index 70bd9c51..c93a8b25 100644 --- a/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_content_access_integration/logintoboggan_content_access_integration.info +++ b/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_content_access_integration/logintoboggan_content_access_integration.info @@ -6,9 +6,9 @@ core = "7.x" dependencies[] = logintoboggan dependencies[] = content_access -; Information added by drupal.org packaging script on 2013-02-04 -version = "7.x-1.3+6-dev" +; Information added by Drupal.org packaging script on 2014-07-08 +version = "7.x-1.4" core = "7.x" project = "logintoboggan" -datestamp = "1359940268" +datestamp = "1404818634" diff --git a/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_rules/logintoboggan_rules.info b/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_rules/logintoboggan_rules.info index 6f3006ca..b2c305fd 100644 --- a/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_rules/logintoboggan_rules.info +++ b/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_rules/logintoboggan_rules.info @@ -6,9 +6,9 @@ core = "7.x" dependencies[] = logintoboggan dependencies[] = rules -; Information added by drupal.org packaging script on 2013-02-04 -version = "7.x-1.3+6-dev" +; Information added by Drupal.org packaging script on 2014-07-08 +version = "7.x-1.4" core = "7.x" project = "logintoboggan" -datestamp = "1359940268" +datestamp = "1404818634" diff --git a/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_variable/logintoboggan_variable.info b/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_variable/logintoboggan_variable.info index 912e5073..bed3a76f 100644 --- a/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_variable/logintoboggan_variable.info +++ b/sites/all/modules/contrib/users/logintoboggan/contrib/logintoboggan_variable/logintoboggan_variable.info @@ -5,9 +5,9 @@ core = "7.x" dependencies[] = logintoboggan dependencies[] = variable -; Information added by drupal.org packaging script on 2013-02-04 -version = "7.x-1.3+6-dev" +; Information added by Drupal.org packaging script on 2014-07-08 +version = "7.x-1.4" core = "7.x" project = "logintoboggan" -datestamp = "1359940268" +datestamp = "1404818634" diff --git a/sites/all/modules/contrib/users/logintoboggan/logintoboggan.info b/sites/all/modules/contrib/users/logintoboggan/logintoboggan.info index 298f28fb..14eef6e3 100644 --- a/sites/all/modules/contrib/users/logintoboggan/logintoboggan.info +++ b/sites/all/modules/contrib/users/logintoboggan/logintoboggan.info @@ -7,9 +7,9 @@ configure = admin/config/system/logintoboggan stylesheets[all][] = logintoboggan.css -; Information added by drupal.org packaging script on 2013-02-04 -version = "7.x-1.3+6-dev" +; Information added by Drupal.org packaging script on 2014-07-08 +version = "7.x-1.4" core = "7.x" project = "logintoboggan" -datestamp = "1359940268" +datestamp = "1404818634" diff --git a/sites/all/modules/contrib/users/logintoboggan/logintoboggan.install b/sites/all/modules/contrib/users/logintoboggan/logintoboggan.install index 88d3c3bb..f5f05190 100644 --- a/sites/all/modules/contrib/users/logintoboggan/logintoboggan.install +++ b/sites/all/modules/contrib/users/logintoboggan/logintoboggan.install @@ -34,7 +34,7 @@ function logintoboggan_update_7000(&$sandbox) { ), ); - update_fix_d7_block_deltas($sandbox, $renamed_deltas, array()); + update_fix_d7_block_deltas($sandbox, $renamed_deltas); } /** diff --git a/sites/all/modules/contrib/users/logintoboggan/logintoboggan.module b/sites/all/modules/contrib/users/logintoboggan/logintoboggan.module index 3e47dee7..cbfa73ad 100644 --- a/sites/all/modules/contrib/users/logintoboggan/logintoboggan.module +++ b/sites/all/modules/contrib/users/logintoboggan/logintoboggan.module @@ -447,8 +447,9 @@ function logintoboggan_user_register_submit($form, &$form_state) { $pre_auth = logintoboggan_validating_id() != DRUPAL_AUTHENTICATED_RID; // If we are allowing user selected passwords then skip the auto-generate function - // The new user's status will be 1 (visitors can create own accounts) if reg_pass_set == 1 - // Immediate login, we are going to assign a pre-auth role, until email validation completed + // The new user's status should default to the site settings, unless reg_passwd_set == 1 + // (immediate login, we are going to assign a pre-auth role), and we want to allow + // admin approval accounts access to the site. if ($reg_pass_set) { $pass = $form_state['values']['pass']; $status = 1; @@ -504,7 +505,7 @@ function logintoboggan_user_register_submit($form, &$form_state) { // 3. Visitors can create their own accounts. $message = t('Further instructions have been sent to your e-mail address.'); if($reg_pass_set && $pre_auth && variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) == USER_REGISTER_VISITORS) { - $message = t('A validation e-mail has been sent to your e-mail address. You will need to follow the instructions in that message in order to gain full access to the site.'); + $message = t('A validation e-mail has been sent to your e-mail address. In order to gain full access to the site, you will need to follow the instructions in that message.'); } if (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) == USER_REGISTER_VISITORS) { @@ -559,12 +560,6 @@ function logintoboggan_user_login_validate($form, &$form_state) { * @ingroup logintoboggan_form */ function logintoboggan_user_register_validate($form, &$form_state) { - //Check to see whether our username matches any email address currently in the system. - if($mail = db_query("SELECT mail FROM {users} WHERE LOWER(:name) = LOWER(mail)", array( - ':name' => $form_state['values']['name'], - ))->fetchField()) { - form_set_error('name', t('This e-mail has already been taken by another user.')); - } //Check to see whether our e-mail address matches the confirm address if enabled. if (variable_get('logintoboggan_confirm_email_at_registration', 0) && isset($form_state['values']['conf_mail'])) { if ($form_state['values']['mail'] != $form_state['values']['conf_mail']) { @@ -624,11 +619,11 @@ function logintoboggan_user_edit_validate($form, &$form_state) { * * @ingroup logintoboggan_core * - * This is the best current place to dynamically remove the authenticated role - * from the user object on initial page load. hook_init() is too late, as menu - * access checks have already been performed. + * This is currently the best place to dynamically remove the authenticated role + * from the user object, hook_boot() allows us to act on the user object before + * any access checks are performed. */ -function logintoboggan_menu_get_item_alter() { +function logintoboggan_boot() { global $user; // Make sure any user with pre-auth role doesn't have authenticated user role @@ -749,6 +744,12 @@ function logintoboggan_revalidate_access($account) { * Which form to display, should be 'login' or 'register'. */ function logintoboggan_unified_login_page($active_form = 'login') { + // Sanitise the $active_form text as it comes direct from the url. + // It should only ever be 'login' or 'register', so default to 'login'. + if ($active_form != 'login' && $active_form != 'register') { + $active_form = 'login'; + } + global $user; if ($user->uid) { menu_set_active_item('user/' . $user->uid); diff --git a/sites/all/modules/contrib/users/user_import/supported/user.inc b/sites/all/modules/contrib/users/user_import/supported/user.inc index 5011b8fc..0469b174 100644 --- a/sites/all/modules/contrib/users/user_import/supported/user.inc +++ b/sites/all/modules/contrib/users/user_import/supported/user.inc @@ -83,7 +83,7 @@ function user_user_import_data($settings, $update_setting, $column_settings, $mo $parsed['year'] ); - if (!empty($timestamp) && is_numerric($timestamp)) { + if (!empty($timestamp) && is_numeric($timestamp)) { $value = $timestamp; } } diff --git a/sites/all/modules/contrib/users/user_import/user_import.admin.inc b/sites/all/modules/contrib/users/user_import/user_import.admin.inc index 161c71bb..1a6a65b8 100644 --- a/sites/all/modules/contrib/users/user_import/user_import.admin.inc +++ b/sites/all/modules/contrib/users/user_import/user_import.admin.inc @@ -5,6 +5,26 @@ * Provide administration configuration pages to import users. */ +function user_import_confirm_delete($form, &$form_state, $import_id) { + + $form['import_id'] = array( + '#type' => 'value', + '#value' => $import_id, + ); + + return confirm_form($form, + t('Are you sure you want to delete the user import process?'), + 'admin/people/user_import', + t('Deleting a user import process will also delete the file from which user data was being read. This action cannot be undone.'), + t('Delete'), t('Cancel')); +} + +function user_import_confirm_delete_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + user_import_delete($form_state['values']['import_id']); + } +} + function user_import_list($action = NULL, $import_id = NULL) { // clear incomplete imports @@ -70,6 +90,28 @@ function user_import_preferences($import_id = NULL, $template_id = NULL) { return $output; } + + +function user_import_confirm_continue($form, &$form_state, $import_id) { + + $form['import_id'] = array( + '#type' => 'value', + '#value' => $import_id, + ); + + return confirm_form($form, + t('Are you sure you want to continue to import users?'), + 'admin/people/user_import', + t('Restart user import from where it last finished.'), + t('Continue'), t('Cancel')); +} + +function user_import_confirm_continue_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + user_import_continue($form_state['values']['import_id']); + } +} + function user_import_continue($import_id = NULL) { if (!empty($import_id) && is_numeric($import_id)) { @@ -81,6 +123,26 @@ function user_import_continue($import_id = NULL) { drupal_goto('admin/people/user_import'); } +function user_import_confirm_import($form, &$form_state, $import_id) { + + $form['import_id'] = array( + '#type' => 'value', + '#value' => $import_id, + ); + + return confirm_form($form, + t('Are you sure you want to import users?'), + 'admin/people/user_import', + t('Start importing users.'), + t('Import'), t('Cancel')); +} + +function user_import_confirm_import_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + user_import_import($form_state['values']['import_id']); + } +} + function user_import_import($import_id = NULL) { if (!empty($import_id) && is_numeric($import_id)) { diff --git a/sites/all/modules/contrib/users/user_import/user_import.info b/sites/all/modules/contrib/users/user_import/user_import.info index 99ac2a2d..baf61586 100644 --- a/sites/all/modules/contrib/users/user_import/user_import.info +++ b/sites/all/modules/contrib/users/user_import/user_import.info @@ -11,9 +11,9 @@ files[] = user_import.test -; Information added by Drupal.org packaging script on 2014-03-09 -version = "7.x-2.2" +; Information added by Drupal.org packaging script on 2015-04-01 +version = "7.x-2.3" core = "7.x" project = "user_import" -datestamp = "1394331207" +datestamp = "1427908388" diff --git a/sites/all/modules/contrib/users/user_import/user_import.module b/sites/all/modules/contrib/users/user_import/user_import.module index 4160a58d..c52f93ed 100644 --- a/sites/all/modules/contrib/users/user_import/user_import.module +++ b/sites/all/modules/contrib/users/user_import/user_import.module @@ -54,6 +54,10 @@ function user_import_permission() { 'title' => t('Import users'), 'description' => t('Import users.'), ), + 'limited user import' => array( + 'title' => t('Import users Reports'), + 'description' => t('View import error reports.'), + ), ); } @@ -84,23 +88,26 @@ function user_import_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'user_import.admin.inc', ); - $items['admin/people/user_import/continue'] = array( + $items['admin/people/user_import/continue/%'] = array( 'title' => 'Continue', - 'page callback' => 'user_import_continue', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('user_import_confirm_continue', 4), 'access arguments' => array('import users'), 'type' => MENU_CALLBACK, 'file' => 'user_import.admin.inc', ); - $items['admin/people/user_import/import'] = array( + $items['admin/people/user_import/import/%'] = array( 'title' => 'Import', - 'page callback' => 'user_import_import', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('user_import_confirm_import', 4), 'access arguments' => array('import users'), 'type' => MENU_CALLBACK, 'file' => 'user_import.admin.inc', ); - $items['admin/people/user_import/delete'] = array( + $items['admin/people/user_import/delete/%'] = array( 'title' => 'Delete Import', - 'page callback' => 'user_import_delete', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('user_import_confirm_delete', 4), 'access arguments' => array('import users'), 'type' => MENU_CALLBACK, 'file' => 'user_import.admin.inc', @@ -113,15 +120,10 @@ function user_import_menu() { 'type' => MENU_LOCAL_TASK, 'file' => 'user_import.admin.inc', ); - $items['user_import/delete'] = array( - 'title' => 'Remove Info', - 'page callback' => 'user_import_limited_delete', - 'type' => MENU_CALLBACK, - 'access arguments' => array('limited user import'), - ); - $items['user_import/errors'] = array( + $items['admin/people/user_import/errors/%'] = array( 'title' => 'Import Errors', 'page callback' => 'user_import_limited_errors', + 'page arguments' => array(4), 'type' => MENU_CALLBACK, 'access arguments' => array('limited user import'), ); @@ -212,11 +214,8 @@ function user_import_trigger_imports() { } } - return; - - // Get template. $settings = _user_import_settings_select(2); @@ -277,17 +276,17 @@ function user_import_content_type_submit($form, &$form_state) { // - - - - - - - - PAGES - - - - - - - - function user_import_limited_errors($import_id = NULL, $template_id = NULL) { - if (empty($import_id) || !is_numeric($import_id)) { - drupal_goto('user_import/' . $template_id); + drupal_goto('admin/people/user_import/' . $template_id); } $pager_id = 1; $max = 25; $import = _user_import_settings_select($import_id); $output = ''; + $file_lines = array(); - $total = db_query('SELECT count(data) FROM {user_import_errors} WHERE :import_id = %d', array(':import_id' => $import['import_id']))->fetchField(); + $total = db_query('SELECT count(data) FROM {user_import_errors} WHERE import_id = :import_id', array(':import_id' => $import_id))->fetchField(); if (empty($total)) { @@ -301,12 +300,13 @@ function user_import_limited_errors($import_id = NULL, $template_id = NULL) { array('data' => t('Errors'), 'field' => 'errors') ); - $query = db_select('user_import_errors') + $query = db_select('user_import_errors', 'uie') + ->fields('uie') ->extend('PagerDefault') ->extend('TableSort'); $query - ->condition('import_id', $import['import_id']) + ->condition('import_id', $import_id, '=') ->limit($max) ->orderByHeader($header); @@ -317,10 +317,9 @@ function user_import_limited_errors($import_id = NULL, $template_id = NULL) { } $output .= theme('user_import_errors_display', array('import' => $import, 'file_lines' => $file_lines, 'total' => $total)); - $output .= theme('pager', array('max' => $max, 'pager_id' => $pager_id)); } - $output .= l(t('Return'), "user_import/$template_id/$import_id"); + $output .= l(t('Return'), "admin/people/user_import"); return $output; } @@ -331,7 +330,8 @@ function user_import_limited_errors($import_id = NULL, $template_id = NULL) { * @param null $template_id */ function user_import_limited_delete($import_id = NULL, $template_id = NULL) { - user_import_delete($import_id, "user_import/$template_id"); + module_load_include('inc', 'user_import', 'user_import.admin'); + user_import_delete($import_id, "admin/people/user_import"); } // - - - - - - - - THEMES - - - - - - - - diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_area_messages.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_area_messages.inc new file mode 100644 index 00000000..eb1e22ae --- /dev/null +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_area_messages.inc @@ -0,0 +1,34 @@ +options['empty'])) { + $return = theme('status_messages'); + } + return $return; + } + +} diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc index 42617e7a..5a5ec004 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_argument.inc @@ -423,11 +423,13 @@ class views_handler_argument extends views_handler { $plugin->options_validate($form['argument_default'][$default_id], $form_state, $form_state['values']['options']['argument_default'][$default_id]); } - // summary plugin - $summary_id = $form_state['values']['options']['summary']['format']; - $plugin = $this->get_plugin('style', $summary_id); - if ($plugin) { - $plugin->options_validate($form['summary']['options'][$summary_id], $form_state, $form_state['values']['options']['summary']['options'][$summary_id]); + // Validate summary plugin options if one is present. + if (isset($form_state['values']['options']['summary']['format'])) { + $summary_id = $form_state['values']['options']['summary']['format']; + $plugin = $this->get_plugin('style', $summary_id); + if ($plugin) { + $plugin->options_validate($form['summary']['options'][$summary_id], $form_state, $form_state['values']['options']['summary']['options'][$summary_id]); + } } $validate_id = $form_state['values']['options']['validate']['type']; @@ -453,14 +455,16 @@ class views_handler_argument extends views_handler { $form_state['values']['options']['default_argument_options'] = $options; } - // summary plugin - $summary_id = $form_state['values']['options']['summary']['format']; - $plugin = $this->get_plugin('style', $summary_id); - if ($plugin) { - $options = &$form_state['values']['options']['summary']['options'][$summary_id]; - $plugin->options_submit($form['summary']['options'][$summary_id], $form_state, $options); - // Copy the now submitted options to their final resting place so they get saved. - $form_state['values']['options']['summary_options'] = $options; + // Handle summary plugin options if one is present. + if (isset($form_state['values']['options']['summary']['format'])) { + $summary_id = $form_state['values']['options']['summary']['format']; + $plugin = $this->get_plugin('style', $summary_id); + if ($plugin) { + $options = &$form_state['values']['options']['summary']['options'][$summary_id]; + $plugin->options_submit($form['summary']['options'][$summary_id], $form_state, $options); + // Copy the now submitted options to their final resting place so they get saved. + $form_state['values']['options']['summary_options'] = $options; + } } $validate_id = $form_state['values']['options']['validate']['type']; diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_field_counter.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_field_counter.inc index 76213a65..e4a0ebff 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_field_counter.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_field_counter.inc @@ -14,6 +14,7 @@ class views_handler_field_counter extends views_handler_field { function option_definition() { $options = parent::option_definition(); $options['counter_start'] = array('default' => 1); + $options['reverse'] = array('default' => FALSE); return $options; } @@ -26,6 +27,13 @@ class views_handler_field_counter extends views_handler_field { '#size' => 2, ); + $form['reverse'] = array( + '#type' => 'checkbox', + '#title' => t('Reverse'), + '#default_value' => $this->options['reverse'], + '#description' => t('Reverse the counter.'), + ); + parent::options_form($form, $form_state); } @@ -34,16 +42,24 @@ class views_handler_field_counter extends views_handler_field { } function render($values) { + $reverse = empty($this->options['reverse']) ? 1 : -1; + // Note: 1 is subtracted from the counter start value below because the // counter value is incremented by 1 at the end of this function. - $count = is_numeric($this->options['counter_start']) ? $this->options['counter_start'] - 1 : 0; + $counter_start = is_numeric($this->options['counter_start']) ? $this->options['counter_start'] : 0; + $count = ($reverse == -1) ? count($this->view->result) + $counter_start : $counter_start -1; $pager = $this->view->query->pager; + // Get the base count of the pager. if ($pager->use_pager()) { - $count += ($pager->get_items_per_page() * $pager->get_current_page() + $pager->get_offset()); + if ($reverse == -1) { + $count = ($pager->total_items + $counter_start - ($pager->get_current_page() * $pager->get_items_per_page()) + $pager->get_offset()); + } else { + $count += (($pager->get_items_per_page() * $pager->get_current_page() + $pager->get_offset())) * $reverse; + } } // Add the counter for the current site. - $count += $this->view->row_index + 1; + $count += ($this->view->row_index + 1) * $reverse; return $count; } diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_field_date.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_field_date.inc index 8517f0b5..f2c63710 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_field_date.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_field_date.inc @@ -16,6 +16,8 @@ class views_handler_field_date extends views_handler_field { $options['date_format'] = array('default' => 'small'); $options['custom_date_format'] = array('default' => ''); + $options['second_date_format_custom'] = array('default' => ''); + $options['second_date_format'] = array('default' => 'small'); $options['timezone'] = array('default' => ''); return $options; @@ -36,6 +38,7 @@ class views_handler_field_date extends views_handler_field { 'custom' => t('Custom'), 'raw time ago' => t('Time ago'), 'time ago' => t('Time ago (with "ago" appended)'), + 'today time ago' => t('Time ago (with "ago" appended) for today\'s date, but not for other dates'), 'raw time hence' => t('Time hence'), 'time hence' => t('Time hence (with "hence" appended)'), 'raw time span' => t('Time span (future dates have "-" prepended)'), @@ -49,8 +52,39 @@ class views_handler_field_date extends views_handler_field { '#title' => t('Custom date format'), '#description' => t('If "Custom", see the PHP manual for date formats. Otherwise, enter the number of different time units to display, which defaults to 2.', array('@url' => 'http://php.net/manual/function.date.php')), '#default_value' => isset($this->options['custom_date_format']) ? $this->options['custom_date_format'] : '', - '#dependency' => array('edit-options-date-format' => array('custom', 'raw time ago', 'time ago', 'raw time hence', 'time hence', 'raw time span', 'time span', 'raw time span', 'inverse time span', 'time span')), + '#dependency' => array('edit-options-date-format' => array('custom', 'raw time ago', 'time ago', 'today time ago', 'raw time hence', 'time hence', 'raw time span', 'time span', 'raw time span', 'inverse time span', 'time span')), ); + $form['second_date_format'] = array( + '#type' => 'select', + '#title' => t('Second date format'), + '#options' => $date_formats + array( + 'custom' => t('Custom'), + ), + '#description' => t('The date format which will be used for rendering dates other than today.'), + '#default_value' => isset($this->options['second_date_format']) ? $this->options['second_date_format'] : 'small', + '#dependency' => array('edit-options-date-format' => array('today time ago')), + ); + $form['second_date_format_custom'] = array( + '#type' => 'textfield', + '#title' => t('Custom date format of second date'), + '#description' => t('If "Custom" is selected in "Second date format", see the PHP manual for date formats. Otherwise, enter the number of different time units to display, which defaults to 2.', array('@url' => 'http://php.net/manual/function.date.php')), + '#default_value' => isset($this->options['second_date_format_custom']) ? $this->options['second_date_format_custom'] : '', + // We have to use states instead of ctools dependency because dependency + // doesn't handle multiple conditions. + '#states' => array( + 'visible' => array( + '#edit-options-date-format' => array('value' => 'today time ago'), + '#edit-options-second-date-format' => array('value' => 'custom'), + ), + ), + // We have to use ctools dependency too because states doesn't add the + // correct left margin to the element's wrapper. + '#dependency' => array( + // This condition is handled by form API's states. +// 'edit-options-date-format' => array('today time ago'), + 'edit-options-second-date-format' => array('custom'), + ), + ); $form['timezone'] = array( '#type' => 'select', '#title' => t('Timezone'), @@ -66,7 +100,7 @@ class views_handler_field_date extends views_handler_field { function render($values) { $value = $this->get_value($values); $format = $this->options['date_format']; - if (in_array($format, array('custom', 'raw time ago', 'time ago', 'raw time hence', 'time hence', 'raw time span', 'time span', 'raw time span', 'inverse time span', 'time span'))) { + if (in_array($format, array('custom', 'raw time ago', 'time ago', 'today time ago', 'raw time hence', 'time hence', 'raw time span', 'time span', 'raw time span', 'inverse time span', 'time span'))) { $custom_format = $this->options['custom_date_format']; } @@ -78,6 +112,21 @@ class views_handler_field_date extends views_handler_field { return format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2); case 'time ago': return t('%time ago', array('%time' => format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2))); + case 'today time ago': + $second_format = $this->options['second_date_format']; + $second_custom_format = $this->options['second_date_format_custom']; + if (format_date(REQUEST_TIME, 'custom', 'Y-m-d', $timezone) == format_date($value, 'custom', 'Y-m-d', $timezone)) { + return t('%time ago', array('%time' => format_interval($time_diff, is_numeric($custom_format) ? $custom_format : 2))); + } + elseif ($second_format == 'custom') { + if ($second_custom_format == 'r') { + return format_date($value, $second_format, $second_custom_format, $timezone, 'en'); + } + return format_date($value, $second_format, $second_custom_format, $timezone); + } + else { + return format_date($value, $this->options['second_date_format'], '', $timezone); + } case 'raw time hence': return format_interval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2); case 'time hence': diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_filter.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_filter.inc index f5db70f9..8583605b 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_filter.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_filter.inc @@ -91,7 +91,11 @@ class views_handler_filter extends views_handler { } if ($this->multiple_exposed_input()) { - $this->group_info = array_filter($options['group_info']['default_group_multiple']); + $this->group_info = NULL; + if (!empty($options['group_info']['default_group_multiple'])) { + $this->group_info = array_filter($options['group_info']['default_group_multiple']); + } + $this->options['expose']['multiple'] = TRUE; } @@ -116,6 +120,7 @@ class views_handler_filter extends views_handler { 'label' => array('default' => '', 'translatable' => TRUE), 'description' => array('default' => '', 'translatable' => TRUE), 'use_operator' => array('default' => FALSE, 'bool' => TRUE), + 'operator_label' => array('default' => '', 'translatable' => TRUE), 'operator' => array('default' => ''), 'identifier' => array('default' => ''), 'required' => array('default' => FALSE, 'bool' => TRUE), @@ -510,6 +515,16 @@ class views_handler_filter extends views_handler { '#description' => t('Allow the user to choose the operator.'), '#default_value' => !empty($this->options['expose']['use_operator']), ); + $form['expose']['operator_label'] = array( + '#type' => 'textfield', + '#default_value' => $this->options['expose']['operator_label'], + '#title' => t('Operator label'), + '#size' => 40, + '#description' => t('This will appear before your operator select field.'), + '#dependency' => array( + 'edit-options-expose-use-operator' => array(1) + ), + ); $form['expose']['operator_id'] = array( '#type' => 'textfield', '#default_value' => $this->options['expose']['operator_id'], @@ -754,10 +769,8 @@ class views_handler_filter extends views_handler { $operator = $this->options['expose']['operator_id']; $this->operator_form($form, $form_state); $form[$operator] = $form['operator']; - - if (isset($form[$operator]['#title'])) { - unset($form[$operator]['#title']); - } + $form[$operator]['#title'] = $this->options['expose']['operator_label']; + $form[$operator]['#title_display'] = 'invisible'; $this->exposed_translate($form[$operator], 'operator'); diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_filter_boolean_operator_string.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_filter_boolean_operator_string.inc index b49dde94..080ac50a 100644 --- a/sites/all/modules/contrib/views/views/handlers/views_handler_filter_boolean_operator_string.inc +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_filter_boolean_operator_string.inc @@ -30,6 +30,6 @@ class views_handler_filter_boolean_operator_string extends views_handler_filter_ else { $where .= "<> ''"; } - $this->query->add_where($this->options['group'], $where); + $this->query->add_where_expression($this->options['group'], $where); } } diff --git a/sites/all/modules/contrib/views/views/handlers/views_handler_filter_fields_compare.inc b/sites/all/modules/contrib/views/views/handlers/views_handler_filter_fields_compare.inc new file mode 100644 index 00000000..fe94ce76 --- /dev/null +++ b/sites/all/modules/contrib/views/views/handlers/views_handler_filter_fields_compare.inc @@ -0,0 +1,142 @@ + ''); + + return $options; + } + + /** + * Provide a list of all operators. + */ + function fields_operator_options() { + return array( + '<' => t('Is less than'), + '<=' => t('Is less than or equal to'), + '=' => t('Is equal to'), + '<>' => t('Is not equal to'), + '>=' => t('Is greater than or equal to'), + '>' => t('Is greater than') + ); + } + + /** + * Provide a list of available fields. + */ + function field_options() { + $options = array(); + + $field_handlers = $this->view->display_handler->get_handlers('field'); + foreach ($field_handlers as $field => $handler) { + if ($handler->table != 'views') { + $options[$field] = $handler->ui_name(); + } + } + + return $options; + } + + /** + * Overrides views_handler_filter#options_form(). + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $field_options = $this->field_options(); + + $form['left_field'] = array( + '#type' => 'select', + '#title' => t('Left field'), + '#default_value' => $this->options['left_field'], + '#options' => $field_options, + '#weight' => -3, + ); + + $form['operator'] = array( + '#type' => 'select', + '#title' => t('Operator'), + '#default_value' => $this->options['operator'], + '#options' => $this->fields_operator_options(), + '#weight' => -2, + ); + + $form['right_field'] = array( + '#type' => 'select', + '#title' => t('Right field'), + '#default_value' => $this->options['right_field'], + '#options' => $field_options, + '#weight' => -1, + ); + + } + + /** + * Overrides views_handler_filter#query(). + * + * Build extra condition from existing fields (from existing joins). + */ + function query() { + $left = $this->options['left_field']; + $right = $this->options['right_field']; + + // Get all existing field handlers. + $field_handlers = $this->view->display_handler->get_handlers('field'); + + // Make sure the selected fields still exist. + if (!isset($field_handlers[$left], $field_handlers[$right])) { + return; + } + + // Get the left table and field. + $left_handler = $field_handlers[$left]; + $left_handler->set_relationship(); + $left_table_alias = $this->query->ensure_table($left_handler->table, $left_handler->relationship); + + // Get the left table and field. + $right_handler = $field_handlers[$right]; + $right_handler->set_relationship(); + $right_table_alias = $this->query->ensure_table($right_handler->table, $right_handler->relationship); + + // Build piece of SQL. + $snippet = + $left_table_alias . '.' . $left_handler->real_field . + ' ' . $this->options['operator'] . ' ' . + $right_table_alias . '.' . $right_handler->real_field; + + $this->query->add_where_expression($this->options['group'], $snippet); + } + + /** + * Overrides views_handler_filter#admin_summary(). + */ + function admin_summary() { + return check_plain( + $this->options['left_field'] . ' ' . + $this->options['operator'] . ' ' . + $this->options['right_field'] + ); + } + +} diff --git a/sites/all/modules/contrib/views/views/includes/admin.inc b/sites/all/modules/contrib/views/views/includes/admin.inc index 160a61a1..1643b34f 100644 --- a/sites/all/modules/contrib/views/views/includes/admin.inc +++ b/sites/all/modules/contrib/views/views/includes/admin.inc @@ -408,7 +408,7 @@ function views_ui_add_form($form, &$form_state) { */ function views_element_validate_integer($element, &$form_state) { $value = $element['#value']; - if ($value !== '' && (!is_numeric($value) || intval($value) != $value)) { + if ($value !== '' && (!is_numeric($value) || intval($value) != $value || abs($value) != $value)) { form_error($element, t('%name must be a positive integer.', array('%name' => $element['#title']))); } } @@ -855,9 +855,6 @@ function views_ui_break_lock_confirm($form, &$form_state, $view) { } $cancel = 'admin/structure/views/view/' . $view->name . '/edit'; - if (!empty($_REQUEST['cancel'])) { - $cancel = $_REQUEST['cancel']; - } $account = user_load($view->locked->uid); return confirm_form($form, @@ -2964,7 +2961,7 @@ function views_ui_ajax_form($js, $key, $view, $display_id = '') { else { $output = array(); $output[] = views_ajax_command_dismiss_form(); - $output[] = views_ajax_command_show_buttons(); + $output[] = views_ajax_command_show_buttons(!empty($view->changed)); $output[] = views_ajax_command_trigger_preview(); if (!empty($form_state['#page_title'])) { $output[] = views_ajax_command_replace_title($form_state['#page_title']); diff --git a/sites/all/modules/contrib/views/views/includes/ajax.inc b/sites/all/modules/contrib/views/views/includes/ajax.inc index 39d8c6f3..cd633605 100644 --- a/sites/all/modules/contrib/views/views/includes/ajax.inc +++ b/sites/all/modules/contrib/views/views/includes/ajax.inc @@ -169,12 +169,16 @@ function views_ajax_command_scroll_top($selector) { /** * Shows Save and Cancel buttons. * + * @param bool $changed + * Whether of not the view has changed. + * * @return * An array suitable for use with the ajax_render() function. */ -function views_ajax_command_show_buttons() { +function views_ajax_command_show_buttons($changed) { $command = array( 'command' => 'viewsShowButtons', + 'changed' => (bool) $changed, ); return $command; } diff --git a/sites/all/modules/contrib/views/views/includes/base.inc b/sites/all/modules/contrib/views/views/includes/base.inc index 217bbec4..2d2ceb56 100644 --- a/sites/all/modules/contrib/views/views/includes/base.inc +++ b/sites/all/modules/contrib/views/views/includes/base.inc @@ -117,7 +117,7 @@ class views_object { $localization_keys = $this->localization_keys; } // but plugins don't because there isn't a common init() these days. - else if (!empty($this->is_plugin)) { + else if (!empty($this->is_plugin) && empty($localization_keys)) { if ($this->plugin_type != 'display') { $localization_keys = array($this->view->current_display); $localization_keys[] = $this->plugin_type; diff --git a/sites/all/modules/contrib/views/views/includes/cache.inc b/sites/all/modules/contrib/views/views/includes/cache.inc index 59c1733d..b74752f1 100644 --- a/sites/all/modules/contrib/views/views/includes/cache.inc +++ b/sites/all/modules/contrib/views/views/includes/cache.inc @@ -23,16 +23,31 @@ function _views_fetch_data($table = NULL, $move = TRUE, $reset = FALSE) { if ($table) { if (!isset($cache[$table])) { $cid = 'views_data:' . $table; - $data = views_cache_get($cid, TRUE); - if (!empty($data->data)) { + if ($data = views_cache_get($cid, TRUE)) { $cache[$table] = $data->data; } else { if (!$fully_loaded) { - // No cache entry, rebuild. - $cache = _views_fetch_data_build(); + // Try to load the full views cache. + if ($data = views_cache_get('views_data', TRUE)) { + $cache = $data->data; + } + else { + // No cache entry, rebuild. + $cache = _views_fetch_data_build(); + } $fully_loaded = TRUE; } + + // Write back a cache for this table. + if (isset($cache[$table])) { + views_cache_set($cid, $cache[$table], TRUE); + } + else { + // If there is still no information about that table, it is missing. + // Write an empty array to avoid repeated rebuilds. + views_cache_set($cid, array(), TRUE); + } } } if (isset($cache[$table])) { @@ -82,11 +97,6 @@ function _views_fetch_data_build() { // Keep a record with all data. views_cache_set('views_data', $cache, TRUE); - // Save data in seperate cache entries. - foreach ($cache as $key => $data) { - $cid = 'views_data:' . $key; - views_cache_set($cid, $data, TRUE); - } return $cache; } diff --git a/sites/all/modules/contrib/views/views/includes/handlers.inc b/sites/all/modules/contrib/views/views/includes/handlers.inc index 2a33d5d5..43461331 100644 --- a/sites/all/modules/contrib/views/views/includes/handlers.inc +++ b/sites/all/modules/contrib/views/views/includes/handlers.inc @@ -1581,7 +1581,7 @@ class views_join { // With an array of values, we need multiple placeholders and the // 'IN' operator is implicit. foreach ($info['value'] as $value) { - $placeholder_i = ':views_join_condition_' . $select_query->nextPlaceholder(); + $placeholder_i = $view_query->placeholder('views_join_condition_'); $arguments[$placeholder_i] = $value; } @@ -1591,10 +1591,9 @@ class views_join { else { // With a single value, the '=' operator is implicit. $operator = !empty($info['operator']) ? $info['operator'] : '='; - $placeholder = ':views_join_condition_' . $select_query->nextPlaceholder(); + $placeholder = $view_query->placeholder('views_join_condition_'); $arguments[$placeholder] = $info['value']; } - $extras[] = "$join_table$info[field] $operator $placeholder"; } diff --git a/sites/all/modules/contrib/views/views/includes/view.inc b/sites/all/modules/contrib/views/views/includes/view.inc index d8c0c1f5..d082a0b6 100644 --- a/sites/all/modules/contrib/views/views/includes/view.inc +++ b/sites/all/modules/contrib/views/views/includes/view.inc @@ -756,7 +756,7 @@ class view extends views_db_object { */ function _init_handler($key, $info) { // Load the requested items from the display onto the object. - $this->$key = $this->display_handler->get_handlers($key); + $this->$key = &$this->display_handler->get_handlers($key); // This reference deals with difficult PHP indirection. $handlers = &$this->$key; diff --git a/sites/all/modules/contrib/views/views/js/ajax.js b/sites/all/modules/contrib/views/views/js/ajax.js index 82b332f8..5c688549 100644 --- a/sites/all/modules/contrib/views/views/js/ajax.js +++ b/sites/all/modules/contrib/views/views/js/ajax.js @@ -61,7 +61,9 @@ Drupal.ajax.prototype.commands.viewsShowButtons = function (ajax, response, status) { $('div.views-edit-view div.form-actions').removeClass('js-hide'); - $('div.views-edit-view div.view-changed.messages').removeClass('js-hide'); + if (response.changed) { + $('div.views-edit-view div.view-changed.messages').removeClass('js-hide'); + } }; Drupal.ajax.prototype.commands.viewsTriggerPreview = function (ajax, response, status) { diff --git a/sites/all/modules/contrib/views/views/js/ajax_view.js b/sites/all/modules/contrib/views/views/js/ajax_view.js index e3bc8213..7d54c676 100644 --- a/sites/all/modules/contrib/views/views/js/ajax_view.js +++ b/sites/all/modules/contrib/views/views/js/ajax_view.js @@ -57,7 +57,7 @@ Drupal.views.ajaxView = function(settings) { this.settings = settings; // Add the ajax to exposed forms. - this.$exposed_form = $('form#views-exposed-form-'+ settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-')); + this.$exposed_form = this.$view.children('.view-filters').children('form'); this.$exposed_form.once(jQuery.proxy(this.attachExposedFormAjax, this)); // Add the ajax to pagers. @@ -66,6 +66,17 @@ Drupal.views.ajaxView = function(settings) { // to a given element. .filter(jQuery.proxy(this.filterNestedViews, this)) .once(jQuery.proxy(this.attachPagerAjax, this)); + + // Add a trigger to update this view specifically. In order to trigger a + // refresh use the following code. + // + // @code + // jQuery('.view-name').trigger('RefreshView'); + // @endcode + // Add a trigger to update this view specifically. + var self_settings = this.element_settings; + self_settings.event = 'RefreshView'; + this.refreshViewAjax = new Drupal.ajax(this.selector, this.$view, self_settings); }; Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() { diff --git a/sites/all/modules/contrib/views/views/js/jquery.ui.dialog.patch.js b/sites/all/modules/contrib/views/views/js/jquery.ui.dialog.patch.js index d00e6aba..3ac7704a 100644 --- a/sites/all/modules/contrib/views/views/js/jquery.ui.dialog.patch.js +++ b/sites/all/modules/contrib/views/views/js/jquery.ui.dialog.patch.js @@ -20,7 +20,7 @@ */ (function ($, undefined) { - if ($.ui && $.ui.dialog) { + if ($.ui && $.ui.dialog && $.ui.dialog.overlay) { $.ui.dialog.overlay.events = $.map('focus,keydown,keypress'.split(','), function(event) { return event + '.dialog-overlay'; }).join(' '); } diff --git a/sites/all/modules/contrib/views/views/js/views-contextual.js b/sites/all/modules/contrib/views/views/js/views-contextual.js index 2e9dcf7a..a2bbc2a9 100644 --- a/sites/all/modules/contrib/views/views/js/views-contextual.js +++ b/sites/all/modules/contrib/views/views/js/views-contextual.js @@ -9,7 +9,7 @@ Drupal.behaviors.viewsContextualLinks = { // If there are views-related contextual links attached to the main page // content, find the smallest region that encloses both the links and the // view, and display it as a contextual links region. - $('.views-contextual-links-page', context).closest(':has(.view)').addClass('contextual-links-region'); + $('.views-contextual-links-page', context).closest(':has(".view"):not("body")').addClass('contextual-links-region'); } }; diff --git a/sites/all/modules/contrib/views/views/modules/comment.views_default.inc b/sites/all/modules/contrib/views/views/modules/comment.views_default.inc index 44ebac90..d0c4796a 100644 --- a/sites/all/modules/contrib/views/views/modules/comment.views_default.inc +++ b/sites/all/modules/contrib/views/views/modules/comment.views_default.inc @@ -25,7 +25,8 @@ function comment_views_default_views() { $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Recent comments'; $handler->display->display_options['use_more'] = TRUE; - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access comments'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; @@ -134,7 +135,8 @@ function comment_views_default_views() { /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Recent posts'; - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; diff --git a/sites/all/modules/contrib/views/views/modules/field.views.inc b/sites/all/modules/contrib/views/views/modules/field.views.inc index 873153ea..0bf1ad2b 100644 --- a/sites/all/modules/contrib/views/views/modules/field.views.inc +++ b/sites/all/modules/contrib/views/views/modules/field.views.inc @@ -488,7 +488,13 @@ function list_field_views_data($field) { foreach ($data as $table_name => $table_data) { foreach ($table_data as $field_name => $field_data) { if (isset($field_data['filter']) && $field_name != 'delta') { - $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_field_list'; + if ($field['type'] == 'list_boolean') { + // Special handler for boolean fields. + $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_field_list_boolean'; + } + else { + $data[$table_name][$field_name]['filter']['handler'] = 'views_handler_filter_field_list'; + } } if (isset($field_data['argument']) && $field_name != 'delta') { if ($field['type'] == 'list_text') { diff --git a/sites/all/modules/contrib/views/views/modules/field/views_handler_field_field.inc b/sites/all/modules/contrib/views/views/modules/field/views_handler_field_field.inc index b50a0aea..a91e13a0 100644 --- a/sites/all/modules/contrib/views/views/modules/field/views_handler_field_field.inc +++ b/sites/all/modules/contrib/views/views/modules/field/views_handler_field_field.inc @@ -820,7 +820,10 @@ class views_handler_field_field extends views_handler_field { * Return an array of items for the field. */ function set_items($values, $row_id) { - if (empty($values->_field_data[$this->field_alias]) || empty($values->_field_data[$this->field_alias]['entity'])) { + // In some cases the instance on the entity might be easy, see + // https://drupal.org/node/1161708 and https://drupal.org/node/1461536 for + // more information. + if (empty($values->_field_data[$this->field_alias]) || empty($values->_field_data[$this->field_alias]['entity']) || !isset($values->_field_data[$this->field_alias]['entity']->{$this->definition['field_name']})) { return array(); } diff --git a/sites/all/modules/contrib/views/views/modules/field/views_handler_filter_field_list_boolean.inc b/sites/all/modules/contrib/views/views/modules/field/views_handler_filter_field_list_boolean.inc new file mode 100644 index 00000000..34bca549 --- /dev/null +++ b/sites/all/modules/contrib/views/views/modules/field/views_handler_filter_field_list_boolean.inc @@ -0,0 +1,33 @@ +definition['field_name']); + $value_options = list_allowed_values($field); + + // Boolean fields have an option for using the label as the 'on' value. This + // results in there being no label values in the allows values array. + // If this is the case, we need to provide the labels. + $filtered = array_filter($value_options); + if (empty($filtered)) { + // We can't provide the label in the same way the FieldAPI formatter does, + // as these are different on each instance, and we may be operating on + // more than one bundle. + $value_options[0] = t('Off'); + $value_options[1] = t('On'); + } + + $this->value_options = $value_options; + } +} diff --git a/sites/all/modules/contrib/views/views/modules/node.views_default.inc b/sites/all/modules/contrib/views/views/modules/node.views_default.inc index 93886a7d..de619c1a 100644 --- a/sites/all/modules/contrib/views/views/modules/node.views_default.inc +++ b/sites/all/modules/contrib/views/views/modules/node.views_default.inc @@ -24,7 +24,8 @@ function node_views_default_views() { /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Monthly archive'; - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; @@ -110,7 +111,8 @@ function node_views_default_views() { /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; @@ -192,7 +194,8 @@ function node_views_default_views() { /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['use_ajax'] = TRUE; - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; diff --git a/sites/all/modules/contrib/views/views/modules/node.views_template.inc b/sites/all/modules/contrib/views/views/modules/node.views_template.inc index b2b184d9..ad894146 100644 --- a/sites/all/modules/contrib/views/views/modules/node.views_template.inc +++ b/sites/all/modules/contrib/views/views/modules/node.views_template.inc @@ -24,6 +24,7 @@ function node_views_templates() { $handler = $view->new_display('default', 'Defaults', 'default'); $handler->display->display_options['title'] = 'Image gallery'; $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['exposed_form']['type'] = 'basic'; diff --git a/sites/all/modules/contrib/views/views/modules/profile/views_handler_field_profile_date.inc b/sites/all/modules/contrib/views/views/modules/profile/views_handler_field_profile_date.inc index 2d9fe966..c2cf691b 100644 --- a/sites/all/modules/contrib/views/views/modules/profile/views_handler_field_profile_date.inc +++ b/sites/all/modules/contrib/views/views/modules/profile/views_handler_field_profile_date.inc @@ -51,20 +51,21 @@ class views_handler_field_profile_date extends views_handler_field_date { // But we *can* deal with non-year stuff: $date = gmmktime(0, 0, 0, $value['month'], $value['day'], $value['year']); + $replace = array( // day 'd' => sprintf('%02d', $value['day']), 'D' => NULL, 'l' => NULL, 'N' => NULL, - 'S' => date('S', $date), + 'S' => gmdate('S', $date), 'w' => NULL, 'j' => $value['day'], // month - 'F' => date('F', $date), + 'F' => gmdate('F', $date), 'm' => sprintf('%02d', $value['month']), - 'M' => date('M', $date), - 'n' => date('n', $date), + 'M' => gmdate('M', $date), + 'n' => gmdate('n', $date), 'Y' => $value['year'], 'y' => substr($value['year'], 2, 2), diff --git a/sites/all/modules/contrib/views/views/modules/search.views_default.inc b/sites/all/modules/contrib/views/views/modules/search.views_default.inc index 449dfb3c..dcde6224 100644 --- a/sites/all/modules/contrib/views/views/modules/search.views_default.inc +++ b/sites/all/modules/contrib/views/views/modules/search.views_default.inc @@ -23,7 +23,8 @@ function search_views_default_views() { /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; diff --git a/sites/all/modules/contrib/views/views/modules/statistics.views_default.inc b/sites/all/modules/contrib/views/views/modules/statistics.views_default.inc index 84a94270..7f527d59 100644 --- a/sites/all/modules/contrib/views/views/modules/statistics.views_default.inc +++ b/sites/all/modules/contrib/views/views/modules/statistics.views_default.inc @@ -25,7 +25,8 @@ function statistics_views_default_views() { $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Popular content'; $handler->display->display_options['use_more'] = TRUE; - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; diff --git a/sites/all/modules/contrib/views/views/modules/system/views_handler_field_file_extension.inc b/sites/all/modules/contrib/views/views/modules/system/views_handler_field_file_extension.inc index 6f9a03fe..b543d8a2 100644 --- a/sites/all/modules/contrib/views/views/modules/system/views_handler_field_file_extension.inc +++ b/sites/all/modules/contrib/views/views/modules/system/views_handler_field_file_extension.inc @@ -10,10 +10,40 @@ * @ingroup views_field_handlers */ class views_handler_field_file_extension extends views_handler_field { + public function option_definition() { + $options = parent::option_definition(); + $options['extension_detect_tar'] = array('default' => FALSE, 'bool' => TRUE); + return $options; + } + + public function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['extension_detect_tar'] = array( + '#type' => 'checkbox', + '#title' => t('Detect if tar is part of the extension'), + '#description' => t("See if the previous extension is '.tar' and if so, add that, so we see 'tar.gz' or 'tar.bz2' instead of just 'gz'."), + '#default_value' => $this->options['extension_detect_tar'], + ); + } + function render($values) { $value = $this->get_value($values); - if (preg_match('/\.([^\.]+)$/', $value, $match)) { - return $this->sanitize_value($match[1]); + if (!$this->options['extension_detect_tar']) { + if (preg_match('/\.([^\.]+)$/', $value, $match)) { + return $this->sanitize_value($match[1]); + } + } + else { + $file_parts = explode('.', basename($value)); + // If there is an extension. + if (count($file_parts) > 1) { + $extension = array_pop($file_parts); + $last_part_in_name = array_pop($file_parts); + if ($last_part_in_name === 'tar') { + $extension = 'tar.' . $extension; + } + return $this->sanitize_value($extension); + } } } } diff --git a/sites/all/modules/contrib/views/views/modules/taxonomy.views_default.inc b/sites/all/modules/contrib/views/views/modules/taxonomy.views_default.inc index db53fc24..f43a0828 100644 --- a/sites/all/modules/contrib/views/views/modules/taxonomy.views_default.inc +++ b/sites/all/modules/contrib/views/views/modules/taxonomy.views_default.inc @@ -23,7 +23,8 @@ function taxonomy_views_default_views() { /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); - $handler->display->display_options['access']['type'] = 'none'; + $handler->display->display_options['access']['type'] = 'perm'; + $handler->display->display_options['access']['perm'] = 'access content'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; diff --git a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc index 7eb868f7..8938ca9f 100644 --- a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc +++ b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_filter_term_node_tid.inc @@ -98,15 +98,12 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on if ($this->options['type'] == 'textfield') { $default = ''; if ($this->value) { - $result = db_select('taxonomy_term_data', 'td') - ->fields('td') - ->condition('td.tid', $this->value) - ->execute(); - foreach ($result as $term) { + $result = taxonomy_term_load_multiple($this->value); + foreach ($result as $entity_term) { if ($default) { $default .= ', '; } - $default .= $term->name; + $default .= entity_label('taxonomy_term', $entity_term); } } @@ -122,13 +119,14 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on } else { if (!empty($this->options['hierarchy']) && $this->options['limit']) { - $tree = taxonomy_get_tree($vocabulary->vid); + $tree = taxonomy_get_tree($vocabulary->vid, 0, NULL, TRUE); $options = array(); if ($tree) { + // Translation system needs full entity objects, so we have access to label. foreach ($tree as $term) { $choice = new stdClass(); - $choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name); + $choice->option = array($term->tid => str_repeat('-', $term->depth) . entity_label('taxonomy_term', $term)); $options[] = $choice; } } @@ -147,8 +145,14 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on $query->condition('tv.machine_name', $vocabulary->machine_name); } $result = $query->execute(); + + $tids = array(); foreach ($result as $term) { - $options[$term->tid] = $term->name; + $tids[] = $term->tid; + } + $entities = taxonomy_term_load_multiple($tids); + foreach ($entities as $entity_term) { + $options[$entity_term->tid] = entity_label('taxonomy_term', $entity_term); } } @@ -238,7 +242,7 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on $rc = parent::accept_exposed_input($input); if ($rc) { // If we have previously validated input, override. - if (isset($this->validated_exposed_input)) { + if (!$this->is_a_group() && isset($this->validated_exposed_input)) { $this->value = $this->validated_exposed_input; } } @@ -347,12 +351,9 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on if ($this->value) { $this->value = array_filter($this->value); - $result = db_select('taxonomy_term_data', 'td') - ->fields('td') - ->condition('td.tid', $this->value) - ->execute(); - foreach ($result as $term) { - $this->value_options[$term->tid] = $term->name; + $result = taxonomy_term_load_multiple($this->value); + foreach ($result as $entity_term) { + $this->value_options[$entity_term->tid] = entity_label('taxonomy_term', $entity_term); } } return parent::admin_summary(); diff --git a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_relationship_node_term_data.inc b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_relationship_node_term_data.inc index d7fbb4c9..cf722883 100644 --- a/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_relationship_node_term_data.inc +++ b/sites/all/modules/contrib/views/views/modules/taxonomy/views_handler_relationship_node_term_data.inc @@ -75,7 +75,9 @@ class views_handler_relationship_node_term_data extends views_handler_relationsh $query->addJoin($def['type'], 'taxonomy_vocabulary', 'tv', 'td.vid = tv.vid'); $query->addJoin($def['type'], 'taxonomy_index', 'tn', 'tn.tid = td.tid'); $query->condition('tv.machine_name', array_filter($this->options['vocabularies'])); - $query->addTag('term_access'); + if (empty($this->query->options['disable_sql_rewrite'])) { + $query->addTag('term_access'); + } $query->fields('td'); $query->fields('tn', array('nid')); $def['table formula'] = $query; diff --git a/sites/all/modules/contrib/views/views/modules/user/views_handler_field_user_link_cancel.inc b/sites/all/modules/contrib/views/views/modules/user/views_handler_field_user_link_cancel.inc index 9129c017..fe038dad 100644 --- a/sites/all/modules/contrib/views/views/modules/user/views_handler_field_user_link_cancel.inc +++ b/sites/all/modules/contrib/views/views/modules/user/views_handler_field_user_link_cancel.inc @@ -22,7 +22,7 @@ class views_handler_field_user_link_cancel extends views_handler_field_user_link if ($uid && user_cancel_access($account)) { $this->options['alter']['make_link'] = TRUE; - $text = !empty($this->options['text']) ? $this->options['text'] : t('cancel'); + $text = !empty($this->options['text']) ? $this->options['text'] : t('Cancel account'); $this->options['alter']['path'] = "user/$uid/cancel"; $this->options['alter']['query'] = drupal_get_destination(); diff --git a/sites/all/modules/contrib/views/views/modules/views.views.inc b/sites/all/modules/contrib/views/views/modules/views.views.inc index 2029aa8b..7c3f4db9 100644 --- a/sites/all/modules/contrib/views/views/modules/views.views.inc +++ b/sites/all/modules/contrib/views/views/modules/views.views.inc @@ -81,6 +81,14 @@ function views_views_data() { ), ); + $data['views']['messages'] = array( + 'title' => t('Messages'), + 'help' => t('Displays messages in the area.'), + 'area' => array( + 'handler' => 'views_handler_area_messages', + ), + ); + if (module_exists('contextual')) { $data['views']['contextual_links'] = array( 'title' => t('Contextual Links'), @@ -110,5 +118,14 @@ function views_views_data() { ); } + $data['views']['fields_compare'] = array( + 'title' => t('Fields comparison'), + 'help' => t('Compare database fields against eachother.'), + 'filter' => array( + 'help' => t('Use fields comparison to filter the result of the view.'), + 'handler' => 'views_handler_filter_fields_compare', + ) + ); + return $data; } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_cache.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_cache.inc index 4d21701f..81f71bfb 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_cache.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_cache.inc @@ -200,25 +200,28 @@ class views_plugin_cache extends views_plugin { $this->storage['head'] = ''; } + // Check if the advanced mapping function of D 7.23 is available. + $array_mapping_func = function_exists('drupal_array_diff_assoc_recursive') ? 'drupal_array_diff_assoc_recursive' : 'array_diff_assoc'; + // Slightly less simple for CSS: $css = drupal_add_css(); $css_start = isset($this->storage['css']) ? $this->storage['css'] : array(); - $this->storage['css'] = array_diff_assoc($css, $css_start); + $this->storage['css'] = $array_mapping_func($css, $css_start); // Get javascript after/before views renders. $js = drupal_add_js(); $js_start = isset($this->storage['js']) ? $this->storage['js'] : array(); // If there are any differences between the old and the new javascript then // store them to be added later. - $this->storage['js'] = array_diff_assoc($js, $js_start); + $this->storage['js'] = $array_mapping_func($js, $js_start); // Special case the settings key and get the difference of the data. $settings = isset($js['settings']['data']) ? $js['settings']['data'] : array(); $settings_start = isset($js_start['settings']['data']) ? $js_start['settings']['data'] : array(); - $this->storage['js']['settings'] = array_diff_assoc($settings, $settings_start); + $this->storage['js']['settings'] = $array_mapping_func($settings, $settings_start); // Get difference of HTTP headers. - $this->storage['headers'] = array_diff_assoc(drupal_get_http_header(), $this->storage['headers']); + $this->storage['headers'] = $array_mapping_func(drupal_get_http_header(), $this->storage['headers']); } /** @@ -253,59 +256,61 @@ class views_plugin_cache extends views_plugin { } function get_results_key() { - global $user; - if (!isset($this->_results_key)) { - - $build_info = $this->view->build_info; - - $query_plugin = $this->view->display_handler->get_plugin('query'); - - foreach (array('query','count_query') as $index) { - // If the default query back-end is used generate SQL query strings from - // the query objects. - if ($build_info[$index] instanceof SelectQueryInterface) { - $query = clone $build_info[$index]; - $query->preExecute(); - $build_info[$index] = (string) $query; - } - } - $key_data = array( - 'build_info' => $build_info, - 'roles' => array_keys($user->roles), - 'super-user' => $user->uid == 1, // special caching for super user. - 'language' => $GLOBALS['language']->language, - 'base_url' => $GLOBALS['base_url'], - ); - foreach (array('exposed_info', 'page', 'sort', 'order', 'items_per_page', 'offset') as $key) { - if (isset($_GET[$key])) { - $key_data[$key] = $_GET[$key]; - } - } - - $this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . md5(serialize($key_data)); + $this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . $this->get_cache_key(); } return $this->_results_key; } function get_output_key() { - global $user; if (!isset($this->_output_key)) { $key_data = array( - 'result' => $this->view->result, - 'roles' => array_keys($user->roles), - 'super-user' => $user->uid == 1, // special caching for super user. 'theme' => $GLOBALS['theme'], - 'language' => $GLOBALS['language']->language, - 'base_url' => $GLOBALS['base_url'], ); - - $this->_output_key = $this->view->name . ':' . $this->display->id . ':output:' . md5(serialize($key_data)); + $this->_output_key = $this->view->name . ':' . $this->display->id . ':output:' . $this->get_cache_key($key_data); } return $this->_output_key; } + + /** + * Returns cache key. + * + * @param array $key_data + * Additional data for cache segmentation and/or overrides for default + * segmentation. + * + * @return string + */ + function get_cache_key($key_data = array()) { + global $user; + + $key_data += array( + 'roles' => array_keys($user->roles), + 'super-user' => $user->uid == 1, // special caching for super user. + 'language' => $GLOBALS['language']->language, + 'base_url' => $GLOBALS['base_url'], + ); + + if (empty($key_data['build_info'])) { + $build_info = $this->view->build_info; + foreach (array('query','count_query') as $index) { + // If the default query back-end is used generate SQL query strings from + // the query objects. + if ($build_info[$index] instanceof SelectQueryInterface) { + $query = clone $build_info[$index]; + $query->preExecute(); + $key_data['build_info'][$index] = array( + 'sql' => (string) $query, + 'arguments' => $query->getArguments(), + ); + } + } + } + $key = md5(serialize($key_data)); + return $key; + } } /** diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc index 75a32c51..db124de0 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_display.inc @@ -918,7 +918,7 @@ class views_plugin_display extends views_plugin { /** * Get a full array of handlers for $type. This caches them. */ - function get_handlers($type) { + function &get_handlers($type) { if (!isset($this->handlers[$type])) { $this->handlers[$type] = array(); $types = views_object_types(); diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_display_feed.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_display_feed.inc index bfd220c5..5eb68e32 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_display_feed.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_display_feed.inc @@ -37,7 +37,7 @@ class views_plugin_display_feed extends views_plugin_display_page { function execute() { $output = $this->view->render(); if (empty($output)) { - return drupal_not_found(); + return MENU_NOT_FOUND; } print $output; } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_display_page.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_display_page.inc index 7ca4bf7f..4bcec0bc 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_display_page.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_display_page.inc @@ -216,11 +216,11 @@ class views_plugin_display_page extends views_plugin_display { // display, and arguments should be set on the view. $this->view->build(); if (!empty($this->view->build_info['fail'])) { - return drupal_not_found(); + return MENU_NOT_FOUND; } if (!empty($this->view->build_info['denied'])) { - return drupal_access_denied(); + return MENU_ACCESS_DENIED; } $this->view->get_breadcrumb(TRUE); diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form.inc index 343eee81..5d546004 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form.inc @@ -173,7 +173,7 @@ class views_plugin_exposed_form extends views_plugin { $view = $this->view; $exposed_data = isset($view->exposed_data) ? $view->exposed_data : array(); $sort_by = isset($exposed_data['sort_by']) ? $exposed_data['sort_by'] : NULL; - if (!empty($sort_by)) { + if (!empty($sort_by) && $this->view->style_plugin->build_sort()) { // Make sure the original order of sorts is preserved // (e.g. a sticky sort is often first) if (isset($view->sort[$sort_by])) { diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form_input_required.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form_input_required.inc index 4f2c2d2a..ca97674e 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form_input_required.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_exposed_form_input_required.inc @@ -71,6 +71,7 @@ class views_plugin_exposed_form_input_required extends views_plugin_exposed_form 'group_type' => 'group', 'content' => $this->options['text_input_required'], 'format' => $this->options['text_input_required_format'], + 'empty' => TRUE, ); $handler = views_get_handler('views', 'area', 'area'); $handler->init($this->view, $options); diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_pager.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_pager.inc index 416d6625..312f54b9 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_pager.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_pager.inc @@ -107,7 +107,7 @@ class views_plugin_pager extends views_plugin { * Get the pager id, if it exists */ function get_pager_id() { - return isset($this->options['id']) ? $this->options['id'] : 0; + return !empty($this->options['id']) ? $this->options['id'] : 0; } /** diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_full.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_full.inc index d4c22038..aedb2237 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_full.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_full.inc @@ -276,7 +276,7 @@ class views_plugin_pager_full extends views_plugin_pager { ); $output = theme($pager_theme, array( 'tags' => $tags, - 'element' => $this->options['id'], + 'element' => $this->get_pager_id(), 'parameters' => $input, 'quantity' => $this->options['quantity'], )); @@ -308,11 +308,12 @@ class views_plugin_pager_full extends views_plugin_pager { // array hasn't been initialized before. $page = isset($_GET['page']) ? explode(',', $_GET['page']) : array(); - for ($i = 0; $i <= $this->options['id'] || $i < count($pager_page_array); $i++) { + $pager_id = $this->get_pager_id(); + for ($i = 0; $i <= $pager_id || $i < count($pager_page_array); $i++) { $pager_page_array[$i] = empty($page[$i]) ? 0 : $page[$i]; } - $this->current_page = intval($pager_page_array[$this->options['id']]); + $this->current_page = intval($pager_page_array[$pager_id]); if ($this->current_page < 0) { $this->current_page = 0; @@ -348,24 +349,25 @@ class views_plugin_pager_full extends views_plugin_pager { // Dump information about what we already know into the globals. global $pager_page_array, $pager_total, $pager_total_items, $pager_limits; // Set the limit. - $pager_limits[$this->options['id']] = $this->options['items_per_page']; + $pager_id = $this->get_pager_id(); + $pager_limits[$pager_id] = $this->options['items_per_page']; // Set the item count for the pager. - $pager_total_items[$this->options['id']] = $this->total_items; + $pager_total_items[$pager_id] = $this->total_items; // Calculate and set the count of available pages. - $pager_total[$this->options['id']] = $this->get_pager_total(); + $pager_total[$pager_id] = $this->get_pager_total(); // See if the requested page was within range: if ($this->current_page < 0) { $this->current_page = 0; } - else if ($this->current_page >= $pager_total[$this->options['id']]) { + else if ($this->current_page >= $pager_total[$pager_id]) { // Pages are numbered from 0 so if there are 10 pages, the last page is 9. - $this->current_page = $pager_total[$this->options['id']] - 1; + $this->current_page = $pager_total[$pager_id] - 1; } // Put this number in to guarantee that we do not generate notices when the pager // goes to look for it later. - $pager_page_array[$this->options['id']] = $this->current_page; + $pager_page_array[$pager_id] = $this->current_page; } } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_mini.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_mini.inc index bec48c89..87d55410 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_mini.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_pager_mini.inc @@ -63,7 +63,7 @@ class views_plugin_pager_mini extends views_plugin_pager_full { ); return theme($pager_theme, array( 'tags' => $tags, - 'element' => $this->options['id'], + 'element' => $this->get_pager_id(), 'parameters' => $input, )); } diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc index 030c5ea0..8a15e8dc 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_query_default.inc @@ -1365,6 +1365,16 @@ class views_plugin_query_default extends views_plugin_query { // Add all query substitutions as metadata. $query->addMetaData('views_substitutions', module_invoke_all('views_query_substitutions', $this)); + if (!$get_count) { + if (!empty($this->limit) || !empty($this->offset)) { + // We can't have an offset without a limit, so provide a very large limit + // instead. + $limit = intval(!empty($this->limit) ? $this->limit : 999999); + $offset = intval(!empty($this->offset) ? $this->offset : 0); + $query->range($offset, $limit); + } + } + return $query; } @@ -1469,16 +1479,8 @@ class views_plugin_query_default extends views_plugin_query { $this->pager->execute_count_query($count_query); } - // Let the pager modify the query to add limits. $this->pager->pre_execute($query); - if (!empty($this->limit) || !empty($this->offset)) { - // We can't have an offset without a limit, so provide a very large limit instead. - $limit = intval(!empty($this->limit) ? $this->limit : 999999); - $offset = intval(!empty($this->offset) ? $this->offset : 0); - $query->range($offset, $limit); - } - $result = $query->execute(); $view->result = array(); diff --git a/sites/all/modules/contrib/views/views/plugins/views_plugin_style_jump_menu.inc b/sites/all/modules/contrib/views/views/plugins/views_plugin_style_jump_menu.inc index 16b0aef7..1de90f79 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_plugin_style_jump_menu.inc +++ b/sites/all/modules/contrib/views/views/plugins/views_plugin_style_jump_menu.inc @@ -142,8 +142,17 @@ class views_plugin_style_jump_menu extends views_plugin_style { unset($this->view->row_index); $default_value = ''; - if ($this->options['default_value'] && !empty($paths[url($_GET['q'])])) { - $default_value = $paths[url($_GET['q'])]; + if ($this->options['default_value']) { + $lookup_options = array(); + // We need to check if the path is absolute + // or else language is not taken in account. + if ($this->view->display[$this->view->current_display]->display_options['fields'][$this->options['path']]['absolute']) { + $lookup_options['absolute'] = TRUE; + } + $lookup_url = url($_GET['q'], $lookup_options); + if (!empty($paths[$lookup_url])) { + $default_value = $paths[$lookup_url]; + } } ctools_include('jump-menu'); diff --git a/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php b/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php index 09d4994e..fa26d333 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php +++ b/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_comment_views_wizard.class.php @@ -75,6 +75,7 @@ class ViewsUiCommentViewsWizard extends ViewsUiBaseViewsWizard { // Add permission-based access control. $display_options['access']['type'] = 'perm'; + $display_options['access']['perm'] = 'access comments'; // Add a relationship to nodes. $display_options['relationships']['nid']['id'] = 'nid'; diff --git a/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_node_views_wizard.class.php b/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_node_views_wizard.class.php index 010220e1..07bb91df 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_node_views_wizard.class.php +++ b/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_node_views_wizard.class.php @@ -64,6 +64,7 @@ class ViewsUiNodeViewsWizard extends ViewsUiBaseViewsWizard { // Add permission-based access control. $display_options['access']['type'] = 'perm'; + $display_options['access']['perm'] = 'access content'; // Remove the default fields, since we are customizing them here. unset($display_options['fields']); diff --git a/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php b/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php index 4f05548b..8c1d6d56 100644 --- a/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php +++ b/sites/all/modules/contrib/views/views/plugins/views_wizard/views_ui_taxonomy_term_views_wizard.class.php @@ -15,6 +15,7 @@ class ViewsUiTaxonomyTermViewsWizard extends ViewsUiBaseViewsWizard { // Add permission-based access control. $display_options['access']['type'] = 'perm'; + $display_options['access']['perm'] = 'access content'; // Remove the default fields, since we are customizing them here. unset($display_options['fields']); diff --git a/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_date.test b/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_date.test index 028b687f..79441429 100644 --- a/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_date.test +++ b/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_date.test @@ -34,6 +34,8 @@ class ViewsHandlerFieldDateTest extends ViewsSqlTest { 'relationship' => 'none', // c is iso 8601 date format @see http://php.net/manual/en/function.date.php 'custom_date_format' => 'c', + 'second_date_format' => 'custom', + 'second_date_format_custom' => 'c', ), )); $time = gmmktime(0, 0, 0, 1, 1, 2000); @@ -51,6 +53,8 @@ class ViewsHandlerFieldDateTest extends ViewsSqlTest { 'medium' => format_date($time, 'medium', '', $timezone), 'large' => format_date($time, 'large', '', $timezone), 'custom' => format_date($time, 'custom', 'c', $timezone), + 'today time ago custom' => format_date($time, 'custom', 'c', $timezone), + 'today time ago' => t('%time ago', array('%time' => format_interval(120, 2))), ); $this->assertRenderedDatesEqual($view, $dates, $timezone); } @@ -67,6 +71,17 @@ class ViewsHandlerFieldDateTest extends ViewsSqlTest { protected function assertRenderedDatesEqual($view, $map, $timezone = NULL) { foreach ($map as $date_format => $expected_result) { + $check_result_number = 0; + + // If it's "today time ago" format we have to check the 6th element. + if ($date_format == 'today time ago') { + $check_result_number = 5; + } + + // Correct the date format. + if ($date_format == 'today time ago custom') { + $date_format = 'today time ago'; + } $view->field['created']->options['date_format'] = $date_format; $t_args = array( '%value' => $expected_result, @@ -80,8 +95,23 @@ class ViewsHandlerFieldDateTest extends ViewsSqlTest { else { $message = t('Value %value in %format format matches.', $t_args); } - $actual_result = $view->field['created']->advanced_render($view->result[0]); + $actual_result = $view->field['created']->advanced_render($view->result[$check_result_number]); $this->assertEqual($expected_result, $actual_result, $message); } } + + /** + * Appends dataSet() with a data row for "today time ago" format testing. + */ + protected function dataSet() { + $data = parent::dataSet(); + $data[] = array( + 'name' => 'David', + 'age' => 25, + 'job' => 'Singer', + 'created' => REQUEST_TIME - 120, + ); + + return $data; + } } diff --git a/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_file_extension.test b/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_file_extension.test new file mode 100644 index 00000000..ab8b0a93 --- /dev/null +++ b/sites/all/modules/contrib/views/views/tests/handlers/views_handler_field_file_extension.test @@ -0,0 +1,66 @@ + 'Field: File extension', + 'description' => 'Test the views_handler_field_file_extension handler.', + 'group' => 'Views Handlers', + ); + } + + function dataSet() { + $data = parent::dataSet(); + $data[0]['name'] = 'file.png'; + $data[1]['name'] = 'file.tar'; + $data[2]['name'] = 'file.tar.gz'; + $data[3]['name'] = 'file'; + + return $data; + } + + function viewsData() { + $data = parent::viewsData(); + $data['views_test']['name']['field']['handler'] = 'views_handler_field_file_extension'; + $data['views_test']['name']['real field'] = 'name'; + + return $data; + } + + /** + * Tests the 'extension_detect_tar' handler option. + */ + public function testFileExtensionTarOption() { + $view = $this->getBasicView(); + + $view->display['default']->handler->override_option('fields', array( + 'name' => array( + 'id' => 'name', + 'table' => 'views_test', + 'field' => 'name', + ), + )); + + $this->executeView($view); + + // Test without the tar option. + $this->assertEqual($view->field['name']->advanced_render($view->result[0]), 'png'); + $this->assertEqual($view->field['name']->advanced_render($view->result[1]), 'tar'); + $this->assertEqual($view->field['name']->advanced_render($view->result[2]), 'gz'); + $this->assertEqual($view->field['name']->advanced_render($view->result[3]), ''); + // Test with the tar option. + $view->field['name']->options['extension_detect_tar'] = TRUE; + $this->assertEqual($view->field['name']->advanced_render($view->result[0]), 'png'); + $this->assertEqual($view->field['name']->advanced_render($view->result[1]), 'tar'); + $this->assertEqual($view->field['name']->advanced_render($view->result[2]), 'tar.gz'); + $this->assertEqual($view->field['name']->advanced_render($view->result[3]), ''); + } +} diff --git a/sites/all/modules/contrib/views/views/tests/handlers/views_handlers.test b/sites/all/modules/contrib/views/views/tests/handlers/views_handlers.test new file mode 100644 index 00000000..f2faee3f --- /dev/null +++ b/sites/all/modules/contrib/views/views/tests/handlers/views_handlers.test @@ -0,0 +1,81 @@ + 'Handlers', + 'description' => 'Tests generic handler functionality.', + 'group' => 'Views Handlers', + ); + } + + /** + * {@inheritdoc} + */ + protected function viewsData() { + $views_data = parent::viewsData(); + $views_data['views']['test_access'] = array( + 'title' => 'test access', + 'help' => '', + 'area' => array( + 'handler' => 'views_test_area_access', + ), + ); + + return $views_data; + } + + /** + * Tests access for handlers using an area handler. + */ + public function testHandlerAccess() { + $view = $this->getBasicView(); + + // add a test area + $view->display['default']->handler->override_option('header', array( + 'test_access' => array( + 'id' => 'test_access', + 'table' => 'views', + 'field' => 'test_access', + 'custom_access' => FALSE, + ), + )); + + $view->init_display(); + $view->init_handlers(); + $handlers = $view->display_handler->get_handlers('header'); + $this->assertEqual(0, count($handlers)); + + $view->destroy(); + + $view = $this->getBasicView(); + + // add a test area + $view->display['default']->handler->override_option('header', array( + 'test_access' => array( + 'id' => 'test_access', + 'table' => 'views', + 'field' => 'test_access', + 'custom_access' => TRUE, + ), + )); + + $view->init_display(); + $view->init_handlers(); + $handlers = $view->display_handler->get_handlers('header'); + $this->assertEqual(1, count($handlers)); + $this->assertTrue(isset($handlers['test_access'])); + } + +} diff --git a/sites/all/modules/contrib/views/views/tests/test_handlers/views_test_area_access.inc b/sites/all/modules/contrib/views/views/tests/test_handlers/views_test_area_access.inc new file mode 100644 index 00000000..57a0014e --- /dev/null +++ b/sites/all/modules/contrib/views/views/tests/test_handlers/views_test_area_access.inc @@ -0,0 +1,28 @@ +options['custom_access']; + } + + /** + * {@inheritdoc} + */ + function option_definition() { + $options = parent::option_definition(); + + $options['custom_access'] = array('default' => TRUE, 'bool' => TRUE); + + return $options; + } + +} diff --git a/sites/all/modules/contrib/views/views/tests/views_cache.test b/sites/all/modules/contrib/views/views/tests/views_cache.test index 31037623..28534a2f 100644 --- a/sites/all/modules/contrib/views/views/tests/views_cache.test +++ b/sites/all/modules/contrib/views/views/tests/views_cache.test @@ -241,4 +241,68 @@ class ViewsCacheTest extends ViewsSqlTest { $this->assertEqual($first_content_type, $second_content_type, t('Content types of responses are equal.')); } + /** + * Test caching of different exposed filter values with the same view result. + * + * Make sure the output is different. + */ + function testExposedFilterSameResultsCaching() { + // Create the view with time-based cache with hour lifetimes and add exposed + // filter to it with "Starts with" operator. + $view = $this->getBasicView(); + $view->set_display(); + $view->display_handler->override_option('cache', array( + 'type' => 'time', + 'results_lifespan' => '3600', + 'output_lifespan' => '3600', + )); + $view->display_handler->override_option('filters', array( + 'name' => array( + 'id' => 'name', + 'table' => 'views_test', + 'field' => 'name', + 'relationship' => 'none', + 'operator' => 'starts', + 'exposed' => TRUE, + 'expose' => array( + 'operator_id' => 'name_op', + 'operator' => 'name_op', + 'identifier' => 'name', + ), + ), + )); + + // Clone the view before setting exposed input. + $clone = $view->copy(); + + // Pass "Rin" to the exposed filter and check that only one row returned. + $view->set_exposed_input(array( + 'name' => 'Rin', + )); + $this->executeView($view); + $first_result = $view->result; + $first_output = $view->render(); + $this->assertEqual(1, count($first_result), t('The number of rows returned by the first view match.')); + + // Pass full "Ringo" to the exposed filter at the second time and make sure + // results are the same. + $clone->set_exposed_input(array( + 'name' => 'Ringo', + )); + $this->executeView($clone); + $second_result = $clone->result; + $second_output = $clone->render(); + $this->assertEqual($first_result, $second_result, t('Results of both views are the same.')); + + // Check that output is not the same and it contains full "Ringo" word in + // default value of exposed input. + $this->assertNotEqual($first_output, $second_output, t('Output of the second view is different.')); + $this->drupalSetContent($second_output); + $element = $this->xpath('//input[@name="name" and @value="Ringo"]'); + $this->assertTrue(!empty($element), t('Input field of exposed filter has the second value.')); + + $view->destroy(); + $clone->destroy(); + } + } diff --git a/sites/all/modules/contrib/views/views/tests/views_module.test b/sites/all/modules/contrib/views/views/tests/views_module.test index dc6c1640..6a27443a 100644 --- a/sites/all/modules/contrib/views/views/tests/views_module.test +++ b/sites/all/modules/contrib/views/views/tests/views_module.test @@ -151,6 +151,51 @@ class ViewsModuleTest extends ViewsSqlTest { $this->assertEqual('views_handler_filter', get_class($handler)); } + /** + * Tests views_fetch_data(). + */ + function testFetchData() { + + // Make sure we start with a empty cache. + $this->resetStaticViewsDataCache(); + cache_clear_all('*', 'cache_views', TRUE); + variable_set('views_test_views_data_count', 0); + + // Request info about an existing table. + $this->assertTrue(views_fetch_data('views_test'), 'Data about existing table returned'); + // This should have triggered a views data rebuild, and written a cache + // entry for all tables and the requested table but no other tables. + $this->assertEqual(variable_get('views_test_views_data_count', 0), 1, 'Views data rebuilt once'); + $this->assertTrue(cache_get('views_data:en', 'cache_views'), 'Cache for all tables written.'); + $this->assertTrue(cache_get('views_data:views_test:en', 'cache_views'), 'Cache for requested table written.'); + $this->assertFalse(cache_get('views_data:views_test_previous:en', 'cache_views'), 'No Cache written for not requested table.'); + $this->assertTrue(drupal_static('_views_fetch_data_fully_loaded'), 'Views data is fully loaded'); + + $this->resetStaticViewsDataCache(); + + // Request the same table again. + $this->assertTrue(views_fetch_data('views_test'), 'Data about existing table returned'); + $this->assertEqual(variable_get('views_test_views_data_count', 0), 1, 'Views data rebuilt once'); + $this->assertFalse(drupal_static('_views_fetch_data_fully_loaded'), 'Views data is not fully loaded'); + + $this->resetStaticViewsDataCache(); + + // Request a missing table, this should load the full cache from cache but + // not rebuilt. + $this->assertFalse(views_fetch_data('views_test_missing'), 'No data about missing table returned'); + $this->assertEqual(variable_get('views_test_views_data_count', 0), 1, 'Views data rebuilt once'); + $this->assertTrue(drupal_static('_views_fetch_data_fully_loaded'), 'Views data is fully loaded'); + + $this->resetStaticViewsDataCache(); + + // Request the same empty table again, this should load only that (empty) + // cache for that table. + $this->assertFalse(views_fetch_data('views_test_missing'), 'No data about missing table returned'); + $this->assertEqual(variable_get('views_test_views_data_count', 0), 1, 'Views data rebuilt once'); + $this->assertFalse(drupal_static('_views_fetch_data_fully_loaded'), 'Views data is not fully loaded'); + + } + /** * Ensure that a certain handler is a instance of a certain table/field. */ @@ -160,4 +205,13 @@ class ViewsModuleTest extends ViewsSqlTest { $this->assertEqual($field_data['handler'], get_class($handler)); } + + /** + * Resets the views data cache. + */ + protected function resetStaticViewsDataCache() { + drupal_static_reset('_views_fetch_data_cache'); + drupal_static_reset('_views_fetch_data_recursion_protected'); + drupal_static_reset('_views_fetch_data_fully_loaded'); + } } diff --git a/sites/all/modules/contrib/views/views/tests/views_test.info b/sites/all/modules/contrib/views/views/tests/views_test.info index 23bd884f..b090daa1 100644 --- a/sites/all/modules/contrib/views/views/tests/views_test.info +++ b/sites/all/modules/contrib/views/views/tests/views_test.info @@ -5,9 +5,9 @@ core = 7.x dependencies[] = views hidden = TRUE -; Information added by drupal.org packaging script on 2013-04-09 -version = "7.x-3.7" +; Information added by Drupal.org packaging script on 2015-02-11 +version = "7.x-3.10" core = "7.x" project = "views" -datestamp = "1365499236" +datestamp = "1423648085" diff --git a/sites/all/modules/contrib/views/views/tests/views_test.module b/sites/all/modules/contrib/views/views/tests/views_test.module index 7adcf430..a7460690 100644 --- a/sites/all/modules/contrib/views/views/tests/views_test.module +++ b/sites/all/modules/contrib/views/views/tests/views_test.module @@ -31,6 +31,10 @@ function views_test_views_api() { * Implements hook_views_data(). */ function views_test_views_data() { + // Count how often this hook is called. + $count = variable_get('views_test_views_data_count', 0); + $count++; + variable_set('views_test_views_data_count', $count); return variable_get('views_test_views_data', array()); } diff --git a/sites/all/modules/contrib/views/views/views.api.php b/sites/all/modules/contrib/views/views/views.api.php index ba9b326f..70c5dc83 100644 --- a/sites/all/modules/contrib/views/views/views.api.php +++ b/sites/all/modules/contrib/views/views/views.api.php @@ -513,6 +513,80 @@ function hook_views_data_alter(&$data) { // Note that the $data array is not returned – it is modified by reference. } +/** + * Override the default data for a Field API field. + * + * Field module's implementation of hook_views_data() invokes this for each + * field in the module that defines the field type (as declared in the field + * array). It is not invoked in other modules. + * + * If no hook implementation exists, hook_views_data() falls back to + * field_views_field_default_views_data(). + * + * @see field_views_data() + * @see hook_field_views_data_alter() + * @see hook_field_views_data_views_data_alter() + * + * @param $field + * A field definition array, as returned by field_info_fields(). + * + * @return + * An array of views data, in the same format as the return value of + * hook_views_data(). + */ +function hook_field_views_data($field) { + +} + +/** + * Alter the views data for a single Field API field. + * + * This is called even if there is no hook_field_views_data() implementation for + * the field, and therefore may be used to alter the default data that + * field_views_field_default_views_data() supplies for the field. + * + * @param $result + * An array of views table data provided for a single field. This has the same + * format as the return value of hook_views_data(). + * @param $field + * A field definition array, as returned by field_info_fields(). + * @param $module + * The module that defines the field type. + * + * @see field_views_data() + * @see hook_field_views_data() + * @see hook_field_views_data_views_data_alter() + */ +function hook_field_views_data_alter(&$result, $field, $module) { + +} + +/** + * Alter the views data on a per field basis. + * + * Field module's implementation of hook_views_data_alter() invokes this for + * each field in the module that defines the field type (as declared in the + * field array). It is not invoked in other modules. + * + * Unlike hook_field_views_data_alter(), this operates on the whole of the views + * data. This allows a field module to add data that concerns its fields to + * other tables, which would not yet be defined at the point when + * hook_field_views_data() and hook_field_views_data_alter() are invoked. For + * example, entityreference adds reverse relationships on the tables for the + * entities which are referenced by entityreference fields. + * + * (Note: this is weirdly named so as not to conflict with + * hook_field_views_data_alter().) + * + * @see hook_field_views_data() + * @see hook_field_views_data_alter() + * @see field_views_data_alter() + */ +function hook_field_views_data_views_data_alter(&$data, $field) { + $field_name = $field['field_name']; + $data_key = 'field_data_' . $field_name; + // Views data for this field is in $data[$data_key] +} /** * Describes plugins defined by the module. @@ -836,7 +910,7 @@ function hook_views_pre_view(&$view, &$display_id, &$args) { user_access('administer site configuration') && $display_id == 'public_display' ) { - $display_id = 'private_display'; + $view->set_display('private_display'); } } diff --git a/sites/all/modules/contrib/views/views/views.info b/sites/all/modules/contrib/views/views/views.info index 50d81482..87b01b98 100644 --- a/sites/all/modules/contrib/views/views/views.info +++ b/sites/all/modules/contrib/views/views/views.info @@ -10,6 +10,7 @@ stylesheets[all][] = css/views.css dependencies[] = ctools ; Handlers files[] = handlers/views_handler_area.inc +files[] = handlers/views_handler_area_messages.inc files[] = handlers/views_handler_area_result.inc files[] = handlers/views_handler_area_text.inc files[] = handlers/views_handler_area_text_custom.inc @@ -49,6 +50,7 @@ files[] = handlers/views_handler_filter_in_operator.inc files[] = handlers/views_handler_filter_many_to_one.inc files[] = handlers/views_handler_filter_numeric.inc files[] = handlers/views_handler_filter_string.inc +files[] = handlers/views_handler_filter_fields_compare.inc files[] = handlers/views_handler_relationship.inc files[] = handlers/views_handler_relationship_groupwise_max.inc files[] = handlers/views_handler_sort.inc @@ -100,6 +102,7 @@ files[] = modules/contact/views_handler_field_contact_link.inc files[] = modules/field/views_handler_field_field.inc files[] = modules/field/views_handler_relationship_entity_reverse.inc files[] = modules/field/views_handler_argument_field_list.inc +files[] = modules/field/views_handler_filter_field_list_boolean.inc files[] = modules/field/views_handler_argument_field_list_string.inc files[] = modules/field/views_handler_filter_field_list.inc files[] = modules/filter/views_handler_field_filter_format_name.inc @@ -253,6 +256,7 @@ files[] = plugins/views_plugin_style_summary_unformatted.inc files[] = plugins/views_plugin_style_table.inc ; Tests +files[] = tests/handlers/views_handlers.test files[] = tests/handlers/views_handler_area_text.test files[] = tests/handlers/views_handler_argument_null.test files[] = tests/handlers/views_handler_argument_string.test @@ -261,6 +265,7 @@ files[] = tests/handlers/views_handler_field_boolean.test files[] = tests/handlers/views_handler_field_custom.test files[] = tests/handlers/views_handler_field_counter.test files[] = tests/handlers/views_handler_field_date.test +files[] = tests/handlers/views_handler_field_file_extension.test files[] = tests/handlers/views_handler_field_file_size.test files[] = tests/handlers/views_handler_field_math.test files[] = tests/handlers/views_handler_field_url.test @@ -274,6 +279,7 @@ files[] = tests/handlers/views_handler_filter_string.test files[] = tests/handlers/views_handler_sort_random.test files[] = tests/handlers/views_handler_sort_date.test files[] = tests/handlers/views_handler_sort.test +files[] = tests/test_handlers/views_test_area_access.inc files[] = tests/test_plugins/views_test_plugin_access_test_dynamic.inc files[] = tests/test_plugins/views_test_plugin_access_test_static.inc files[] = tests/test_plugins/views_test_plugin_style_test_mapping.inc @@ -312,9 +318,9 @@ files[] = tests/views_cache.test files[] = tests/views_view.test files[] = tests/views_ui.test -; Information added by drupal.org packaging script on 2013-04-09 -version = "7.x-3.7" +; Information added by Drupal.org packaging script on 2015-02-11 +version = "7.x-3.10" core = "7.x" project = "views" -datestamp = "1365499236" +datestamp = "1423648085" diff --git a/sites/all/modules/contrib/views/views/views.module b/sites/all/modules/contrib/views/views/views.module index fc427f49..9cdcfb58 100644 --- a/sites/all/modules/contrib/views/views/views.module +++ b/sites/all/modules/contrib/views/views/views.module @@ -355,9 +355,6 @@ function views_permission() { * Implement hook_menu(). */ function views_menu() { - // Any event which causes a menu_rebuild could potentially mean that the - // Views data is updated -- module changes, profile changes, etc. - views_invalidate_cache(); $items = array(); $items['views/ajax'] = array( 'title' => 'Views', @@ -468,16 +465,31 @@ function views_menu_alter(&$callbacks) { * The menu argument index. This counts from 1. */ function views_arg_load($value, $name, $display_id, $index) { - static $views = array(); + static $views = array(); - // Make sure we haven't already loaded this views argument for a similar menu - // item elsewhere. - $key = $name . ':' . $display_id . ':' . $value . ':' . $index; - if (isset($views[$key])) { - return $views[$key]; + $display_ids = is_array($display_id) ? $display_id : array($display_id); + $display_id = reset($display_ids); + + foreach ($display_ids as $id) { + // Make sure we haven't already loaded this views argument for a similar + // menu item elsewhere. Since access is always checked for the current user, + // we are sure that the static cache contains valid entries. + $key = $name . ':' . $id . ':' . $value . ':' . $index; + if (isset($views[$key])) { + return $views[$key]; + } + // Lazy load the view object to avoid unnecessary work. + if (!isset($view)) { + $view = views_get_view($name); + } + // Pick the first display we have access to. + if ($view && count($display_ids) > 1 && $view->access($id)) { + $display_id = $id; + break; + } } - if ($view = views_get_view($name)) { + if ($view) { $view->set_display($display_id); $view->init_handlers(); @@ -551,7 +563,7 @@ function views_page_alter(&$page) { } /** - * Implements MODULE_preprocess_HOOK(). + * Implements MODULE_preprocess_HOOK() for html.tpl.php. */ function views_preprocess_html(&$variables) { // If the page contains a view as its main content, contextual links may have @@ -569,7 +581,7 @@ function views_preprocess_html(&$variables) { if (!empty($variables['page']['#views_contextual_links_info'])) { $key = array_search('contextual-links-region', $variables['classes_array']); if ($key !== FALSE) { - unset($variables['classes_array'][$key]); + $variables['classes_array'] = array_diff($variables['classes_array'], array('contextual-links-region')); // Add the JavaScript, with a group and weight such that it will run // before modules/contextual/contextual.js. drupal_add_js(drupal_get_path('module', 'views') . '/js/views-contextual.js', array('group' => JS_LIBRARY, 'weight' => -1)); @@ -577,6 +589,27 @@ function views_preprocess_html(&$variables) { } } +/** +* Implements hook_preprocess_HOOK() for page.tpl.php. +*/ +function views_preprocess_page(&$variables) { + // If the page contains a view as its main content, contextual links may have + // been attached to the page as a whole; for example, by views_page_alter(). + // This allows them to be associated with the page and rendered by default + // next to the page title (which we want). However, it also causes the + // Contextual Links module to treat the wrapper for the entire page (i.e., + // the tag) as the HTML element that these contextual links are + // associated with. This we don't want; for better visual highlighting, we + // prefer a smaller region to be chosen. The region we prefer differs from + // theme to theme and depends on the details of the theme's markup in + // page.tpl.php, so we can only find it using JavaScript. We therefore remove + // the "contextual-links-region" class from the tag here and add + // JavaScript that will insert it back in the correct place. + if (!empty($variables['page']['#views_contextual_links_info'])) { + $variables['classes_array'] = array_diff($variables['classes_array'], array('contextual-links-region')); + } +} + /** * Implements hook_contextual_links_view_alter(). */ diff --git a/sites/all/modules/contrib/views/views/views_ui.info b/sites/all/modules/contrib/views/views/views_ui.info index 95ea0149..d8be6e4d 100644 --- a/sites/all/modules/contrib/views/views/views_ui.info +++ b/sites/all/modules/contrib/views/views/views_ui.info @@ -7,9 +7,9 @@ dependencies[] = views files[] = views_ui.module files[] = plugins/views_wizard/views_ui_base_views_wizard.class.php -; Information added by drupal.org packaging script on 2013-04-09 -version = "7.x-3.7" +; Information added by Drupal.org packaging script on 2015-02-11 +version = "7.x-3.10" core = "7.x" project = "views" -datestamp = "1365499236" +datestamp = "1423648085"