PluginProbe
Taboola / 3.0.0
Taboola v3.0.0
1.0.4 1.0.5 1.0.6 1.0.8 2.0.1 2.0.2 2.1.0 2.1.1 2.2.2 2.2.3 3.0.0 3.0.1 3.0.2 3.1.0 trunk 1.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.2 1.0.3
← All changes | taboola_widget.php +38 -115 3.1.03.0.0 View file →
@@ -2,13 +2,13 @@
2 2 /**
3 3 * Plugin Name: Taboola
4 4 * Plugin URI: https://developers.taboola.com/web-integrations/docs/wordpress-plugin
5 5 * Description: Taboola
6 - * Version: 3.1.0
6 + * Version: 3.0.0
7 7 * Author: Taboola
8 8 */
9 9
10 -define( 'TABOOLA_PLUGIN_VERSION', '3.1.0' ); // track every release
10 +define( 'TABOOLA_PLUGIN_VERSION', '3.0' ); // track every release
11 11 define( 'TABOOLA_MIN_VER', '3.0' ); // bump only when DB changes
12 12 define( 'TABOOLA_DEBUG_MODE', false );
13 13
14 14 define( 'TABOOLA_OPTION_NAME', 'taboola_plugin_version' );
@@ -21,11 +21,9 @@
21 21 define( 'TABOOLA_CONTENT_FORMAT_HTML', 'html' );
22 22
23 23 include_once 'widget.php';
24 24 require_once 'JavaScriptWrapper.php';
25 -if ( ! class_exists( 'simple_html_dom' ) ) {
26 - require_once plugin_dir_path( __FILE__ ) . 'simple_html_dom.php'; // ← NEW
27 -}
25 +require_once plugin_dir_path( __FILE__ ) . 'simple_html_dom.php'; // ← NEW
28 26
29 27 if ( ! class_exists( 'TaboolaWP' ) ) {
30 28 class TaboolaWP {
31 29
@@ -50,9 +48,9 @@
50 48
51 49 /* ─────────────────────────── constructor ─────────────────────────── */
52 50 public function __construct() {
53 51 global $wpdb;
54 - //initialize plugin constant
52 +
55 53 define( 'TaboolaWP', true );
56 54
57 55 $this->_is_widget_on_page = false;
58 56 $this->_is_head_script_loaded = false;
@@ -83,34 +81,11 @@
83 81 if ( is_admin() ) {
84 82 add_action( 'admin_menu', [ $this, 'admin_generate_menu' ] );
85 83 add_filter( 'plugin_action_links',
86 84 [ $this, 'plugin_action_links' ], 10, 2 );
87 - }
88 -
89 -
90 -
91 -
92 - elseif ( $this->settings ) {
85 + } elseif ( $this->settings ) {
93 86 /* loader & flush */
94 87 add_action( 'wp_head', [ $this, 'taboola_header_loader_inject' ] );
95 - if ( ! empty( $this->settings->publisher_id_push ) ) {
96 - add_action( 'wp_head', [ $this, 'taboola_webpush_loader_js' ] );
97 -
98 - $sw = 'sw.js';
99 - $sw_path = ABSPATH . $sw;
100 -
101 - $content = file_exists( $sw_path ) ? file_get_contents( $sw_path ) : '';
102 -
103 - if ( strpos( $content, $this->tpl_sw ) === false ) {
104 - if ( ! is_writable( ABSPATH ) || ( file_exists( $sw_path ) && ! is_writable( $sw_path ) ) ) {
105 - return $this->notice( $this->msg_sw_error );
106 - }
107 - $content = $this->tpl_sw . PHP_EOL . $content;
108 - if ( file_put_contents( $sw_path, $content ) === false ) {
109 - return $this->notice( $this->msg_sw_error );
110 - }
111 - }
112 - }
113 88 add_action( 'wp_footer', [ $this, 'taboola_footer_loader_js' ] );
114 89
115 90 /* content widgets */
116 91 add_filter( 'the_content', [ $this, 'load_taboola_content' ] );
@@ -270,21 +245,15 @@
270 245 return $page_type;
271 246 }
272 247
273 248 // return the head loader script
274 - function taboola_header_loader_js() {
249 + function taboola_header_loader_js() {
250 + $head_string = "";
251 +
252 + // Only adding the loader if a widget is going to be placed on the page.
275 253 if ($this->is_widget_on_page()){
276 -
277 - // New logic to get all mid-article locations
278 - $mid_locations_string = '';
279 - if (!empty($this->settings->mid_widgets)) {
280 - $mid_widgets_array = json_decode($this->settings->mid_widgets, true);
281 - if (is_array($mid_widgets_array)) {
282 - $locations = array_column($mid_widgets_array, 'location_string');
283 - $mid_locations_string = implode(', ', $locations);
284 - }
285 - }
286 -
254 + // PC - since these params will be inserted in 'loaderInjectionScript.js' via search and replace,
255 + // double brackets are used to ensure that each key is a unique string.
287 256 $stringParams = array(
288 257 '{{PUBLISHER_ID}}' => $this->settings->publisher_id,
289 258 '{{PAGE_TYPE}}' => $this->get_page_type(),
290 259 '{{WORDPRESS_VERSION}}' => get_bloginfo('version'),
@@ -289,18 +258,19 @@
289 258 '{{PAGE_TYPE}}' => $this->get_page_type(),
290 259 '{{WORDPRESS_VERSION}}' => get_bloginfo('version'),
291 260 '{{PHP_VERSION}}' => phpversion(),
292 261 '{{PLUGIN_VERSION}}' => TABOOLA_PLUGIN_VERSION,
293 - '{{LOC_MID}}' => $mid_locations_string,
294 - '{{LOC_HOME}}' => $this->settings->home_location_string ?? ''
262 + '{{LOC_MID}}' => $this->settings->mid_location_string,
263 + '{{LOC_HOME}}' => $this->settings->home_location_string
295 264 );
296 265
297 266 $scriptWrapper = new JavaScriptWrapper("loaderInjectionScript.js",$stringParams);
298 - return $scriptWrapper->getScriptMarkupString();
267 + $head_string = $scriptWrapper->getScriptMarkupString();
299 268 }
300 - return "";
269 + return $head_string;
301 270 }
302 271
272 +
303 273 // This function is used for the hook action, injects the header content to the <head> tag.
304 274 function taboola_header_loader_inject(){
305 275 echo $this->taboola_header_loader_js();
306 276 }
@@ -503,31 +473,8 @@
503 473 implode( "\n", $arr[TABOOLA_CONTENT_FORMAT_SCRIPT] ?? [] ) .
504 474 '</script>',
505 475 ]);
506 476 }
507 - /* ------------------------------------------------------------------
508 - * wpautop() hardening for anything injected through the_content.
509 - *
510 - * wpautop() pads block-level tags with blank lines, then splits the
511 - * content on blank lines and wraps each chunk in <p>. Its <script>
512 - * protection only runs after that split, so two things tear an injected
513 - * <script> apart and spill its tail onto the page as reader-visible text:
514 - * 1. a blank line anywhere in the script body, and
515 - * 2. a block-level tag (e.g. <div>) sitting inside a JS string literal.
516 - * Both have to be neutralised; fixing only one still breaks.
517 - * ------------------------------------------------------------------*/
518 -
519 - // Hide markup from wpautop's block-tag scan. \x3C decodes back to "<"
520 - // when the surrounding JS string literal is evaluated.
521 - private function js_escape_markup($markup){
522 - return str_replace('<', '\x3C', (string) $markup);
523 - }
524 -
525 - // Collapse blank lines so wpautop has no paragraph boundary to split on.
526 - private function wpautop_safe_script($script){
527 - return preg_replace('/(\R[ \t]*){2,}/', "\n", (string) $script);
528 - }
529 -
530 477 // Below-article widget
531 478 // Do the actual logic of choosing where to place the taboola content.
532 479 function embed_taboola_content_location($content, $taboola_content){
533 480 $do_default = true;
@@ -535,13 +482,13 @@
535 482 // tag is placed outside of content in order to allow "read more" functionality.
536 483 if ($this->settings->out_of_content_enabled){
537 484
538 485 $scriptWrapper = new JavaScriptWrapper("js_inject.min.js",array(
539 - "{{HTML}}" => $this->js_escape_markup($this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_HTML)),
540 - "{{SCRIPT}}" => $this->js_escape_markup($this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_SCRIPT)))
486 + "{{HTML}}" => $this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_HTML),
487 + "{{SCRIPT}}" => $this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_SCRIPT))
541 488 );
542 489 $scriptWrapper->appendScript("injectWidgetByMarker('tbmarker');");
543 - $content = $content."<span id='tbmarker'></span><script type='text/javascript'>".$this->wpautop_safe_script($scriptWrapper)."</script>";
490 + $content = $content."<span id='tbmarker'></span><script type='text/javascript'>".$scriptWrapper."</script>";
544 491 $do_default = false;
545 492 }
546 493
547 494 // Default for below-article widget - add to the end of the content
@@ -567,13 +514,13 @@
567 514 if ($full_indicator == TABOOLA_JS_INDICATOR){
568 515
569 516 $xpath = substr($location,strlen(TABOOLA_JS_INDICATOR));
570 517 $scriptWrapper = new JavaScriptWrapper("js_inject.min.js",array(
571 - "{{HTML}}" => $this->js_escape_markup($this->format_taboola_content_mid($taboola_content_mid,TABOOLA_CONTENT_FORMAT_HTML)),
572 - "{{SCRIPT}}" => $this->js_escape_markup($this->format_taboola_content_mid($taboola_content_mid,TABOOLA_CONTENT_FORMAT_SCRIPT)))
518 + "{{HTML}}" => $this->format_taboola_content_mid($taboola_content_mid,TABOOLA_CONTENT_FORMAT_HTML),
519 + "{{SCRIPT}}" => $this->format_taboola_content_mid($taboola_content_mid,TABOOLA_CONTENT_FORMAT_SCRIPT))
573 520 );
574 521 $scriptWrapper->appendScript("injectWidgetByXpath('".$xpath."');");
575 - $content = $content."<span id='tbdefault'></span><script type='text/javascript'>".$this->wpautop_safe_script($scriptWrapper)."</script>";
522 + $content = $content."<span id='tbdefault'></span><script type='text/javascript'>".$scriptWrapper."</script>";
576 523
577 524 $do_default = false;
578 525 }
579 526
@@ -579,11 +526,9 @@
579 526
580 527 // server side selector provided (see simple_html_dom selectors http://simplehtmldom.sourceforge.net/manual.htm)
581 528 // basically it's CSS selectors like in jQuery
582 529 } else{
583 - if ( ! class_exists( 'simple_html_dom' ) ) {
584 - require_once('simple_html_dom.php');
585 - }
530 + require_once('simple_html_dom.php');
586 531
587 532 $html_doc = str_get_html($content);
588 533 $target_location = $html_doc->find($location, ($occurrence) - 1);
589 534
@@ -631,13 +576,13 @@
631 576 if ($full_indicator == TABOOLA_JS_INDICATOR){
632 577
633 578 $xpath = substr($location,strlen(TABOOLA_JS_INDICATOR));
634 579 $scriptWrapper = new JavaScriptWrapper("js_inject.min.js",array(
635 - "{{HTML}}" => $this->js_escape_markup($this->format_taboola_content_home($taboola_content_home,TABOOLA_CONTENT_FORMAT_HTML)),
636 - "{{SCRIPT}}" => $this->js_escape_markup($this->format_taboola_content_home($taboola_content_home,TABOOLA_CONTENT_FORMAT_SCRIPT)))
580 + "{{HTML}}" => $this->format_taboola_content_home($taboola_content_home,TABOOLA_CONTENT_FORMAT_HTML),
581 + "{{SCRIPT}}" => $this->format_taboola_content_home($taboola_content_home,TABOOLA_CONTENT_FORMAT_SCRIPT))
637 582 );
638 583 $scriptWrapper->appendScript("injectWidgetByXpath('".$xpath."');");
639 - $content = $content."<span id='tbdefault'></span><script type='text/javascript'>".$this->wpautop_safe_script($scriptWrapper)."</script>";
584 + $content = $content."<span id='tbdefault'></span><script type='text/javascript'>".$scriptWrapper."</script>";
640 585
641 586 $do_default = false;
642 587 }
643 588
@@ -642,12 +587,10 @@
642 587 }
643 588
644 589 // server side selector provided (see simple_html_dom selectors http://simplehtmldom.sourceforge.net/manual.htm)
645 590 // basically it's CSS selectors like in jQuery
646 - } else{
647 - if ( ! class_exists( 'simple_html_dom' ) ) {
591 + } else{
648 592 require_once('simple_html_dom.php');
649 - }
650 593
651 594 $html_doc = str_get_html($content);
652 595 $target_location = $html_doc->find($location,($this->settings->home_location_string_occurrence)-1);
653 596
@@ -674,19 +617,12 @@
674 617 global $current_user;
675 618 add_menu_page(__('Taboola','taboola_widget'), __('Taboola','taboola_widget'), 'manage_options', 'taboola_widget', array(&$this, 'admin_taboola_settings'), $this->plugin_url.'img/taboola_icon.png', 110);
676 619 }
677 620
678 - // Empty numeric inputs must reach MySQL as NULL, not '', or strict mode
679 - // rejects the whole row.
680 - private function nullable_int($value){
681 - return (isset($value) && trim((string) $value) !== '') ? (int) $value : null;
682 - }
683 -
684 621 function admin_taboola_settings(){
685 622 global $wpdb;
686 623 $settings = $wpdb->get_row("select * from ".$wpdb->prefix."_taboola_settings limit 1");
687 624 $taboola_errors = array();
688 - $taboola_save_error = '';
689 625 if($_SERVER['REQUEST_METHOD'] == 'POST'){
690 626
691 627 if(trim(strip_tags($_POST['publisher_id'])) == ''){
692 628 $taboola_errors[] = "Publisher ID";
@@ -768,38 +704,33 @@
768 704 }
769 705 }
770 706 $mid_widgets_json = json_encode($mid_widgets_data);
771 707
772 - /* $wpdb formats every value as %s unless told otherwise, so a PHP
773 - false or an empty string reaches MySQL as ''. Under
774 - STRICT_TRANS_TABLES (the MySQL 8 default) '' is rejected for the
775 - TINYINT/INT columns and the whole write is refused. Send real
776 - integers for the flags and NULL for empty numeric fields. */
777 708 $data = array(
778 709 "publisher_id" => trim($_POST['publisher_id']),
779 710
780 - "web_push_enabled" => isset($_POST['web_push_enabled']) ? 1 : 0,
781 - "publisher_id_push" => $this->nullable_int($_POST['publisher_id_push'] ?? null),
711 + "web_push_enabled" => isset($_POST['web_push_enabled']) ? true : false,
712 + "publisher_id_push" => !empty($_POST['publisher_id_push']) ? trim($_POST['publisher_id_push']) : '',
782 713
783 - "first_bc_enabled" => isset($_POST['first_bc_enabled']) ? 1 : 0,
714 + "first_bc_enabled" => isset($_POST['first_bc_enabled']) ? true : false,
784 715 "first_bc_widget_id" => !empty($_POST['first_bc_widget_id']) ? trim($_POST['first_bc_widget_id']) : '',
785 716 "first_bc_placement" => !empty($_POST['first_bc_placement']) ? trim($_POST['first_bc_placement']) : '',
786 717
787 - "out_of_content_enabled" => isset($_POST['out_of_content_enabled']) ? 1 : 0,
718 + "out_of_content_enabled" => isset($_POST['out_of_content_enabled']) ? true : false,
788 719
789 - "mid_enabled" => isset($_POST['mid_enabled']) ? 1 : 0,
720 + "mid_enabled" => isset($_POST['mid_enabled']) ? true : false,
790 721 "mid_widgets" => $mid_widgets_json,
791 722
792 - "home_enabled" => isset($_POST['home_enabled']) ? 1 : 0,
723 + "home_enabled" => isset($_POST['home_enabled']) ? true : false,
793 724 "home_widget_id" => !empty($_POST['home_widget_id']) ? trim($_POST['home_widget_id']) : '',
794 725 "home_placement" => !empty($_POST['home_placement']) ? trim($_POST['home_placement']) : '',
795 726
796 - "home_location_string_occurrence" => $this->nullable_int($_POST['home_location_string_occurrence'] ?? null),
727 + "home_location_string_occurrence" => !empty($_POST['home_location_string_occurrence']) ? $_POST['home_location_string_occurrence'] : '',
797 728 "home_location_string" => !empty($_POST['home_location_string']) ? trim($_POST['home_location_string']) : '',
798 - "category_enabled" => isset($_POST['category_enabled']) ? 1 : 0,
729 + "category_enabled" => isset($_POST['category_enabled']) ? true : false,
799 730 "category_widget_id" => !empty($_POST['category_widget_id']) ? trim($_POST['category_widget_id']) : '',
800 731 "category_placement" => !empty($_POST['category_placement']) ? trim($_POST['category_placement']) : '',
801 - "category_location_string_occurrence" => $this->nullable_int($_POST['category_location_string_occurrence'] ?? null),
732 + "category_location_string_occurrence" => !empty($_POST['category_location_string_occurrence']) ? $_POST['category_location_string_occurrence'] : '',
802 733 "category_location_string" => !empty($_POST['category_location_string']) ? trim($_POST['category_location_string']) : '',
803 734
804 735 );
805 736
@@ -810,20 +741,12 @@
810 741 }
811 742
812 743 if ($is_valid_nonce) {
813 744 if($settings == NULL){
814 - $saved = $wpdb->insert($this->tbl_taboola_settings, $data);
745 + $wpdb->insert($this->tbl_taboola_settings, $data);
815 746 } else {
816 - $saved = $wpdb->update($this->tbl_taboola_settings, $data, array('id' => $settings->id));
747 + $wpdb->update($this->tbl_taboola_settings, $data, array('id' => $settings->id));
817 748 }
818 -
819 - // update() returns 0 when nothing changed; only false is a failure.
820 - if ($saved === false) {
821 - $taboola_save_error = "The database rejected the write, so your changes were not saved: "
822 - . ($wpdb->last_error !== '' ? $wpdb->last_error : 'unknown database error');
823 - }
824 - } else {
825 - $taboola_save_error = "Security check failed - the settings page had been open too long. Reload it and apply your changes again.";
826 749 }
827 750 }
828 751 $settings = $wpdb->get_row("select * from ".$wpdb->prefix."_taboola_settings limit 1");
829 752 }