PluginProbe
Print, PDF & Email by PrintFriendly / 3.11.2
Print, PDF & Email by PrintFriendly v3.11.2
5.5.13 5.5.12 5.5.11 trunk 0.2 0.9 1.0 2.0 2.1.8 3.0 3.0.9 3.1.6 3.10.0 3.11.0 3.11.1 3.11.2 3.12.0 3.12.1 3.12.2 3.12.3 3.12.4 3.12.5 3.13.0 3.14.0 3.14.1 All 95 releases
printfriendly / pf.php

pf.php in Print, PDF & Email by PrintFriendly 3.11.2, at pf.php

1,632 lines 68.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 Plugin Name: Print, PDF & Email by PrintFriendly
5 Plugin URI: http://www.printfriendly.com
6 Description: PrintFriendly & PDF button for your website. Optimizes your pages and brand for print, pdf, and email.
7 Name and URL are included to ensure repeat visitors and new visitors when printed versions are shared.
8 Version: 3.11.2
9 Author: Print, PDF, & Email by PrintFriendly
10 Author URI: http://www.PrintFriendly.com
11
12 Changelog :
13 3.11.2 - Fix button upgrade for pf-icon-both.gif
14 3.11.1 - Bug fix
15 3.11.0 - Update buttons
16 3.10.0 - Change "leave us a rating" message.
17 3.9.2 - Correctly handle spaces in print-only detection
18 3.9.1 - Better print-only detection
19 3.9.0 - Add new button
20 3.8.7 - Bug fix.
21 3.8.6 - Allow default image setting to be small medium or large.
22 3.8.5 - Bug fix.
23 3.8.4 - Bug fix.
24 3.8.1 - Improve automatic error reporting.
25 3.8.0 - Add automatic error reporting.
26 3.7.6 - WooCommerce support improvments: remove upsells from print preview.
27 3.7.5 - WooCommerce support improvments: fix DOMDocument.loadHTML warnings.
28 3.7.4 - Added CSS Relative Position and Z-Index to button to avoid content covering the button.
29 3.7.3 - Always use https
30 3.7.2 - Use schema less URLs for loading icons
31 3.7.1 - Use www.printfriendly.com instead of app.printfriendly.com for redirects
32 3.7.0 - Remove http/https option, use current schema
33 3.6.0 - Allow custom HTML in Custom Button Text
34 3.5.4 - WooCommerce 'Content Algorithm' fix
35 3.5.3 - Fix security issues
36 3.5.2 - Fix code to support PHP 5.2
37 3.5.0 - WooCommerce product page improvements. Better support for product images, price, and description.
38 3.4.8 - Fix button images style
39 3.4.7 - Fix button style to remove underline
40 3.4.6 - Always removed PrintFriendly button underline regardless plugin CSS for button styles option
41 3.4.4 - Removed page content selection option - Wordpress Standard/Strict
42 3.4.2 - Fixed the issue occured due to new changes made in the page content selection options
43 3.4.1 - Improved page content selection options
44 3.4.0 - Fixed the admin javascript error and increased plugin text boxes size
45 3.3.10 - Implemented both Classic Google Analytics and Google Universal Analytics code.
46 3.3.9 - Removed the functionality that opens new window when JavaScript is disabled.
47 3.3.8 - Shortcode Bug fix, urlencode button href
48 3.3.7 - Readme.txt update
49 3.3.6 - Fixed JS optimization Bug
50 3.3.5 - Wordpress 3.8 support
51 3.3.4 - Provided Algorithm Options
52 3.3.3 - Using WP content hook for all Buttons
53 3.3.2 - Algorithm update
54 3.3.1 - SSL support issue.
55 3.3.0 - Printfriendly custom commands support and PF Algo V6 release.
56 3.2.10 - Fixed Bug.
57 3.2.9 - Added Support for Google Analytics
58 3.2.8 - Algorithm Update
59 3.2.7 - Removed Break tag from button code.
60 3.2.6 - Fixed Button behavior when displayed on Homepage for NON-JS version. Fixed CSS issue with Button when placed above content. Fixed box-shadow issue with button. Custom print and pdf options now available for Non-JS version (custom header, custom css, image alignment, etc.). Fixed custom header bug.
61 3.2.5 - Added hide images and image style options. Improved input validation. Improved output escaping. Removed printfriendly post_class. Small i8n fix. Few small HTML fixes.
62 3.2.4 - Add printfriendly post_class. Fixed minor JS bug. Added redundancy to uninstall script.
63 3.2.3 - Rolling back to version 3.2.1
64 3.2.2 - Add printfriendly post_class. Add printfriendly button display settings per individual category. Fixed minor JS bug. Added redundancy to uninstall script.
65 3.2.1 - Improve script loading.
66 3.2.0 - Important chrome issue fix. Ie syntax error fix.
67 3.1.9 - Minor css detail.
68 3.1.8 - Add printfriendly options to allow/not allow print, pdf, email from the Printfriendly and PDF dialog.
69 3.1.7 - Revert default print button show settings. Prevent easy override of print button text-decoration and border style properties.
70 3.1.6 - Adding PrintFriendly and PDF alignment style classes.
71 3.1.5 - Set button appearance in more flexible way. Remove styles that interfered with wordpress themes. Add shortcode for printfriendly button. Fix redirect to printfriendly.com link. Added custom css feature.
72 3.1.4 - Changed https url. Don't hide text change box when disabling css.
73 3.1.3 - Fixed bug with disable css option
74 3.1.2 - Added disable css option to admin settings.
75 3.1.1 - Fixed admin js caching.
76 3.1.0 - Fixed admin css caching.
77 3.0.9 - New features: Custom header, disable click-to-delete, https support (beta), PrintFriendly Pro (ad-free).
78 3.0.8 - Reordered PrintFriendly & PDF buttons. CSS stylesheet option is now checked by default.
79 3.0.7 - Added additional images for print button.
80 3.0.6 - Fix bug that would display button on category pages when not wanted.
81 3.0.5 - Include button on category pages if user has selected "All pages".
82 3.0.4 - Align-right and align-center support for themes that remove WordPress core css.
83 3.0.3 - Support for bad themes that alter template tags and prevent JavaScript from loading in footer.
84 3.0.2 - Fixed JS bug with Google Chrome not submitting and fixed input validation issues.
85 3.0.1 - Fixed minor JS bug.
86 3.0 - Complete overhaul of the plugin by Joost de Valk.
87 2.1.8 - The Print Button was showing up on printed, or PDF, pages. Junk! Print or PDF button no longer displayed on printed out page or PDF.
88 2.1.7 - Changed button from span to div to support floating.
89 2.1.6 - Added rel="nofollow" to links. Changed button from <a> to <span> to fix target_new or target_blank issues.
90 2.1.5 - Fix conflict with link tracking plugins. Custom image support for hosted wordpress sites.
91 2.1.4 - wp head fix.
92 2.1.3 - Manual option for button placement. Security updates for multi-author sites.
93 2.1.2 - Improvements to Setting page layout and PrintFriendly button launching from post pages.
94 2.1.1 - Fixed admin settings bug.
95 2.1 - Update for mult-author websites. Improvements to Settings page.
96 2.0 - Customize the style, placement, and pages your printfriendly button appears.
97 1.5 - Added developer ability to disable hook and use the pf_show_link() function to better be used in a custom theme & Uninstall cleanup.
98 1.4 - Changed Name.
99 1.3 - Added new buttons, removed redundant code.
100 1.2 - User can choose to show or not show buttons on the listing page.
101 */
102
103 /**
104 * PrintFriendly WordPress plugin. Allows easy embedding of printfriendly.com buttons.
105 * @package PrintFriendly_WordPress
106 * @author PrintFriendly <support@printfriendly.com>
107 * @copyright Copyright (C) 2012, PrintFriendly
108 */
109 if ( ! class_exists( 'PrintFriendly_WordPress' ) ) {
110
111 /**
112 * Class containing all the plugins functionality.
113 * @package PrintFriendly_WordPress
114 */
115 class PrintFriendly_WordPress {
116 /**
117 * Current plugin version.
118 * @var string
119 */
120 var $plugin_version = '3.11.2';
121
122 /**
123 * The hook, used for text domain as well as hooks on pages and in get requests for admin.
124 * @var string
125 */
126 var $hook = 'printfriendly';
127
128 /**
129 * The option name, used throughout to refer to the plugins option and option group.
130 * @var string
131 */
132 var $option_name = 'printfriendly_option';
133
134 /**
135 * The plugins options, loaded on init containing all the plugins settings.
136 * @var array
137 */
138 var $options = array();
139
140 /**
141 * Database version, used to allow for easy upgrades to / additions in plugin options between plugin versions.
142 * @var int
143 */
144 var $db_version = 14;
145
146 /**
147 * Settings page, used within the plugin to reliably load the plugins admin JS and CSS files only on the admin page.
148 * @var string
149 */
150 var $settings_page = '';
151
152 /**
153 * GetSentry error reporting client
154 * @var Raven_Client
155 */
156 var $raven_client = null;
157
158 /**
159 * Constructor
160 *
161 * @since 3.0
162 */
163 function __construct() {
164 try {
165 // delete_option( $this->option_name );
166
167 // Retrieve the plugin options
168 $this->options = get_option( $this->option_name );
169
170 // If the options array is empty, set defaults
171 if ( ! is_array( $this->options ) )
172 $this->set_defaults();
173
174 // Sentry PHP SDK supports PHP 5.3 and higher.
175 if( isset( $this->options['enable_error_reporting'] ) && $this->options['enable_error_reporting'] == 'yes' && version_compare(PHP_VERSION, '5.3.0') >= 0) {
176 $this->init_error_reporting();
177 }
178
179 /**
180 * Set page content selection option "Wordpress Standard/Strict" to "WP Template"
181 */
182 if( isset( $this->options['pf_algo'] ) && $this->options['pf_algo'] == 'ws' ){
183 $this->options['pf_algo'] = 'wp';
184 update_option( $this->option_name, $this->options );
185 }
186
187 // If the version number doesn't match, upgrade
188 if ( $this->db_version > $this->options['db_version'] )
189 $this->upgrade();
190
191 add_action( 'wp_head', array( &$this, 'front_head' ) );
192 // automaticaly add the link
193 if( !$this->is_manual() ) {
194 add_filter( 'the_content', array( &$this, 'show_link' ) );
195 add_filter( 'the_excerpt', array( &$this, 'show_link' ) );
196 }
197
198 add_action('the_content', array(&$this, 'add_pf_content_class_around_content_hook'));
199
200 // Admin hooks
201 if ( is_admin() ) {
202 // Hook into init for registration of the option and the language files
203 add_action( 'admin_init', array( &$this, 'init' ) );
204
205 // Register the settings page
206 add_action( 'admin_menu', array( &$this, 'add_config_page' ) );
207
208 // Register the contextual help
209 add_filter( 'contextual_help', array( &$this, 'contextual_help' ), 10, 2 );
210
211 // Enqueue the needed scripts and styles
212 add_action( 'admin_enqueue_scripts',array( &$this, 'admin_enqueue_scripts' ) );
213
214 // Register a link to the settings page on the plugins overview page
215 add_filter( 'plugin_action_links', array( &$this, 'filter_plugin_actions' ), 10, 2 );
216 }
217 } catch(Exception $e) {
218 $this->raven_catch($e);
219 }
220 }
221
222 function init_error_reporting() {
223 try {
224 require_once 'vendor/PrintFriendly/Raven/Autoloader.php';
225
226 PrintFriendly_Raven_Autoloader::register();
227
228 $this->raven_client = new PrintFriendly_Raven_Client('https://46a55182ffbe477c8cf1cb0f1cee36c2:a32ee5b4fad940c4808845b618147f21@sentry.io/171161', array(
229 'release' => $this->plugin_version,
230 'timeout' => 4
231 ));
232
233 $this->raven_client->tags_context(array(
234 'wordpress-version' => get_bloginfo('version'),
235 'php-version' => PHP_VERSION
236 ));
237
238 $this->raven_client->setSendCallback(array( &$this, 'raven_callback' ));
239 } catch (Exception $e) {
240 if (!ini_get('display_errors')) {
241 error_log('PrintFriendly init_error_reporting Error: ' . $e);
242 }
243
244 $this->raven_catch($e);
245 }
246 }
247
248 function raven_callback($data) {
249 try {
250 return isset($data) && preg_match('/printfriendly/', json_encode($data));
251 } catch (Exception $e) {
252 return true;
253 }
254 }
255
256 function raven_catch($e) {
257 if (isset($this->raven_client)) {
258 try {
259 $this->raven_client->captureException($e);
260 } catch(Exception $e) {}
261 }
262 }
263
264 /**
265 * Adds wraps content in pf-content class to help Printfriendly algo determine the content
266 *
267 * @since 3.2.8
268 *
269 **/
270 function add_pf_content_class_around_content_hook($content = false) {
271 try {
272 if( $this->is_wp_algo_on($content) ) {
273 add_action( 'wp_footer', array( &$this, 'print_script_footer' ));
274 return '<div class="pf-content">'.$content.'</div>';
275 } else {
276 return $content;
277 }
278 } catch (Exception $e) {
279 $this->raven_catch($e);
280 }
281 }
282
283 /**
284 * Override to check if print-only command is being used
285 *
286 * @since 3.3.0
287 **/
288 function print_only_override($content) {
289 $pattern = '/class\s*?=\s*?(["\']|["\']([^"\']*?)\s)print-only(["\']|\s([^"\']*?)["\'])/';
290 $pf_pattern = '/class\s*?=\s*?(["\']|["\']([^"\']*?)\s)pf-content(["\']|\s([^"\']*?)["\'])/';
291
292 return (preg_match($pattern, $content) || preg_match($pf_pattern, $content)) ;
293 }
294
295 /**
296 * Check if WP Algorithm is selected and content doesn't use print-only
297 *
298 * @since 3.5.4
299 **/
300 function is_wp_algo_on($content) {
301 return !class_exists('WooCommerce') && isset($this->options['pf_algo']) && $content && $this->options['pf_algo'] == 'wp' && !$this->print_only_override($content);
302 }
303
304 /**
305 * PHP 4 Compatible Constructor
306 *
307 * @since 3.0
308 */
309 function PrintFriendly_WordPress() {
310 $this->__construct();
311 }
312
313 /**
314 * Prints the PrintFriendly button CSS, in the header.
315 *
316 * @since 3.0
317 */
318 function front_head() {
319 try {
320 ?>
321 <style type="text/css" media="screen">
322 div.printfriendly a, div.printfriendly a:link, div.printfriendly a:hover, div.printfriendly a:visited {
323 text-decoration: none;
324 border: none;
325 }
326 </style>
327 <?php
328
329 if ( isset( $this->options['enable_css'] ) && $this->options['enable_css'] != 'on' )
330 return;
331 ?>
332 <style type="text/css" media="screen">
333 div.printfriendly {
334 margin: <?php echo $this->options['margin_top'].'px '.$this->options['margin_right'].'px '.$this->options['margin_bottom'].'px '.$this->options['margin_left'].'px'; ?>;
335 position: relative;
336 z-index: 1000;
337 }
338 div.printfriendly a, div.printfriendly a:link, div.printfriendly a:visited {
339 font-size: <?php echo $this->options['text_size']; ?>px;
340 color: <?php echo $this->options['text_color']; ?>;
341 vertical-align: bottom;
342 }
343 .printfriendly a {
344 box-shadow:none;
345 }
346 .printfriendly a:hover {
347 cursor: pointer;
348 }
349 .printfriendly a img {
350 border: none;
351 padding:0;
352 margin-right: 6px;
353 box-shadow: none;
354 -webkit-box-shadow: none;
355 -moz-box-shadow: none;
356 }
357 .printfriendly a span{
358 vertical-align: bottom;
359 }
360 .pf-alignleft {
361 float: left;
362 }
363 .pf-alignright {
364 float: right;
365 }
366 div.pf-aligncenter {
367 display: block;
368 margin-left: auto;
369 margin-right: auto;
370 text-align: center;
371 }
372 </style>
373 <style type="text/css" media="print">
374 .printfriendly {
375 display: none;
376 }
377 </style>
378 <?php
379 } catch (Exception $e) {
380 $this->raven_catch($e);
381 }
382 }
383
384 /**
385 * Prints the PrintFriendly JavaScript, in the footer, and loads it asynchronously.
386 *
387 * @since 3.0
388 */
389 function print_script_footer() {
390 if (isset($this->options['javascript']) && $this->options['javascript'] == 'no')
391 return;
392
393 else {
394 $tagline = $this->options['tagline'];
395 $image_url = $this->options['image_url'];
396 if( $this->options['logo'] == 'favicon' ) {
397 $tagline = '';
398 $image_url = '';
399 }
400
401 // Currently we use v3 for both: normal and password protected sites
402 ?>
403 <script type="text/javascript">
404
405 var pfHeaderImgUrl = '<?php echo esc_js(esc_url($image_url)); ?>';
406 var pfHeaderTagline = '<?php echo esc_js($tagline); ?>';
407 var pfdisableClickToDel = '<?php echo esc_js($this->options['click_to_delete']); ?>';
408 var pfImagesSize = '<?php echo esc_js($this->options['images-size']); ?>';
409 var pfImageDisplayStyle = '<?php echo esc_js($this->options['image-style']); ?>';
410 var pfDisableEmail = '<?php echo esc_js($this->options['email']); ?>';
411 var pfDisablePDF = '<?php echo esc_js($this->options['pdf']); ?>';
412 var pfDisablePrint = '<?php echo esc_js($this->options['print']); ?>';
413 var pfCustomCSS = '<?php echo esc_js(esc_url($this->options['custom_css_url'])); ?>';
414 (function() {
415 var e = document.createElement('script'); e.type="text/javascript";
416 e.src = 'https://cdn.printfriendly.com/printfriendly.js';
417 document.getElementsByTagName('head')[0].appendChild(e);
418 })();
419 </script>
420 <?php
421 }
422 }
423
424 /**
425 * Primary frontend function, used either as a filter for the_content, or directly using pf_show_link
426 *
427 * @since 3.0
428 * @param string $content the content of the post, when the function is used as a filter
429 * @return string $button or $content with the button added to the content when appropriate, just the content when button shouldn't be added or just button when called manually.
430 */
431 function show_link( $content = false ) {
432 try {
433 $is_manual = $this->is_manual();
434
435 if( !$content && !$is_manual )
436 return "";
437
438 $button = $this->getButton();
439 if ( $is_manual )
440 {
441 // Hook the script call now, so it only get's loaded when needed, and need is determined by the user calling pf_button
442 add_action( 'wp_footer', array( &$this, 'print_script_footer' ) );
443 return $button;
444 }
445
446 else
447 {
448 if ( (is_page() && ( isset($this->options['show_on_pages']) && 'on' === $this->options['show_on_pages'] ) )
449 || (is_home() && ( ( isset($this->options['show_on_homepage']) && 'on' === $this->options['show_on_homepage'] ) && $this->category_included() ) )
450 || (is_tax() && ( ( isset($this->options['show_on_taxonomies']) && 'on' === $this->options['show_on_taxonomies'] ) && $this->category_included() ) )
451 || (is_category() && ( ( isset($this->options['show_on_categories']) && 'on' === $this->options['show_on_categories'] ) && $this->category_included() ) )
452 || (is_single() && ( ( isset($this->options['show_on_posts']) && 'on' === $this->options['show_on_posts'] ) && $this->category_included() ) ) )
453 {
454 // Hook the script call now, so it only get's loaded when needed, and need is determined by the user calling pf_button
455 add_action( 'wp_footer', array( &$this, 'print_script_footer' ) );
456
457 if ( $this->options['content_placement'] == 'before' )
458 return $button.$content;
459 else
460 return $content.$button;
461 }
462 else
463 {
464 return $content;
465 }
466 }
467 } catch (Exception $e) {
468 $this->raven_catch($e);
469 }
470 }
471
472
473 /**
474 * @since 3.3.8
475 * @returns Printfriendly Button HTML
476 */
477
478 function getButton($add_footer_script = false) {
479 if($add_footer_script) {
480 add_action( 'wp_footer', array( &$this, 'print_script_footer' ) );
481 }
482 $js_enabled = $this->js_enabled();
483 $analytics_code = "";
484 $onclick = '';
485
486 if ( $this->google_analytics_enabled() ) {
487 $title_var = "NULL";
488 $analytics_code = "if(typeof(_gaq) != 'undefined') { _gaq.push(['_trackEvent','PRINTFRIENDLY', 'print', '".$title_var."']);
489 }else if(typeof(ga) != 'undefined') { ga('send', 'event','PRINTFRIENDLY', 'print', '".$title_var."'); }";
490 if( $js_enabled ) {
491 $onclick = 'onclick="window.print();'. $analytics_code .' return false;"';
492 } else {
493 $onclick = '';
494 }
495 } else if ( $js_enabled ) {
496 $onclick = 'onclick="window.print(); return false;"';
497 }
498
499 if( $js_enabled ){
500 $href = '#';
501 } else {
502 $href = 'https://www.printfriendly.com/print?url='.urlencode(get_permalink());
503 }
504
505 if (!$js_enabled) {
506 if($this->google_analytics_enabled()) {
507 $onclick = $onclick.' onclick="'.$analytics_code.'"';
508 }
509 $href = "https://www.printfriendly.com/print?headerImageUrl=".urlencode($this->options['image_url'])."&headerTagline=".urlencode($this->options['tagline'])."&pfCustomCSS=".urlencode($this->options['custom_css_url'])."&imageDisplayStyle=".urlencode($this->options['image-style'])."&disableClickToDel=".urlencode($this->options['click_to_delete'])."&disablePDF=".urlencode($this->options['pdf'])."&disablePrint=".urlencode($this->options['print'])."&disableEmail=".urlencode($this->options['email'])."&imagesSize=".urlencode($this->options['images-size'])."&url=".urlencode(get_permalink())."&source=wp";
510 }
511 if ( !is_singular() && '' != $onclick && $js_enabled) {
512 $onclick = '';
513 $href = add_query_arg('pfstyle','wp',get_permalink());
514 }
515
516 $align = '';
517 if ( 'none' != $this->options['content_position'] )
518 $align = ' pf-align'.$this->options['content_position'];
519 $href = str_replace("&", "&amp;", $href );
520 $button = apply_filters( 'printfriendly_button', '<div class="printfriendly'.$align.'"><a href="'.$href.'" rel="nofollow" '.$onclick.' class="noslimstat">'.$this->button().'</a></div>' );
521 return $button;
522 }
523
524
525 /**
526 * @since 3.2.9
527 * @returns if google analytics enabled
528 */
529 function google_analytics_enabled() {
530 return isset( $this->options['enable_google_analytics'] ) && $this->options['enable_google_analytics'] == 'yes';
531 }
532 /**
533 * @since 3.2.6
534 * @return boolean true if JS is enabled for the plugin
535 **/
536 function js_enabled() {
537 return isset( $this->options['javascript'] ) && $this->options['javascript'] == 'yes';
538 }
539
540 /**
541 * Filter posts by category.
542 *
543 * @since 3.2.2
544 * @return boolean true if post belongs to category selected for button display
545 */
546 function category_included() {
547 // return ( 'all' === $this->options['category_ids'][0] || in_category($this->options['category_ids']) );
548 return true;
549 }
550
551 /**
552 * Register the textdomain and the options array along with the validation function
553 *
554 * @since 3.0
555 */
556 function init() {
557 try {
558 // Allow for localization
559 load_plugin_textdomain( $this->hook, false, basename( dirname( __FILE__ ) ) . '/languages' );
560
561 // Register our option array
562 register_setting( $this->option_name, $this->option_name, array( &$this, 'options_validate' ) );
563 } catch (Exception $e) {
564 $this->raven_catch($e);
565 }
566 }
567
568 /**
569 * Validate the saved options.
570 *
571 * @since 3.0
572 * @param array $input with unvalidated options.
573 * @return array $valid_input with validated options.
574 */
575 function options_validate( $input ) {
576 // Prevent CSRF attack
577 check_admin_referer( 'pf-options', 'pf-nonce' );
578
579 $valid_input = $input;
580
581 // Section 1 options
582 if ( !isset( $input['button_type'] ) || !in_array( $input['button_type'], array(
583 'buttons/printfriendly-pdf-email-button.png',
584 'buttons/printfriendly-pdf-email-button-md.png',
585 'buttons/printfriendly-pdf-email-button-notext.png', // buttongroup1
586 'buttons/printfriendly-pdf-button.png',
587 'buttons/printfriendly-pdf-button-nobg.png',
588 'buttons/printfriendly-pdf-button-nobg-md.png', // buttongroup2
589 'buttons/printfriendly-button.png',
590 'buttons/printfriendly-button-nobg.png',
591 'buttons/printfriendly-button-md.png',
592 'buttons/printfriendly-button-lg.png', // buttongroup3
593 'buttons/print-button.png',
594 'buttons/print-button-nobg.png',
595 'buttons/print-button-gray.png', // buttongroup3
596 'custom-image' // custom
597 ) ) ) {
598 $valid_input['button_type'] = 'buttons/printfriendly-button.png';
599 }
600
601 // @todo custom image url validation
602 if ( !isset( $input['custom_image'] ) || empty( $input['custom_image'] ) )
603 $valid_input['custom_image'] = '';
604
605 // @todo validate optional custom text
606 if ( !isset( $input['custom_text'] ) ) {
607 $valid_input['custom_text'] = 'Print Friendly';
608 }
609 /* else {
610
611 }*/
612
613 // Custom button selected, but no url nor text given, reset button type to default
614 if( 'custom-image' === $valid_input['button_type'] && ( '' === $valid_input['custom_image'] && '' === $input['custom_text'] ) ) {
615 $valid_input['button_type'] = 'buttons/printfriendly-button.png';
616 add_settings_error( $this->option_name, 'invalid_custom_image', __( 'No valid custom image url received, please enter a valid url to use a custom image.', $this->hook ) );
617 }
618
619
620 $valid_input['text_size'] = (int) $input['text_size'];
621 if ( !isset($valid_input['text_size']) || 0 == $valid_input['text_size'] ) {
622 $valid_input['text_size'] = 14;
623 } else if ( 25 < $valid_input['text_size'] || 9 > $valid_input['text_size'] ) {
624 $valid_input['text_size'] = 14;
625 add_settings_error( $this->option_name, 'invalid_text_size', __( 'The text size you entered is invalid, please stay between 9px and 25px', $this->hook ) );
626 }
627
628 if ( !isset( $input['text_color'] )) {
629 $valid_input['text_color'] = $this->options['text_color'];
630 } else if ( ! preg_match('/^#[a-f0-9]{3,6}$/i', $input['text_color'] ) ) {
631 // Revert to previous setting and throw error.
632 $valid_input['text_color'] = $this->options['text_color'];
633 add_settings_error( $this->option_name, 'invalid_color', __( 'The color you entered is not valid, it must be a valid hexadecimal RGB font color.', $this->hook ) );
634 }
635
636
637
638 /* Section 2 options */
639 if ( !isset( $input['enable_css'] ) || 'off' !== $input['enable_css'] )
640 $valid_input['enable_css'] = 'on';
641
642 if ( !isset( $input['content_position'] ) || !in_array( $input['content_position'], array( 'none', 'left', 'center', 'right' ) ) )
643 $valid_input['content_position'] = 'left';
644
645 if ( !isset( $input['content_placement'] ) || !in_array( $input['content_placement'], array( 'before', 'after' ) ) )
646 $valid_input['content_placement'] = 'after';
647
648 foreach ( array( 'margin_top', 'margin_right', 'margin_bottom', 'margin_left' ) as $opt )
649 $valid_input[$opt] = (int) $input[$opt];
650
651 unset( $opt );
652
653
654 /* Section 3 options */
655 foreach ( array( 'show_on_posts', 'show_on_pages', 'show_on_homepage', 'show_on_categories', 'show_on_taxonomies' ) as $opt ) {
656 if ( !isset( $input[$opt] ) || 'on' !== $input[$opt] ) {
657 unset( $valid_input[$opt] );
658 }
659 }
660 unset( $opt );
661
662 // Just in case
663 if( isset( $input['show_on_template'] ) )
664 unset( $valid_input['show_on_template'] );
665
666
667 if( isset( $input['category_ids'] ) ) {
668 /**
669 * Validate received category ids:
670 * - Is there only one array item and does it contain the string text 'all' ? => pass
671 * - Otherwise, make sure the ids are integer values
672 */
673 /* $valid_input['category_ids'] = explode(',', $input['category_ids']);
674 $valid_input['category_ids'] = array_map( 'trim', $valid_input['category_ids'] );
675 if( ( count( $valid_input['category_ids'] ) === 1 && 'all' === $valid_input['category_ids'][0] ) === false ) {
676 foreach( $valid_input['category_ids'] as $k => $v ) {
677 if( $v !== '' && ( ctype_digit( (string) $v ) === true && ( intval( $v ) == $v ) ) ) {
678 $valid_input['category_ids'][$k] = intval( $v );
679 }
680 else {
681 // Invalid input - Show error message ?
682 unset( $valid_input['category_ids'][$k] );
683 }
684 }
685 }*/
686 unset( $valid_input['category_ids'] );
687 }
688
689 //echo '<pre>'.print_r($input,1).'</pre>';
690 //die;
691
692
693
694 /* Section 4 options */
695 if ( !isset( $input['logo'] ) || !in_array( $input['logo'], array( 'favicon', 'upload-an-image' ) ) )
696 $valid_input['logo'] = 'favicon';
697
698 // @todo custom logo url validation
699 if ( !isset( $input['image_url'] ) || empty( $input['image_url'] ) )
700 $valid_input['image_url'] = '';
701
702 // @todo validate optional tagline text
703 if ( !isset( $input['tagline'] ) ) {
704 $valid_input['tagline'] = '';
705 }
706 /* else {
707
708 }*/
709
710 // Custom logo selected, but no valid url given, reset logo to default
711 if( 'upload-an-image' === $valid_input['logo'] && '' === $valid_input['image_url'] ) {
712 $valid_input['logo'] = 'favicon';
713 add_settings_error( $this->option_name, 'invalid_custom_logo', __( 'No valid custom logo url received, please enter a valid url to use a custom logo.', $this->hook ) );
714 }
715
716
717 if ( !isset( $input['image-style'] ) || !in_array( $input['image-style'], array( 'right', 'left', 'none', 'block' ) ) )
718 $valid_input['image-style'] = 'right';
719
720
721 foreach( array( 'click_to_delete', 'email', 'pdf', 'print', ) as $opt ) {
722 if( !isset( $input[$opt] ) || !in_array( $input[$opt], array( '0', '1' ) ) ) {
723 $valid_input[$opt] = '0';
724 }
725 }
726 unset( $opt );
727
728 if( !isset( $input['images-size'] ) || !in_array( $input['images-size'], array( 'full-size', 'remove-images', 'large', 'medium', 'small' ) ) ) {
729 $valid_input['images-size'] = 'full-size';
730 }
731
732 // @todo custom css url validation
733 if ( !isset( $input['custom_css_url'] ) || empty( $input['custom_css_url'] ) )
734 $valid_input['custom_css_url'] = '';
735
736
737
738 /* Section 5 options */
739 if ( !isset( $input['password_protected'] ) || !in_array( $input['password_protected'], array( 'no', 'yes' ) ) )
740 $valid_input['password_protected'] = 'no';
741
742 if ( !isset( $input['javascript'] ) || !in_array( $input['javascript'], array( 'no', 'yes' ) ) )
743 $valid_input['javascript'] = 'yes';
744
745 /*Analytics Options */
746 if ( !isset( $input['enable_google_analytics'] ) || !in_array( $input['enable_google_analytics'], array( 'no', 'yes' ) ) ) {
747 $valid_input['enable_google_analytics'] = "no";
748 }
749
750 if ( !isset( $input['pf_algo'] ) || !in_array( $input['pf_algo'], array( 'wp', 'pf' ) ) ) {
751 $valid_input['pf_algo'] = "wp";
752 }
753
754 /* Database version */
755 $valid_input['db_version'] = $this->db_version;
756
757 return $valid_input;
758 }
759
760 /**
761 * Register the config page for all users that have the manage_options capability
762 *
763 * @since 3.0
764 */
765 function add_config_page() {
766 try {
767 $this->settings_page = add_options_page( __( 'PrintFriendly Options', $this->hook ), __( 'Print Friendly & PDF', $this->hook ), 'manage_options', $this->hook, array( &$this, 'config_page' ) );
768
769 //register callback gets call prior your own page gets rendered
770 add_action('load-'.$this->settings_page, array(&$this, 'on_load_printfriendly'));
771 } catch (Exception $e) {
772 $this->raven_catch($e);
773 }
774 }
775
776 /**
777 * Shows help on the plugin page when clicking on the Help button, top right.
778 *
779 * @since 3.0
780 */
781 function contextual_help( $contextual_help, $screen_id ) {
782 try {
783 if ( $this->settings_page == $screen_id ) {
784 $contextual_help = '<strong>'.__( "Need Help?", $this->hook ).'</strong><br/>'
785 .sprintf( __( "Be sure to check out the %s!", $this->hook), '<a href="https://wordpress.org/extend/plugins/printfriendly/faq/">'.__( "Frequently Asked Questions", $this->hook ).'</a>' );
786 }
787 return $contextual_help;
788 } catch (Exception $e) {
789 $this->raven_catch($e);
790 }
791 }
792
793 /**
794 * Enqueue the scripts for the admin settings page
795 *
796 * @since 3.0
797 * @param string $hook_suffix hook to check against whether the current page is the PrintFriendly settings page.
798 */
799 function admin_enqueue_scripts( $screen_id ) {
800 try {
801 if ( $this->settings_page == $screen_id ) {
802 $ver = '3.2.5';
803 wp_register_script( 'pf-color-picker', plugins_url( 'colorpicker.js', __FILE__ ), array( 'jquery', 'media-upload' ), $ver );
804 wp_register_script( 'pf-admin-js', plugins_url( 'admin.js', __FILE__ ), array( 'jquery', 'media-upload' ), $ver );
805
806 wp_enqueue_script( 'pf-color-picker' );
807 wp_enqueue_script( 'pf-admin-js' );
808
809
810 wp_enqueue_style( 'printfriendly-admin-css', plugins_url( 'admin.css', __FILE__ ), array(), $ver);
811 }
812 } catch (Exception $e) {
813 $this->raven_catch($e);
814 }
815 }
816
817 /**
818 * Register the settings link for the plugins page
819 *
820 * @since 3.0
821 * @param array $links the links for the plugins.
822 * @param string $file filename to check against plugins filename.
823 * @return array $links the links with the settings link added to it if appropriate.
824 */
825 function filter_plugin_actions( $links, $file ){
826 try {
827 // Static so we don't call plugin_basename on every plugin row.
828 static $this_plugin;
829 if ( ! $this_plugin ) $this_plugin = plugin_basename( __FILE__ );
830
831 if ( $file == $this_plugin ){
832 $settings_link = '<a href="options-general.php?page='.$this->hook.'">' . __( 'Settings', $this->hook ) . '</a>';
833 array_unshift( $links, $settings_link ); // before other links
834 }
835
836 return $links;
837 } catch (Exception $e) {
838 $this->raven_catch($e);
839 }
840 }
841
842 /**
843 * Set default values for the plugin. If old, as in pre 1.0, settings are there, use them and then delete them.
844 *
845 * @since 3.0
846 */
847 function set_defaults() {
848 try {
849 // Set some defaults
850 $this->options = array(
851 'button_type' => 'buttons/printfriendly-button.png',
852 'content_position' => 'left',
853 'content_placement' => 'after',
854 'custom_image' => 'https://cdn.printfriendly.com/icons/printfriendly-icon-md.png',
855 'custom_text' => 'Print Friendly',
856 'enable_css' => 'on',
857 'margin_top' => '12',
858 'margin_right' => '12',
859 'margin_bottom' => '12',
860 'margin_left' => '12',
861 'show_on_posts' => 'on',
862 'show_on_pages' => 'on',
863 'text_color' => '#6D9F00',
864 'text_size' => 14,
865 'logo' => 'favicon',
866 'image_url' => '',
867 'tagline' => '',
868 'click_to_delete' => '0', // 0 - allow, 1 - do not allow
869 'hide-images' => '0', // 0 - show images, 1 - hide images
870 'image-style' => 'right', // 'right', 'left', 'none', 'block'
871 'email' => '0', // 0 - allow, 1 - do not allow
872 'pdf' => '0', // 0 - allow, 1 - do not allow
873 'print' => '0', // 0 - allow, 1 - do not allow
874 'password_protected' => 'no',
875 'javascript' => 'yes',
876 'custom_css_url' => '',
877 'enable_google_analytics' => 'no',
878 'enable_error_reporting' => 'yes',
879 'pf_algo' => 'wp',
880 'images-size' => 'full-size'
881 );
882
883 // Check whether the old badly named singular options are there, if so, use the data and delete them.
884 foreach ( array_keys( $this->options ) as $opt ) {
885 $old_opt = get_option( 'pf_'.$opt );
886 if ( $old_opt !== false ) {
887 $this->options[$opt] = $old_opt;
888 delete_option( 'pf_'.$opt );
889 }
890 }
891
892 // This should always be set to the latest immediately when defaults are pushed in.
893 $this->options['db_version'] = $this->db_version;
894
895 update_option( $this->option_name, $this->options );
896 } catch (Exception $e) {
897 $this->raven_catch($e);
898 }
899 }
900
901 /**
902 * Upgrades the stored options, used to add new defaults if needed etc.
903 *
904 * @since 3.0
905 */
906 function upgrade() {
907 // update options to version 2
908 if($this->options['db_version'] < 2) {
909
910 $additional_options = array(
911 'enable_css' => 'on',
912 'logo' => 'favicon',
913 'image_url' => '',
914 'tagline' => '',
915 'click_to_delete' => '0',
916 'password_protected' => 'no',
917 'javascript' => 'yes'
918 );
919
920 // use old javascript_include value to initialize javascript
921 if(!isset($this->options['javascript_include']))
922 $additional_options['javascript'] = 'no';
923
924 unset($this->options['javascript_include']);
925 unset($this->options['javascript_fallback']);
926
927 // correcting badly named option
928 if(isset($this->options['disable_css'])) {
929 $additional_options['enable_css'] = $this->options['disable_css'];
930 unset($this->options['disable_css']);
931 }
932
933 // check whether image we do not list any more was used
934 if(in_array($this->options['button_type'], array('button-print-whgn20.png', 'pf_button_sq_qry_m.png', 'pf_button_sq_qry_l.png', 'pf_button_sq_grn_m.png', 'pf_button_sq_grn_l.png'))) {
935 // previous version had a bug with button name
936 if(in_array($this->options['button_type'], array('pf_button_sq_qry_m.png', 'pf_button_sq_qry_l.png')))
937 $this->options['button_type'] = str_replace('qry', 'gry', $this->options['button_type']);
938
939 $image_address = 'https://cdn.printfriendly.com/'.$this->options['button_type'];
940 $this->options['button_type'] = 'custom-image';
941 $this->options['custom_text'] = '';
942 $this->options['custom_image'] = $image_address;
943 }
944
945 $this->options = array_merge($this->options, $additional_options);
946 }
947
948 // update options to version 3
949 if($this->options['db_version'] < 3) {
950
951 $old_show_on = $this->options['show_list'];
952 // 'manual' setting
953 $additional_options = array('custom_css_url' => '');
954
955 if($old_show_on == 'all') {
956 $additional_options = array(
957 'show_on_pages' => 'on',
958 'show_on_posts' => 'on',
959 'show_on_homepage' => 'on',
960 'show_on_categories' => 'on',
961 'show_on_taxonomies' => 'on'
962 );
963 }
964
965 if($old_show_on == 'single') {
966 $additional_options = array(
967 'show_on_pages' => 'on',
968 'show_on_posts' => 'on'
969 );
970 }
971
972 if($old_show_on == 'posts') {
973 $additional_options = array(
974 'show_on_posts' => 'on',
975 );
976 }
977
978 unset($this->options['show_list']);
979
980 $this->options = array_merge($this->options, $additional_options);
981 }
982
983 // update options to version 4
984 if($this->options['db_version'] < 4) {
985
986 $additional_options = array(
987 'email' => '0',
988 'pdf' => '0',
989 'print' => '0',
990 );
991
992 $this->options = array_merge($this->options, $additional_options);
993 }
994
995 // update options to version 6
996 // Replacement for db version 5 - should also be run for those already upgraded
997 if($this->options['db_version'] < 6) {
998 unset($this->options['category_ids']);
999 }
1000
1001 if($this->options['db_version'] < 7) {
1002 $additional_options = array(
1003 'hide-images' => '0',
1004 'image-style' => 'right',
1005 );
1006
1007 $this->options = array_merge($this->options, $additional_options);
1008 }
1009
1010 if($this->options['db_version'] < 8) {
1011 $this->options['enable_google_analytics'] = 'no';
1012 }
1013
1014 if($this->options['db_version'] < 9) {
1015 $this->options['pf_algo'] = 'wp';
1016 }
1017
1018 if($this->options['db_version'] < 10) {
1019 $this->options['enable_error_reporting'] = 'yes';
1020 }
1021
1022 if($this->options['db_version'] < 11) {
1023 if (!isset($this->options['custom_css_url'])) {
1024 $this->options['custom_css_url'] = '';
1025 }
1026 }
1027
1028 if($this->options['db_version'] < 12) {
1029 $this->options['images-size'] = $this->options['hide-images'] == '1' ? 'remove-images' : 'full-size';
1030 }
1031
1032 if ($this->options['db_version'] < 13) {
1033 switch ($this->options['button_type']) {
1034 case 'pf-button.gif':
1035 $this->options['button_type'] = 'buttons/printfriendly-button.png';
1036 break;
1037 case 'pf-button-both.gif':
1038 $this->options['button_type'] = 'buttons/printfriendly-pdf-button.png';
1039 break;
1040 case 'pf-button-big.gif':
1041 $this->options['button_type'] = 'buttons/printfriendly-button-lg.png';
1042 break;
1043 case 'pf-button-print-pdf-mail.png':
1044 $this->options['button_type'] = 'buttons/printfriendly-pdf-email-button-notext.png';
1045 break;
1046 case 'button-print-grnw20.png':
1047 $this->options['button_type'] = 'buttons/print-button.png';
1048 break;
1049 case 'button-print-blu20.png':
1050 $this->options['button_type'] = 'buttons/print-button-nobg.png';
1051 break;
1052 case 'button-print-gry20.png':
1053 $this->options['button_type'] = 'buttons/print-button-gray.png';
1054 break;
1055 case 'pf-icon-small.gif':
1056 case 'pf-icon.gif':
1057 case 'text-only':
1058 $this->options['button_type'] = 'custom-image';
1059 $this->options['custom_image'] = 'icons/printfriendly-icon-md.png';
1060 break;
1061 }
1062 }
1063
1064 if ($this->options['db_version'] < 14) {
1065 if ($this->options['button_type'] == 'pf-icon-both.gif') {
1066 $this->options['button_type'] = 'buttons/printfriendly-pdf-button-nobg.png';
1067 }
1068 }
1069
1070 $this->options['db_version'] = $this->db_version;
1071
1072 update_option( $this->option_name, $this->options );
1073 }
1074
1075 /**
1076 * Displays radio button in the admin area
1077 *
1078 * @since 3.0
1079 * @param string $name the name of the radio button to generate.
1080 * @param boolean $br whether or not to add an HTML <br> tag, defaults to true.
1081 */
1082 function radio($name, $br = false){
1083 $var = '<input id="'.$name.'" class="radio" name="'.$this->option_name.'[button_type]" type="radio" value="'.$name.'" '.$this->checked( 'button_type', $name, false ).'/>';
1084 $button = $this->button( $name );
1085 if ( '' != $button )
1086 echo '<label for="'.$name.'">' . $var . $button . '</label>';
1087 else
1088 echo $var;
1089
1090 if ( $br )
1091 echo '<br>';
1092 }
1093
1094 /**
1095 * Displays button image in the admin area
1096 *
1097 * @since 3.0
1098 * @param string $name the name of the button to generate.
1099 */
1100 function button( $name = false ){
1101 if( !$name )
1102 $name = $this->options['button_type'];
1103
1104 $button_css = $this->generic_button_css();
1105 /* esc_html was removerd to support custom html, CSRF prevents from attack by using this field */
1106 $text = $this->options['custom_text'];
1107 $img_path = 'https://cdn.printfriendly.com/';
1108
1109 if ($name == "custom-image") {
1110 if( '' == trim($this->options['custom_image']) )
1111 $return = '';
1112 else
1113 $return = '<img src="'.esc_url($this->options['custom_image']).'" alt="Print Friendly" style="display: inline" />';
1114
1115 $return .= $text;
1116
1117 return $return;
1118 } else {
1119 return '<img style="'.$button_css.'" src="'.$img_path.$name.'" alt="Print Friendly" />';
1120 }
1121 }
1122
1123 /**
1124 *
1125 *
1126 **/
1127
1128 function generic_button_css() {
1129 return "border:none;-webkit-box-shadow:none; box-shadow:none;";
1130 }
1131
1132
1133 /**
1134 * Convenience function to output a value custom button preview elements
1135 *
1136 * @since 3.0.9
1137 */
1138 function custom_button_preview() {
1139 if( '' == trim($this->options['custom_image']) )
1140 $button_preview = '<span id="pf-custom-button-preview"></span>';
1141 else
1142 $button_preview = '<span id="pf-custom-button-preview"><img src="'.esc_url($this->options['custom_image']).'" alt="Print Friendly" /></span>';
1143
1144 $button_preview .= '<span class="printfriendly-text2">'.esc_html($this->options['custom_text']).'</span>';
1145
1146 echo $button_preview;
1147 }
1148
1149 /**
1150 * Convenience function to output a value for an input
1151 *
1152 * @since 3.0
1153 * @param string $val value to check.
1154 */
1155 function val( $val ) {
1156 if ( isset( $this->options[$val] ) )
1157 echo esc_attr( $this->options[$val] );
1158 }
1159
1160 /**
1161 * Like the WordPress checked() function but it doesn't throw notices when the array key isn't set and uses the plugins options array.
1162 *
1163 * @since 3.0
1164 * @param mixed $val value to check.
1165 * @param mixed $check_against value to check against.
1166 * @param boolean $echo whether or not to echo the output.
1167 * @return string checked, when true, empty, when false.
1168 */
1169 function checked( $val, $check_against = true, $echo = true ) {
1170 if ( !isset( $this->options[$val] ) )
1171 return;
1172
1173 if ( $this->options[$val] == $check_against ) {
1174 if ( $echo )
1175 echo ' checked="checked" ';
1176 else
1177 return ' checked="checked" ';
1178 }
1179 }
1180
1181 /**
1182 * Helper for creating checkboxes.
1183 *
1184 * @since 3.1.5
1185 * @param string $name string used for various parts of checkbox
1186 *
1187 */
1188 function create_checkbox($name, $label='', $labelid='' ) {
1189 $label = ( !empty( $label) ? $label : __( ucfirst($name), $this->hook ) );
1190 echo '<label' . ( !empty( $labelid ) ? ' id=' . $labelid : '' ) . '><input type="checkbox" class="show_list" name="' . $this->option_name . '[show_on_' . $name . ']" value="on" ';
1191 $this->checked( 'show_on_' . $name, 'on');
1192 echo ' />' . $label . "</label>\r\n";
1193 }
1194
1195
1196 /**
1197 * Helper that checks if any of the content types is checked to display pf button.
1198 *
1199 * @since 3.1.5
1200 * @return boolean true if none of the content types is checked
1201 *
1202 */
1203 function is_manual() {
1204 try {
1205 return !(isset($this->options['show_on_posts']) ||
1206 isset($this->options['show_on_pages']) ||
1207 isset($this->options['show_on_homepage']) ||
1208 isset($this->options['show_on_categories']) ||
1209 // (isset($this->options['category_ids']) && count($this->options['category_ids']) > 0) ||
1210 isset($this->options['show_on_taxonomies']));
1211 } catch (Exception $e) {
1212 $this->raven_catch($e);
1213 }
1214 }
1215
1216
1217 /**
1218 * Like the WordPress selected() function but it doesn't throw notices when the array key isn't set and uses the plugins options array.
1219 *
1220 * @since 3.0.9
1221 * @param mixed $val value to check.
1222 * @param mixed $check_against value to check against.
1223 * @return string checked, when true, empty, when false.
1224 */
1225 function selected( $val, $check_against = true) {
1226 if ( !isset( $this->options[$val] ) )
1227 return;
1228
1229 return selected ($this->options[$val], $check_against);
1230 }
1231
1232 /**
1233 * For use with page metabox.
1234 *
1235 * @since 3.2.2
1236 */
1237 function get_page_post_type() {
1238 $post_types = get_post_types( array( 'name' => 'page' ), 'object' );
1239 //echo '<pre>'.print_r($post_types,1).'</pre>';
1240 //die;
1241
1242 return $post_types['page'];
1243 }
1244
1245
1246 /**
1247 * Helper that checks if wp versions is above 3.0.
1248 *
1249 * @since 3.2.2
1250 * @return boolean true wp version is above 3.0
1251 *
1252 */
1253 function wp_version_gt30() {
1254 global $wp_version;
1255 return version_compare($wp_version, '3.0', '>=');
1256 }
1257
1258
1259 /**
1260 * Create box for picking individual categories.
1261 *
1262 * @since 3.2.2
1263 */
1264 function create_category_metabox() {
1265 $obj = new stdClass();
1266 $obj->ID = 0;
1267 do_meta_boxes('settings_page_' . $this->hook, 'normal', $obj);
1268 }
1269
1270
1271 /**
1272 * Load metaboxes advanced button display settings.
1273 *
1274 * @since 3.2.2
1275 */
1276 function on_load_printfriendly() {
1277 global $wp_version;
1278 if($this->wp_version_gt30()) {
1279 require_once('includes/meta-boxes.php');
1280 //require_once('includes/nav-menu.php');
1281 wp_enqueue_script('post');
1282
1283 add_meta_box('categorydiv', __('Only display when post is in:', $this->hook), 'post_categories_meta_box', 'settings_page_'. $this->hook, 'normal', 'core');
1284 }
1285 }
1286
1287 function console_log( $data ) {
1288 echo '<script>';
1289 echo 'console.log(' . json_encode( $data ) . ')';
1290 echo '</script>';
1291 }
1292
1293 /**
1294 * Output the config page
1295 *
1296 * @since 3.0
1297 */
1298 function config_page() {
1299
1300
1301 // Since WP 3.2 outputs these errors by default, only display them when we're on versions older than 3.2 that do support the settings errors.
1302 global $wp_version;
1303 if(version_compare($wp_version, '3.2', '<' ) && $this->wp_version_gt30() )
1304 settings_errors();
1305
1306 // Show the content of the options array when debug is enabled
1307 if ( WP_DEBUG ) {
1308 echo "<p>" . __( 'Currently in Debug Mode. Following information is visible in debug mode only:', $this->hook ) . "</p>";
1309 echo '<pre>' . __( 'Options:', $this->hook ) . '<br><br>' . print_r( $this->options, 1 ) . '</pre>';
1310 }
1311 ?>
1312
1313 <style type="text/css">
1314 input[type="radio"], img {
1315 vertical-align: middle;
1316 }
1317 </style>
1318
1319 <div id="pf_settings" class="wrap">
1320
1321 <div class="icon32" id="printfriendly"></div>
1322 <h2><?php _e( 'Print Friendly & PDF Settings', $this->hook ); ?></h2>
1323
1324 <form action="options.php" method="post">
1325 <?php wp_nonce_field( 'pf-options', 'pf-nonce' ); ?>
1326 <?php settings_fields( $this->option_name ); ?>
1327
1328 <h3><?php _e( "Pick Your Button Style", $this->hook ); ?></h3>
1329
1330 <fieldset id="button-style">
1331 <div id="buttongroup1">
1332 <?php $this->radio('buttons/printfriendly-pdf-email-button.png'); ?>
1333 <?php $this->radio('buttons/printfriendly-pdf-email-button-md.png'); ?>
1334 <?php $this->radio('buttons/printfriendly-pdf-email-button-notext.png'); ?>
1335 </div>
1336 <div id="buttongroup2">
1337 <?php $this->radio('buttons/printfriendly-pdf-button.png'); ?>
1338 <?php $this->radio('buttons/printfriendly-pdf-button-nobg.png'); ?>
1339 <?php $this->radio('buttons/printfriendly-pdf-button-nobg-md.png'); ?>
1340 </div>
1341 <div id="buttongroup3">
1342 <?php $this->radio('buttons/printfriendly-button.png'); ?>
1343 <?php $this->radio('buttons/printfriendly-button-nobg.png'); ?>
1344 <?php $this->radio('buttons/printfriendly-button-md.png'); ?>
1345 <?php $this->radio('buttons/printfriendly-button-lg.png'); ?>
1346 </div>
1347 <div id="buttongroup4">
1348 <?php $this->radio('buttons/print-button.png'); ?>
1349 <?php $this->radio('buttons/print-button-nobg.png'); ?>
1350 <?php $this->radio('buttons/print-button-gray.png'); ?>
1351 </div>
1352
1353 <div id="custom" class="clear">
1354 <label for="custom-image">
1355 <?php echo '<input id="custom-image" class="radio" name="'.$this->option_name.'[button_type]" type="radio" value="custom-image" '.$this->checked( 'button_type', 'custom-image', false ).'/>'; ?>
1356 <?php _e( "Custom Button", $this->hook ); ?>
1357 </label>
1358
1359 <div id="custom-img">
1360 <div style="float: left">
1361 <span>PrintFriendly Icon Size</span>
1362 <select id="pf-icon" style="margin: 0">
1363 <option value="icons/printfriendly-icon-sm.png" <?php selected( $this->options['custom_image'], 'https://cdn.printfriendly.com/icons/printfriendly-icon-sm.png'); ?>>Small</option>
1364 <option value="icons/printfriendly-icon-md.png" <?php selected( $this->options['custom_image'], 'https://cdn.printfriendly.com/icons/printfriendly-icon-md.png'); ?>>Medium</option>
1365 <option value="icons/printfriendly-icon-lg.png" <?php selected( $this->options['custom_image'], 'https://cdn.printfriendly.com/icons/printfriendly-icon-lg.png'); ?>>Large</option>
1366 </select>
1367 </div>
1368
1369 <div style="float: left; margin-left: 50px">
1370 <?php _e( "Enter Image URL", $this->hook ); ?><br>
1371 <input id="custom_image" type="text" class="clear regular-text" style="width: 500px" name="<?php echo $this->option_name; ?>[custom_image]" value="<?php $this->val( 'custom_image' ); ?>" />
1372 <div class="description"><?php _e( "Ex: https://www.example.com/<br>Ex: /wp/wp-content/uploads/example.png", $this->hook ); ?>
1373 </div>
1374 </div>
1375 </div>
1376
1377 <div id="pf-custom-button-error"></div>
1378 <div id="custom-txt" >
1379 <div id="txt-enter">
1380 <?php _e( "Text", $this->hook ); ?><br>
1381 <input type="text" size="30" class="clear regular-text" name="<?php echo $this->option_name; ?>[custom_text]" id="custom_text" value="<?php $this->val( 'custom_text' ); ?>">
1382 </div>
1383 <div id="txt-color">
1384 <?php _e( "Text Color", $this->hook ); ?>
1385 <input type="hidden" name="<?php echo $this->option_name; ?>[text_color]" id="text_color" value="<?php $this->val( 'text_color' ); ?>"/><br>
1386 <div id="colorSelector">
1387 <div style="background-color: <?php echo $this->options['text_color']; ?>;"></div>
1388 </div>
1389 </div>
1390 <div id="txt-size">
1391 <?php _e( "Text Size", $this->hook ); ?><br>
1392 <input type="number" id="text_size" min="9" max="25" class="small-text" name="<?php echo $this->option_name; ?>[text_size]" value="<?php $this->val( 'text_size' ); ?>"/>
1393 </div>
1394 </div>
1395 <div id="custom-button-preview">
1396 <?php $this->custom_button_preview(); ?>
1397 </div>
1398 </fieldset>
1399 <br class="clear">
1400
1401 <!--Section 2 Button Positioning-->
1402 <div id="button-positioning">
1403 <h3><?php _e( "Button Positioning", $this->hook ); ?>
1404 <span id="css"><input type="checkbox" name="<?php echo $this->option_name; ?>[enable_css]" value="<?php $this->val('enable_css');?>" <?php $this->checked('enable_css', 'off'); ?> />Do not use CSS for button styles</span>
1405 </h3>
1406 <div id="button-positioning-options">
1407 <div id="alignment">
1408 <label<?php /*for="pf_content_position"*/ ?>>
1409 <select id="pf_content_position" name="<?php echo $this->option_name; ?>[content_position]" >
1410 <option value="left" <?php selected( $this->options['content_position'], 'left' ); ?>><?php _e( "Left Align", $this->hook ); ?></option>
1411 <option value="right" <?php selected( $this->options['content_position'], 'right' ); ?>><?php _e( "Right Align", $this->hook ); ?></option>
1412 <option value="center" <?php selected( $this->options['content_position'], 'center' ); ?>><?php _e( "Center", $this->hook ); ?></option>
1413 <option value="none" <?php selected( $this->options['content_position'], 'none' ); ?>><?php _e( "None", $this->hook ); ?></option>
1414 </select>
1415 </label>
1416 </div>
1417 <div class="content_placement">
1418 <label<?php /* for="pf_content_placement"*/ ?>>
1419 <select id="pf_content_placement" name="<?php echo $this->option_name; ?>[content_placement]" >
1420 <option value="before" <?php selected( $this->options['content_placement'], 'before' ); ?>><?php _e( "Above Content", $this->hook ); ?></option>
1421 <option value="after" <?php selected( $this->options['content_placement'], 'after' ); ?>><?php _e( "Below Content", $this->hook ); ?></option>
1422 </select>
1423 </label>
1424 </div>
1425 <div id="margin">
1426 <label for="pf-margin_left">
1427 <input type="number" name="<?php echo $this->option_name; ?>[margin_left]" id="pf-margin_left" value="<?php $this->val( 'margin_left' ); ?>" maxlength="3"/>
1428 <?php _e( "Margin Left", $this->hook ); ?>
1429 </label>
1430 <label for="pf-margin_right">
1431 <input type="number" name="<?php echo $this->option_name; ?>[margin_right]" id="pf-margin_right" value="<?php $this->val( 'margin_right' ); ?>"/> <?php _e( "Margin Right", $this->hook ); ?>
1432 </label>
1433 <label for="pf-margin_top">
1434 <input type="number" name="<?php echo $this->option_name; ?>[margin_top]" id="pf-margin_top" value="<?php $this->val( 'margin_top' ); ?>" maxlength="3"/> <?php _e( "Margin Top", $this->hook ); ?>
1435 </label>
1436 <label for="pf-margin_bottom">
1437 <input type="number" name="<?php echo $this->option_name; ?>[margin_bottom]" id="pf-margin_bottom" value="<?php $this->val( 'margin_bottom' ); ?>" maxlength="3"/> <?php _e( "Margin Bottom", $this->hook ); ?>
1438 </label>
1439 </div>
1440 </div>
1441 </div>
1442 <br class="clear">
1443
1444 <!--Section 3 Button Placement-->
1445 <div id="button-placement">
1446 <h3><?php _e( "Display button on:", $this->hook ); ?></h3>
1447 <div id="pages">
1448 <?php $this->create_checkbox('posts', __( 'Posts', $this->hook )); ?>
1449 <?php $this->create_checkbox('pages', __( 'Pages', $this->hook )); ?>
1450 <?php $this->create_checkbox('homepage', __( 'Homepage', $this->hook )); ?>
1451 <?php $this->create_checkbox('categories', __( 'Category Pages', $this->hook )); ?>
1452 <?php $this->create_checkbox('taxonomies', __( 'Taxonomy Pages', $this->hook )); ?>
1453 <label for="show_on_template"><input type="checkbox" class="show_template" name="show_on_template" id="show_on_template" /><?php echo _e( 'Add direct to template', $this->hook ); ?></label>
1454 <textarea id="pf-shortcode" class="code" rows="2" cols="40">&lt;?php if(function_exists('pf_show_link')){echo pf_show_link();} ?&gt;</textarea>
1455 <label<?php /* for="pf-shortcode2"*/ ?>><?php _e( "or use shortcode inside your page/article", $this->hook ); ?></label>
1456 <textarea<?php /* id="pf-shortcode2"*/ ?> class="code" rows="2" cols="40">[printfriendly]</textarea>
1457 <?php /* <input type="hidden" name="<? php echo $this->option_name; ?>[category_ids]" id="category_ids" value="<?php echo implode(',', $this->options['category_ids']); ? >" /> */ ?>
1458 </div>
1459 </div>
1460 <?php /*if($this->wp_version_gt30()) { ? >
1461 <div id="pf-categories">
1462 <h4><?php printf( __( '<a %s>Additional filter</a>', $this->hook), ' href="javascript:void(0)" id="toggle-categories"' ); ?></h4>
1463 <div id="pf-categories-metabox">
1464 <?php $this->create_category_metabox(); ?>
1465 </div>
1466 </div>
1467 <? php } */ ?>
1468
1469 <br class="clear">
1470
1471 <!--Section 4 Button Print Options-->
1472 <div id="print-options">
1473 <h3><?php _e( "Print PDF Options", $this->hook ); ?></h3>
1474 <label id="pf-favicon" for="favicon"<?php /*for="pf-logo"*/ ?>>
1475 <?php _e( "Page header", $this->hook ); ?>
1476 <select id="pf-logo" name="<?php echo $this->option_name; ?>[logo]" >
1477 <option value="favicon" <?php selected( $this->options['logo'], 'favicon' ); ?>><?php _e( "My Website Icon", $this->hook ); ?></option>
1478 <option value="upload-an-image" <?php selected( $this->options['logo'], 'upload-an-image' ); ?>><?php _e( "Upload an Image", $this->hook ); ?></option>
1479 </select>
1480 </label>
1481 <?php /* <div class="custom-logo">
1482 <label for="upload-an-image"><?php _e( "Enter url", $this->hook ); ?></label><input id="upload-an-image" type="text" class="regular-text" name="<?php echo $this->option_name; ?>[image_url]" value="<?php $this->val( 'image_url' ); ?>" />
1483 <label for="image-tagline"><?php _e( "Text (optional)", $this->hook ); ?></label><input id="image-tagline" type="text" class="regular-text" name="<?php echo $this->option_name; ?>[tagline]" value="<?php $this->val( 'tagline' ); ?>" />
1484 </div> */ ?>
1485 <div class="custom-logo"><label for="Enter_URL">Enter url</label><input id="upload-an-image" type="text" class="regular-text" name="<?php echo $this->option_name; ?>[image_url]" value="<?php $this->val( 'image_url' ); ?>" /><label for="Text__optional_">Text (optional)</label><input id="image-tagline" type="text" class="regular-text" name="<?php echo $this->option_name; ?>[tagline]" value="<?php $this->val( 'tagline' ); ?>" /></div>
1486 <div id="pf-image-error"></div>
1487 <div id="pf-image-preview"></div>
1488 <label for="click_to_delete">
1489 <?php _e( "Click-to-delete", $this->hook ); ?>
1490 <select name="<?php echo $this->option_name; ?>[click_to_delete]" id="click-to-delete">
1491 <option value="0" <?php selected( $this->options['click_to_delete'], '0' ); ?>><?php _e( "Allow", $this->hook ); ?></option>
1492 <option value="1" <?php selected( $this->options['click_to_delete'], '1' ); ?>><?php _e( "Not Allow", $this->hook ); ?></option>
1493 </select>
1494 </label>
1495 <label for="images-size">
1496 <?php _e( "Images", $this->hook ); ?>
1497 <select name="<?php echo $this->option_name; ?>[images-size]" id="images-size">
1498 <option value="full-size" <?php selected( $this->options['images-size'], 'full-size' ); ?>><?php _e( "Full Size", $this->hook ); ?></option>
1499 <option value="large" <?php selected( $this->options['images-size'], 'large' ); ?>><?php _e( "Large", $this->hook ); ?></option>
1500 <option value="medium" <?php selected( $this->options['images-size'], 'medium' ); ?>><?php _e( "Medium", $this->hook ); ?></option>
1501 <option value="small" <?php selected( $this->options['images-size'], 'small' ); ?>><?php _e( "Small", $this->hook ); ?></option>
1502 <option value="remove-images" <?php selected( $this->options['images-size'], 'remove-images' ); ?>><?php _e( "Remove Images", $this->hook ); ?></option>
1503 </select>
1504 </label>
1505 <label for="image-style">
1506 <?php _e( "Image style", $this->hook ); ?>
1507 <select name="<?php echo $this->option_name; ?>[image-style]" id="image-style">
1508 <option value="right" <?php selected( $this->options['image-style'], 'right' ); ?>><?php _e( "Align Right", $this->hook ); ?></option>
1509 <option value="left" <?php selected( $this->options['image-style'], 'left' ); ?>><?php _e( "Align Left", $this->hook ); ?></option>
1510 <option value="none" <?php selected( $this->options['image-style'], 'none' ); ?>><?php _e( "Align None", $this->hook ); ?></option>
1511 <option value="block" <?php selected( $this->options['image-style'], 'block' ); ?>><?php _e( "Center/Block", $this->hook ); ?></option>
1512 </select>
1513 </label>
1514 <label for="email">
1515 <?php _e( "Email", $this->hook ); ?>
1516 <select name="<?php echo $this->option_name; ?>[email]" id="email">
1517 <option value="0" <?php selected( $this->options['email'], '0' ); ?>><?php _e( "Allow", $this->hook ); ?></option>
1518 <option value="1" <?php selected( $this->options['email'], '1' ); ?>><?php _e( "Not Allow", $this->hook ); ?></option>
1519 </select>
1520 </label>
1521 <label for="pdf">
1522 <span class="alignleft"><?php _e( "PDF", $this->hook ); ?></span>
1523 <select name="<?php echo $this->option_name; ?>[pdf]" id="pdf" class="alignleft clear">
1524 <option value="0" <?php selected( $this->options['pdf'], '0' ); ?>><?php _e( "Allow", $this->hook ); ?></option>
1525 <option value="1" <?php selected( $this->options['pdf'], '1' ); ?>><?php _e( "Not Allow", $this->hook ); ?></option>
1526 </select>
1527 <p class="alignleft">
1528 <h4 class="alignleft notice"><abbr class="required"><?php _e( "Developer Note: ", $this->hook ); ?></abbr><?php _e( "On localhost the images can not be included in the PDF. Once the website is live/public images will be included in the PDF.", $this->hook ); ?></h4>
1529 </p>
1530 </label>
1531 <label for="print" class="clear">
1532 <?php _e( "Print", $this->hook ); ?>
1533 <select name="<?php echo $this->option_name; ?>[print]" id="print">
1534 <option value="0" <?php selected( $this->options['print'], '0' ); ?>><?php _e( "Allow", $this->hook ); ?></option>
1535 <option value="1" <?php selected( $this->options['print'], '1' ); ?>><?php _e( "Not Allow", $this->hook ); ?></option>
1536 </select>
1537 </label>
1538 <label for="custom_css_url">
1539 <?php _e( "Custom css url", $this->hook ); ?>
1540 <input id="custom_css_url" type="text" class="regular-text" name="<?php echo $this->option_name; ?>[custom_css_url]" value="<?php $this->val( 'custom_css_url' ); ?>" />
1541 <span class="description pf-help-link"><a target="_howto" href="https://support.printfriendly.com/customer/portal/articles/895256-custom-css-styles"><?php _e( '?', $this->hook ); ?></a></span>
1542 </label>
1543 </div>
1544
1545 <!--Section 5 WebMaster-->
1546 <h3><?php _e( "Webmaster Settings", $this->hook ); ?></h3>
1547
1548 <label for="password_protected"><?php _e( 'Password Protected Content', $this->hook ); ?>
1549 <select id="password_protected" name="<?php echo $this->option_name; ?>[password_protected]">
1550 <option value="no" <?php selected( $this->options['password_protected'], 'no' ); ?>><?php _e( "No", $this->hook ); ?></option>
1551 <option value="yes" <?php selected( $this->options['password_protected'], 'yes' ); ?>><?php _e( "Yes", $this->hook ); ?></option>
1552 </select>
1553 </label>
1554 <label for="javascript"><?php _e( 'Use JavaScript', $this->hook ); ?><br>
1555 <select id="javascript" name="<?php echo $this->option_name; ?>[javascript]>">
1556 <option value="yes" <?php $this->selected( 'javascript', 'yes' ); ?>> <?php _e( "Yes", $this->hook ); ?></option>
1557 <option value="no" <?php $this->selected( 'javascript', 'no' ); ?>> <?php _e( "No", $this->hook ); ?></option>
1558 </select>
1559 <span class="description javascript no-italics">
1560 <?php _e( "Preview appears on the page in a Lightbox.", $this->hook ); ?>
1561 </span>
1562 <span class="description no-javascript no-italics">
1563 <?php _e( "Preview opens a new browser tab.", $this->hook ); ?>
1564 </span>
1565 </label>
1566 <label for="pf-analytics-tracking"><?php _e( 'Track in Google Analytics', $this->hook ); ?><br>
1567 <select id="pf-analytics-tracking" name="<?php echo $this->option_name; ?>[enable_google_analytics]">
1568 <option value="yes" <?php $this->selected( 'enable_google_analytics', 'yes' ); ?>> <?php _e( "Yes", $this->hook ); ?></option>
1569 <option value="no" <?php $this->selected( 'enable_google_analytics', 'no' ); ?>> <?php _e( "No", $this->hook ); ?></option>
1570 </select>
1571 </label>
1572 <label for="pf-error-reporting"><?php _e( 'Error Reporting', $this->hook ); ?>
1573 <span class="description no-italics" ><?php _e( 'Ensure PrintFriendly is working - Automatically send anonymous alert if PrintFriendly encounters an error.', $this->hook ); ?>
1574 <br>
1575 <select id="pf-error-reporting" name="<?php echo $this->option_name; ?>[enable_error_reporting]">
1576 <option value="yes" <?php $this->selected( 'enable_error_reporting', 'yes' ); ?>> <?php _e( "Yes", $this->hook ); ?></option>
1577 <option value="no" <?php $this->selected( 'enable_error_reporting', 'no' ); ?>> <?php _e( "No", $this->hook ); ?></option>
1578 </select>
1579 </label>
1580 <label for="pf-algo-usage"><?php _e( 'My Page Content Selected By:', $this->hook ); ?> <span class="description no-italics" ><?php _e( 'Change this setting if your content is not showing in the preview.', $this->hook ); ?></span><br>
1581
1582 <?php
1583 if (class_exists('WooCommerce')) {
1584 ?>
1585 <span><strong>Not available for woocommerce</strong></span>
1586 <?php
1587 } else {
1588 ?>
1589 <select id="pf-algo-usage" name="<?php echo $this->option_name; ?>[pf_algo]">
1590 <option value="wp" <?php $this->selected( 'pf_algo', 'wp' ); ?>> <?php _e( 'WP Template', $this->hook ); ?></option>
1591 <option value="pf" <?php $this->selected( 'pf_algo', 'pf' ); ?>> <?php _e( "Content Algorithm", $this->hook ); ?></option>
1592 </select>
1593 <?php
1594 }
1595 ?>
1596
1597 </label>
1598
1599 <p class="submit">
1600 <input type="submit" class="button-primary" value="<?php esc_attr_e( "Save Options", $this->hook ); ?>"/>
1601 <input type="reset" class="button-secondary" value="<?php esc_attr_e( "Cancel", $this->hook ); ?>"/>
1602 </p>
1603 <div id="after-submit">
1604 <p>
1605 <?php _e( sprintf( __( 'If you like <strong>PrintFriendly</strong> please leave us a %s rating. A huge thanks in advance!', 'printfriendly' ), '<a href="https://wordpress.org/support/plugin/printfriendly/reviews?rate=5#new-post" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>' ), $this->hook ); ?>
1606 </p>
1607 <p><?php _e( "Need professional options for your corporate, education, or agency developed website? Check out", $this->hook ); ?> <a href="https://www.printfriendly.com/pro">PrintFriendly Pro</a>.</p>
1608 <p>
1609 <?php _e( "Need help or have suggestions?", $this->hook ); ?> <a href="mailto:support@printfriendly.com?subject=Support%20for%20PrintFriendly%20WordPress%20plugin">support@PrintFriendly.com</a>
1610 </p>
1611 </div>
1612 </form>
1613 <?php
1614 }
1615 }
1616 $printfriendly = new PrintFriendly_WordPress();
1617 }
1618
1619 // Add shortcode for printfriendly button
1620 add_shortcode( 'printfriendly', 'pf_show_link' );
1621
1622 /**
1623 * Convenience function for use in templates.
1624 *
1625 * @since 3.0
1626 * @return string returns a button to be printed.
1627 */
1628 function pf_show_link() {
1629 global $printfriendly;
1630 return $printfriendly->getButton(true);
1631 }
1632