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
taboola / taboola_widget.php

taboola_widget.php in Taboola 3.0.0, at taboola_widget.php

952 lines 40.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Taboola
4 * Plugin URI: https://developers.taboola.com/web-integrations/docs/wordpress-plugin
5 * Description: Taboola
6 * Version: 3.0.0
7 * Author: Taboola
8 */
9
10 define( 'TABOOLA_PLUGIN_VERSION', '3.0' ); // track every release
11 define( 'TABOOLA_MIN_VER', '3.0' ); // bump only when DB changes
12 define( 'TABOOLA_DEBUG_MODE', false );
13
14 define( 'TABOOLA_OPTION_NAME', 'taboola_plugin_version' );
15
16 define( 'TABOOLA_XPATH_MARKER', '/' );
17 define( 'TABOOLA_JS_INDICATOR', '{JS}' );
18 define( 'TABOOLA_JS_MARKER', '{' );
19 define( 'TABOOLA_CONTENT_FORMAT_STRING', 'string' );
20 define( 'TABOOLA_CONTENT_FORMAT_SCRIPT', 'script' );
21 define( 'TABOOLA_CONTENT_FORMAT_HTML', 'html' );
22
23 include_once 'widget.php';
24 require_once 'JavaScriptWrapper.php';
25 require_once plugin_dir_path( __FILE__ ) . 'simple_html_dom.php'; // ← NEW
26
27 if ( ! class_exists( 'TaboolaWP' ) ) {
28 class TaboolaWP {
29
30 /* ─────────────────────────── properties ─────────────────────────── */
31 public $data = [];
32 public $_is_widget_on_page;
33 public $_is_head_script_loaded = false;
34
35 private $tpl_sw = 'importScripts("https://cdn.taboola.com/webpush/tsw.js");';
36 private $msg_sw_error = <<<SWE
37 <p>The file <code>sw.js</code> in the WP root is not writable.
38 Please change its permissions or paste the code below manually:</p>
39 <pre><code>{{SW}}</code></pre>
40 <p>Also make sure it's reachable at <code>{{DOMAIN}}/sw.js</code></p>
41 SWE;
42
43 public $plugin_name;
44 public $plugin_directory;
45 public $plugin_url;
46 public $settings;
47 public $tbl_taboola_settings;
48
49 /* ─────────────────────────── constructor ─────────────────────────── */
50 public function __construct() {
51 global $wpdb;
52
53 define( 'TaboolaWP', true );
54
55 $this->_is_widget_on_page = false;
56 $this->_is_head_script_loaded = false;
57
58 $this->plugin_name = plugin_basename( __FILE__ );
59 $this->plugin_directory = plugin_dir_path( __FILE__ );
60 $this->plugin_url = trailingslashit(
61 WP_PLUGIN_URL . '/' . dirname( plugin_basename( __FILE__ ) )
62 );
63 $this->tbl_taboola_settings = $wpdb->prefix . '_taboola_settings';
64 $this->settings = $wpdb->get_row(
65 "SELECT * FROM {$this->tbl_taboola_settings} LIMIT 1"
66 );
67
68 /* activation / upgrade */
69 register_activation_hook( $this->plugin_name, [ $this, 'update_db' ] );
70 add_action( 'admin_init', [ $this, 'update_db' ] );
71
72 /* widgets */
73 if ( $this->settings && ! empty( $this->settings->publisher_id ) ) {
74 add_action(
75 'widgets_init',
76 static fn() => register_widget( 'WP_Widget_Taboola' )
77 );
78 }
79
80 /* admin vs front-end hooks */
81 if ( is_admin() ) {
82 add_action( 'admin_menu', [ $this, 'admin_generate_menu' ] );
83 add_filter( 'plugin_action_links',
84 [ $this, 'plugin_action_links' ], 10, 2 );
85 } elseif ( $this->settings ) {
86 /* loader & flush */
87 add_action( 'wp_head', [ $this, 'taboola_header_loader_inject' ] );
88 add_action( 'wp_footer', [ $this, 'taboola_footer_loader_js' ] );
89
90 /* content widgets */
91 add_filter( 'the_content', [ $this, 'load_taboola_content' ] );
92 add_filter( 'the_content', [ $this, 'load_taboola_content_mid' ] );
93
94 /* full-page buffer – home & category */
95 add_action( 'template_redirect', [ $this, 'tb_home_buffer_start' ], 0 );
96 add_action( 'shutdown', [ $this, 'tb_home_buffer_flush' ], PHP_INT_MAX );
97
98 add_action( 'template_redirect', [ $this, 'tb_cat_buffer_start' ], 0 );
99 add_action( 'shutdown', [ $this, 'tb_cat_buffer_flush' ], PHP_INT_MAX );
100 }
101 } // __construct
102
103
104 /* ======================================================================
105 CATEGORY ▸ should we show the widget?
106 ====================================================================== */
107 private function should_show_content_widget_category(): bool {
108 return (
109 trim( $this->settings->publisher_id ) !== '' &&
110 ( is_category() || is_archive() || is_search() ) &&
111 $this->settings->category_enabled &&
112 trim( $this->settings->category_widget_id ) !== ''
113 );
114 }
115
116 /* ----------------------------------------------------------------------
117 HOMEPAGE ▸ full-page buffer
118 -------------------------------------------------------------------- */
119 public function tb_home_buffer_start() {
120 if ( $this->should_show_content_widget_home() ) {
121 ob_start( [ $this, 'tb_home_buffer_inject' ] );
122 }
123 }
124 public function tb_home_buffer_inject( $html ) {
125 return $this->load_taboola_content_home( $html );
126 }
127
128 /* ----------------------------------------------------------------------
129 CATEGORY ▸ buffer hooks
130 -------------------------------------------------------------------- */
131 public function tb_cat_buffer_start() {
132 if ( $this->should_show_content_widget_category() ) {
133 ob_start( [ $this, 'tb_cat_buffer_inject' ] );
134 }
135 }
136 public function tb_cat_buffer_inject( $html ) {
137 return $this->load_taboola_content_category( $html );
138 }
139 public function tb_cat_buffer_flush() {
140 if ( ob_get_length() ) {
141 echo ob_get_clean();
142 }
143 }
144
145 /* ----------------------------------------------------------------------
146 CATEGORY ▸ choose where to inject
147 -------------------------------------------------------------------- */
148 private function embed_taboola_content_location_category(
149 string $html,
150 array $taboola_content,
151 string $selector ) : string {
152
153 $formatted = $this->format_taboola_content_category( $taboola_content );
154
155 /* A. no selector → bottom of page */
156 if ( $selector === '' ) {
157 return str_ireplace( '</body>', $formatted . '</body>', $html );
158 }
159
160 /* B. selector given → try server-side injection */
161 $doc = str_get_html( $html );
162 if ( ! $doc ) {
163 // parser failed → graceful fallback
164 return str_ireplace( '</body>', $formatted . '</body>', $html );
165 }
166
167 $occurrence = max( 0, $this->settings->category_location_string_occurrence - 1 );
168 $target = $doc->find( $selector, $occurrence );
169
170 if ( $target ) { // selector found
171 $target->outertext .= $formatted;
172 return (string) $doc; // done – no duplicate
173 }
174
175 /* C. selector not found → bottom of page */
176 return str_ireplace( '</body>', $formatted . '</body>', $html );
177 }
178
179 /* ------------------------------------------------------------------ */
180 public function tb_home_buffer_flush() {
181 if ( ob_get_length() ) {
182 echo ob_get_clean();
183 }
184 }
185
186
187
188
189 function plugin_action_links($links, $file) {
190 static $this_plugin;
191
192 if (!$this_plugin) {
193 $this_plugin = plugin_basename(__FILE__);
194 }
195
196 if ($file == $this_plugin) {
197 $settings_link = '<a href="' . get_bloginfo('wpurl') . '/wp-admin/options-general.php?page=taboola_widget">Settings</a>';
198 array_unshift($links, $settings_link);
199 }
200
201 return $links;
202 }
203
204 private function should_show_content_widget(){
205 $retVal = ((trim($this->settings->publisher_id) != '') && is_single() && $this->settings->first_bc_enabled && trim($this->settings->first_bc_widget_id) != '');
206 return $retVal;
207 }
208
209 private function should_show_content_widget_mid(){
210 // PC - only if v2 was installed:
211 if (!$this->is_db_updated_for_min_ver("2.0.0"))
212 return false;
213 $retVal1 = ((trim($this->settings->publisher_id) != '') && is_single() && !empty($this->settings->mid_enabled));
214 return $retVal1;
215 }
216
217 private function should_show_content_widget_home(){
218 // PC - only if v2 was installed:
219
220 //error_log( print_r( $this->settings, true ) ); // TEMP line
221
222 if (!$this->is_db_updated_for_min_ver("2.0.0"))
223 return false;
224 $retVal2 = ((trim($this->settings->publisher_id) != '') && (is_front_page() || is_home()) && $this->settings->home_enabled && trim($this->settings->home_widget_id) != '');
225 return $retVal2;
226 }
227
228 private function should_show_sidebar_widget(){
229 $retVal = ((trim($this->settings->publisher_id) != '') && is_active_widget( false, false, TABOOLA_WIDGET_BASE_ID, true ));
230 return $retVal;
231 }
232
233 // Determine if a taboola widget should be added somewhere on the current page (content or sidebar)
234 function is_widget_on_page(){
235 return $this->should_show_content_widget() || $this->should_show_content_widget_mid() || $this->should_show_content_widget_home() || $this->should_show_sidebar_widget() || $this->should_show_content_widget_category() ;
236 }
237
238 function get_page_type(){
239 $page_type='article';
240 if (is_front_page()){
241 $page_type='home';
242 }else if (is_category() || is_archive() || is_search()){
243 $page_type='category';
244 }
245 return $page_type;
246 }
247
248 // return the head loader script
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.
253 if ($this->is_widget_on_page()){
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.
256 $stringParams = array(
257 '{{PUBLISHER_ID}}' => $this->settings->publisher_id,
258 '{{PAGE_TYPE}}' => $this->get_page_type(),
259 '{{WORDPRESS_VERSION}}' => get_bloginfo('version'),
260 '{{PHP_VERSION}}' => phpversion(),
261 '{{PLUGIN_VERSION}}' => TABOOLA_PLUGIN_VERSION,
262 '{{LOC_MID}}' => $this->settings->mid_location_string,
263 '{{LOC_HOME}}' => $this->settings->home_location_string
264 );
265
266 $scriptWrapper = new JavaScriptWrapper("loaderInjectionScript.js",$stringParams);
267 $head_string = $scriptWrapper->getScriptMarkupString();
268 }
269 return $head_string;
270 }
271
272
273 // This function is used for the hook action, injects the header content to the <head> tag.
274 function taboola_header_loader_inject(){
275 echo $this->taboola_header_loader_js();
276 }
277
278 // adding webpush loader
279 function taboola_webpush_loader_js() {
280 if(is_single() || is_home() || is_category() || is_front_page()){
281 $stringParamsWeb = array(
282 '{{PUBLISHER_ID}}' => $this->settings->publisher_id_push
283 );
284 $webpushInjectionScript = new JavaScriptWrapper("webPush.js",$stringParamsWeb);
285 echo $webpushInjectionScript;
286 }
287 }
288
289 function taboola_footer_loader_js() {
290
291 // Only adding flush script if a widget is going to be placed on the page.
292 if ($this->is_widget_on_page()){
293 $flushInjectionScript = new JavaScriptWrapper('flushInjectionScript.js',array());
294 echo $flushInjectionScript->getScriptMarkupString();
295 }
296 }
297
298 // Below-article widget
299 function load_taboola_content($content)
300 {
301 $taboola_content = array();
302 if ($this->should_show_content_widget()){
303
304 $firstWidgetParams = array(
305 '{{WIDGET_ID}}' => $this->settings->first_bc_widget_id,
306 '{{CONTAINER}}' => 'taboola-below-article-thumbnails',
307 // PC - If v2 was not installed, then use v1 logic
308 '{{PLACEMENT}}' => (!empty($this->settings->first_bc_placement)) ? $this->settings->first_bc_placement : 'below-article' // In case v1 upgrade has not run yet
309 );
310
311 $firstWidgetScript = new JavaScriptWrapper("widgetInjectionScript.js",$firstWidgetParams);
312 $taboola_content[TABOOLA_CONTENT_FORMAT_HTML][] = "<div id='taboola-below-article-thumbnails'></div>";
313 $taboola_content[TABOOLA_CONTENT_FORMAT_SCRIPT][] = $firstWidgetScript;
314
315 $content = $this->embed_taboola_content_location($content,$taboola_content);
316 }
317
318 return $content;
319 }
320
321 // Mid-article-widget
322 function load_taboola_content_mid($content) {
323 if ($this->should_show_content_widget_mid()){
324 $mid_widgets = json_decode($this->settings->mid_widgets ?? '[]');
325
326 if (is_array($mid_widgets) && !empty($mid_widgets)) {
327 foreach ($mid_widgets as $index => $widget) {
328 $container_id = 'taboola-mid-article-thumbnails-' . $index;
329
330 $widgetParams = array(
331 '{{WIDGET_ID}}' => $widget->widget_id,
332 '{{CONTAINER}}' => $container_id,
333 '{{PLACEMENT}}' => $widget->placement
334 );
335
336 $widgetScript = new JavaScriptWrapper("widgetInjectionScript.js", $widgetParams);
337 $taboola_content_mid = array(
338 TABOOLA_CONTENT_FORMAT_HTML => array("<div id='{$container_id}'></div>"),
339 TABOOLA_CONTENT_FORMAT_SCRIPT => array($widgetScript),
340 );
341
342 $content = $this->embed_taboola_content_location_mid(
343 $content,
344 $taboola_content_mid,
345 $widget->location_string,
346 $widget->occurrence
347 );
348 }
349 }
350 }
351 return $content;
352 }
353
354 // Homepage widget
355 function load_taboola_content_home($content)
356 {
357 //error_log( 'TB-DEBUG ② entered load_taboola_content_home' );
358 $taboola_content_home = array();
359 if ($this->should_show_content_widget_home()){
360
361 $homeWidgetParams = array('{{WIDGET_ID}}' => $this->settings->home_widget_id,
362 '{{CONTAINER}}' => 'taboola-homepage-thumbnails',
363 '{{PLACEMENT}}' => $this->settings->home_placement);
364
365 $homeWidgetScript = new JavaScriptWrapper("widgetInjectionScript.js",$homeWidgetParams);
366 $taboola_content_home[TABOOLA_CONTENT_FORMAT_HTML][] = "<div id='taboola-homepage-thumbnails'></div>";
367 $taboola_content_home[TABOOLA_CONTENT_FORMAT_SCRIPT][] = $homeWidgetScript;
368
369 $content = $this->embed_taboola_content_location_home($content,$taboola_content_home,trim($this->settings->home_location_string));
370 }
371 return $content;
372
373 }
374 /* ------------------------------------------------------------------
375 * CATEGORY ▸ build widget & inject
376 * ------------------------------------------------------------------*/
377 public function load_taboola_content_category( $content ) {
378
379 // 1) Build the DIV that Taboola will fill
380 $taboola[TABOOLA_CONTENT_FORMAT_HTML][] =
381 "<div id='taboola-category-thumbnails'></div>";
382
383 // 2) Build the JS that loads the feed (reuse the wrapper)
384 $taboola[TABOOLA_CONTENT_FORMAT_SCRIPT][] =
385 new JavaScriptWrapper( 'widgetInjectionScript.js', [
386 '{{WIDGET_ID}}' => $this->settings->category_widget_id,
387 '{{CONTAINER}}' => 'taboola-category-thumbnails',
388 '{{PLACEMENT}}' => $this->settings->category_placement,
389 ]);
390
391 // 3) Decide where to insert (selector or end of <body>)
392 return $this->embed_taboola_content_location_category(
393 $content,
394 $taboola,
395 trim( $this->settings->category_location_string )
396 );
397 }
398
399 // Below-article widget
400
401 // Extract the taboola content in the required format:
402 // String - for injecting on the servr side
403 // Script or HTML - for injecting on the client side
404 function format_taboola_content($taboola_content,$format){
405 $ret_val = null;
406
407 switch($format){
408 case TABOOLA_CONTENT_FORMAT_STRING:
409 $result_string = join("",$taboola_content[TABOOLA_CONTENT_FORMAT_HTML]).
410 "<script type='text/javascript'>".join("\n",$taboola_content[TABOOLA_CONTENT_FORMAT_SCRIPT])."</script>";
411 $ret_val = $result_string;
412 break;
413
414 // script or html
415 default:
416 $ret_val = str_replace("\n","",join("",$taboola_content[$format]));
417 break;
418 }
419
420 return $ret_val;
421 }
422
423
424 // Mid-article widget
425 function format_taboola_content_mid($taboola_content_mid,$format){
426 $ret_val = null;
427
428 switch($format){
429 case TABOOLA_CONTENT_FORMAT_STRING:
430 $result_string = join("",$taboola_content_mid[TABOOLA_CONTENT_FORMAT_HTML]).
431 "<script type='text/javascript'>".join("\n",$taboola_content_mid[TABOOLA_CONTENT_FORMAT_SCRIPT])."</script>";
432 $ret_val = $result_string;
433 break;
434
435 // script or html
436 default:
437 $ret_val = str_replace("\n","",join("",$taboola_content_mid[$format]));
438 break;
439 }
440
441 return $ret_val;
442 }
443
444
445 // Homepage widget
446 function format_taboola_content_home($taboola_content_home,$format){
447
448 $ret_val = null;
449
450 switch($format){
451 case TABOOLA_CONTENT_FORMAT_STRING:
452 $result_string = join("",$taboola_content_home[TABOOLA_CONTENT_FORMAT_HTML]).
453 "<script type='text/javascript'>".join("\n",$taboola_content_home[TABOOLA_CONTENT_FORMAT_SCRIPT])."</script>";
454 $ret_val = $result_string;
455 break;
456
457 // script or html
458 default:
459 $ret_val = str_replace("\n","",join("",$taboola_content_home[$format]));
460 break;
461 }
462
463 return $ret_val;
464
465 }
466
467
468 // ► CATEGORY formatter ◄
469 private function format_taboola_content_category( $arr ) {
470 return implode( "\n", [
471 implode( "\n", $arr[TABOOLA_CONTENT_FORMAT_HTML] ?? [] ),
472 '<script type="text/javascript">' .
473 implode( "\n", $arr[TABOOLA_CONTENT_FORMAT_SCRIPT] ?? [] ) .
474 '</script>',
475 ]);
476 }
477 // Below-article widget
478 // Do the actual logic of choosing where to place the taboola content.
479 function embed_taboola_content_location($content, $taboola_content){
480 $do_default = true;
481
482 // tag is placed outside of content in order to allow "read more" functionality.
483 if ($this->settings->out_of_content_enabled){
484
485 $scriptWrapper = new JavaScriptWrapper("js_inject.min.js",array(
486 "{{HTML}}" => $this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_HTML),
487 "{{SCRIPT}}" => $this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_SCRIPT))
488 );
489 $scriptWrapper->appendScript("injectWidgetByMarker('tbmarker');");
490 $content = $content."<span id='tbmarker'></span><script type='text/javascript'>".$scriptWrapper."</script>";
491 $do_default = false;
492 }
493
494 // Default for below-article widget - add to the end of the content
495 if ($do_default){
496 $content = $content.$this->format_taboola_content($taboola_content,TABOOLA_CONTENT_FORMAT_STRING);
497 }
498
499 return $content;
500 }
501
502 // Mid-article widget
503 // Do the actual logic of choosing where to place the taboola content based on the "location" attribute
504 function embed_taboola_content_location_mid($content, $taboola_content_mid, $location, $occurrence = 1){
505 $do_default = true;
506
507 if (isset($location) && $location != ''){
508 $first_char = substr($location,0,1);
509
510 // DIV/XPATH provided for JS handling
511 if ($first_char == TABOOLA_JS_MARKER){
512 $full_indicator = substr($location,0,strlen(TABOOLA_JS_INDICATOR));
513
514 if ($full_indicator == TABOOLA_JS_INDICATOR){
515
516 $xpath = substr($location,strlen(TABOOLA_JS_INDICATOR));
517 $scriptWrapper = new JavaScriptWrapper("js_inject.min.js",array(
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))
520 );
521 $scriptWrapper->appendScript("injectWidgetByXpath('".$xpath."');");
522 $content = $content."<span id='tbdefault'></span><script type='text/javascript'>".$scriptWrapper."</script>";
523
524 $do_default = false;
525 }
526
527 // server side selector provided (see simple_html_dom selectors http://simplehtmldom.sourceforge.net/manual.htm)
528 // basically it's CSS selectors like in jQuery
529 } else{
530 require_once('simple_html_dom.php');
531
532 $html_doc = str_get_html($content);
533 $target_location = $html_doc->find($location, ($occurrence) - 1);
534
535 // if the location was found within the html content
536 if (isset($target_location) && is_object($target_location)){
537
538 // adding taboola content AFTER the target location
539 $target_location->outertext = $target_location->outertext.$this->format_taboola_content_mid($taboola_content_mid,TABOOLA_CONTENT_FORMAT_STRING);
540 $content = $html_doc;
541 $do_default = false;
542 }
543 }
544 }
545
546 return $content;
547 }
548
549 // Homepage widget
550 // Do the actual logic of choosing where to place the taboola content based on the "location" attribute
551 function embed_taboola_content_location_home($content, $taboola_content_home, $location){
552
553
554 // error_log( 'TB-DEBUG ③ raw selector string: [' . $location . ']' );
555
556 // load parser
557 //require_once plugin_dir_path( __FILE__ ) . 'simple_html_dom.php';
558 // $html_doc = str_get_html( $content );
559
560 // occurrence: settings is 1-based, find() wants 0-based
561 // $occurrence = max( 1, intval( $this->settings->home_location_string_occurrence ) );
562 // $node = $html_doc->find( $location, $occurrence - 1 );
563 // $found = is_object( $node ) ? 1 : 0;
564
565 // error_log( "TB-DEBUG ③ found {$found} matching node(s) for selector [{$location}]" );
566 // ────────────────────────────
567 $do_default = true;
568
569 if (isset($location) && $location != ''){
570 $first_char = substr($location,0,1);
571
572 // DIV/XPATH provided for JS handling
573 if ($first_char == TABOOLA_JS_MARKER){
574 $full_indicator = substr($location,0,strlen(TABOOLA_JS_INDICATOR));
575
576 if ($full_indicator == TABOOLA_JS_INDICATOR){
577
578 $xpath = substr($location,strlen(TABOOLA_JS_INDICATOR));
579 $scriptWrapper = new JavaScriptWrapper("js_inject.min.js",array(
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))
582 );
583 $scriptWrapper->appendScript("injectWidgetByXpath('".$xpath."');");
584 $content = $content."<span id='tbdefault'></span><script type='text/javascript'>".$scriptWrapper."</script>";
585
586 $do_default = false;
587 }
588
589 // server side selector provided (see simple_html_dom selectors http://simplehtmldom.sourceforge.net/manual.htm)
590 // basically it's CSS selectors like in jQuery
591 } else{
592 require_once('simple_html_dom.php');
593
594 $html_doc = str_get_html($content);
595 $target_location = $html_doc->find($location,($this->settings->home_location_string_occurrence)-1);
596
597 // if the location was found within the html content
598 if (isset($target_location) && is_object($target_location)){
599
600 // adding taboola content AFTER the target location
601 $target_location->outertext = $target_location->outertext.$this->format_taboola_content_home($taboola_content_home,TABOOLA_CONTENT_FORMAT_STRING);
602 $content = $html_doc;
603 $do_default = false;
604 }
605 }
606 }
607 // Default for below-article widget - add to the end of the content
608 if ($do_default){
609 $content = $content.$this->format_taboola_content_home($taboola_content_home,TABOOLA_CONTENT_FORMAT_STRING);
610 }
611 return $content;
612
613
614 }
615
616 function admin_generate_menu(){
617 global $current_user;
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);
619 }
620
621 function admin_taboola_settings(){
622 global $wpdb;
623 $settings = $wpdb->get_row("select * from ".$wpdb->prefix."_taboola_settings limit 1");
624 $taboola_errors = array();
625 if($_SERVER['REQUEST_METHOD'] == 'POST'){
626
627 if(trim(strip_tags($_POST['publisher_id'])) == ''){
628 $taboola_errors[] = "Publisher ID";
629 }
630
631 if(isset($_POST['web_push_enabled'])) {
632 if (trim(strip_tags($_POST['publisher_id_push'])) == '') {
633 $taboola_errors[] = "Publisher Push ID";
634 }
635 }
636
637 if(isset($_POST['first_bc_enabled'])) {
638 if (trim(strip_tags($_POST['first_bc_widget_id'])) == '') {
639 $taboola_errors[] = "Below-article > Widget ID";
640 }
641 if (trim(strip_tags($_POST['first_bc_placement'])) == '') {
642 $taboola_errors[] = "Below-article > Placement Name";
643 }
644 }
645
646 if(isset($_POST['mid_enabled'])) {
647 if(isset($_POST['mid_widget_id']) && is_array($_POST['mid_widget_id'])) {
648 foreach ($_POST['mid_widget_id'] as $index => $widget_id) {
649 if(trim($widget_id) == '') {
650 $taboola_errors[] = "Mid-article Widget #".($index + 1)." > Widget ID";
651 }
652 if(trim($_POST['mid_placement'][$index]) == '') {
653 $taboola_errors[] = "Mid-article Widget #".($index + 1)." > Placement Name";
654 }
655 }
656 }
657 }
658
659 if(isset($_POST['home_enabled'])) {
660 if (trim(strip_tags($_POST['home_widget_id'])) == '') {
661 $taboola_errors[] = "Homepage > Widget ID";
662 }
663 if (trim(strip_tags($_POST['home_placement'])) == '') {
664 $taboola_errors[] = "Homepage > Placement Name";
665 }
666
667 if (trim(strip_tags($_POST['home_location_string'])) == '') {
668 $taboola_errors[] = "Homepage > CSS selector";
669 }
670 else {
671 if (!empty($_POST['home_location_string']) && !$this->is_home_location_string_occurrence_valid($_POST['home_location_string_occurrence'])) {
672 $taboola_errors[] = "Homepage > Occurance (must be >= 1)";
673 }
674 }
675 }
676 if ( isset($_POST['category_enabled']) ) {
677 if ( trim(strip_tags($_POST['category_widget_id'])) == '' )
678 $taboola_errors[] = "Category > Widget ID";
679 if ( trim(strip_tags($_POST['category_placement'])) == '' )
680 $taboola_errors[] = "Category > Placement Name";
681 }
682
683 if(count($taboola_errors) == 0){
684
685 $mid_widgets_data = array();
686 if (isset($_POST['mid_widget_id']) && is_array($_POST['mid_widget_id'])) {
687 foreach ($_POST['mid_widget_id'] as $index => $widget_id) {
688 if (!empty(trim($widget_id))) {
689
690 $location_string = 'p';
691 if (isset($_POST['mid_paragraph_ui_mode'][$index]) && $_POST['mid_paragraph_ui_mode'][$index] === 'Other') {
692 if (isset($_POST['mid_location_string'][$index])) {
693 $location_string = sanitize_text_field($_POST['mid_location_string'][$index]);
694 }
695 }
696
697 $mid_widgets_data[] = array(
698 'widget_id' => sanitize_text_field($widget_id),
699 'placement' => sanitize_text_field($_POST['mid_placement'][$index]),
700 'location_string' => $location_string,
701 'occurrence' => intval($_POST['mid_location_string_occurrence'][$index]),
702 );
703 }
704 }
705 }
706 $mid_widgets_json = json_encode($mid_widgets_data);
707
708 $data = array(
709 "publisher_id" => trim($_POST['publisher_id']),
710
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']) : '',
713
714 "first_bc_enabled" => isset($_POST['first_bc_enabled']) ? true : false,
715 "first_bc_widget_id" => !empty($_POST['first_bc_widget_id']) ? trim($_POST['first_bc_widget_id']) : '',
716 "first_bc_placement" => !empty($_POST['first_bc_placement']) ? trim($_POST['first_bc_placement']) : '',
717
718 "out_of_content_enabled" => isset($_POST['out_of_content_enabled']) ? true : false,
719
720 "mid_enabled" => isset($_POST['mid_enabled']) ? true : false,
721 "mid_widgets" => $mid_widgets_json,
722
723 "home_enabled" => isset($_POST['home_enabled']) ? true : false,
724 "home_widget_id" => !empty($_POST['home_widget_id']) ? trim($_POST['home_widget_id']) : '',
725 "home_placement" => !empty($_POST['home_placement']) ? trim($_POST['home_placement']) : '',
726
727 "home_location_string_occurrence" => !empty($_POST['home_location_string_occurrence']) ? $_POST['home_location_string_occurrence'] : '',
728 "home_location_string" => !empty($_POST['home_location_string']) ? trim($_POST['home_location_string']) : '',
729 "category_enabled" => isset($_POST['category_enabled']) ? true : false,
730 "category_widget_id" => !empty($_POST['category_widget_id']) ? trim($_POST['category_widget_id']) : '',
731 "category_placement" => !empty($_POST['category_placement']) ? trim($_POST['category_placement']) : '',
732 "category_location_string_occurrence" => !empty($_POST['category_location_string_occurrence']) ? $_POST['category_location_string_occurrence'] : '',
733 "category_location_string" => !empty($_POST['category_location_string']) ? trim($_POST['category_location_string']) : '',
734
735 );
736
737 $is_valid_nonce = false;
738
739 if (isset( $_POST['my_plugin_nonce']) && wp_verify_nonce( $_POST['my_plugin_nonce'], 'my_plugin_update_field_action' ) ) {
740 $is_valid_nonce = true;
741 }
742
743 if ($is_valid_nonce) {
744 if($settings == NULL){
745 $wpdb->insert($this->tbl_taboola_settings, $data);
746 } else {
747 $wpdb->update($this->tbl_taboola_settings, $data, array('id' => $settings->id));
748 }
749 }
750 }
751 $settings = $wpdb->get_row("select * from ".$wpdb->prefix."_taboola_settings limit 1");
752 }
753 include_once('settings.php');
754 }
755
756 function is_mid_location_string_valid($mid_location_string){
757 // TODO:: validate the location string
758 return true;
759 }
760
761 function is_mid_location_string_occurrence_valid($mid_location_string_occurrence){
762
763 if ((int)$mid_location_string_occurrence >= 1) {
764 return true;
765 }
766 return false;
767 }
768
769 function is_home_location_string_valid($home_location_string){
770 // TODO:: validate the location string
771 return true;
772 }
773
774 function is_home_location_string_occurrence_valid($home_location_string_occurrence){
775
776 if ((int)$home_location_string_occurrence >= 1) {
777 return true;
778 }
779 return false;
780 }
781
782 function columnExists($column_name) {
783 global $wpdb;
784 $table_name = $wpdb->prefix . "_taboola_settings";
785 tb_write_log("table name : " . $table_name);
786 tb_write_log("column name : " . $column_name);
787
788 $column_exists = $wpdb->get_var("SHOW COLUMNS FROM $table_name LIKE '$column_name'") !== null;
789
790 if ($column_exists) {
791 tb_write_log("Yes - column " . $column_name . " DOES exist!"); //PC
792 return true;
793 } else {
794 tb_write_log("No - column " . $column_name . " does NOT exist!"); //PC
795 return false;
796 }
797 }
798
799 function is_upgrade_from_v1() {
800
801 if($this->columnExists("first_bc_widget_id") && !$this->columnExists("first_bc_placement")){
802 tb_write_log("This IS a v1 upgrade!"); //PC
803 return true;
804 }
805 else {
806 tb_write_log("This is NOT a v1 upgrade!"); //PC
807 return false;
808 }
809 }
810
811 function is_db_updated_for_min_ver($min_ver) {
812 global $wpdb;
813 $table_name = $wpdb->prefix . "_taboola_settings";
814
815 if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
816 tb_write_log("Table NOT FOUND");
817 return false;
818 }
819 else {
820 tb_write_log("Table EXISTS");
821 }
822 $saved_version = get_option(TABOOLA_OPTION_NAME, '1.0.0');
823
824 $db_is_up_to_date = version_compare($saved_version, $min_ver, '>=');
825 return $db_is_up_to_date;
826
827 }
828
829 function is_db_updated_for_current_ver() {
830 global $wpdb;
831 $saved_version = get_option(TABOOLA_OPTION_NAME, '1.0.0');
832 $plugin_version = $this->get_loaded_plugin_version();
833 $db_is_up_to_date = version_compare($saved_version, $plugin_version, '>=');
834 return $db_is_up_to_date;
835 }
836
837 function get_loaded_plugin_version() {
838 $plugin_data = get_plugin_data( __FILE__ );
839 $loaded_plugin_version = $plugin_data['Version'];
840 return $loaded_plugin_version;
841 }
842
843 function save_taboola_version($min_ver) {
844 tb_write_log("SAVING NEW MIN VERSION: " . $min_ver); // PC
845 $saved_version = get_option(TABOOLA_OPTION_NAME, '');
846 if ($saved_version == '') {
847 add_option(TABOOLA_OPTION_NAME, $min_ver);
848 }
849 else {
850 update_option(TABOOLA_OPTION_NAME, $min_ver);
851 }
852 }
853
854 function update_db(){
855 if ($this->is_db_updated_for_min_ver(TABOOLA_MIN_VER)) {
856 return;
857 }
858
859 $this->save_taboola_version(TABOOLA_MIN_VER);
860
861 global $wpdb;
862 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
863
864 $charset_collate = '';
865 if ( ! empty( $wpdb->charset ) ) {
866 $charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}";
867 }
868 if ( ! empty( $wpdb->collate ) ) {
869 $charset_collate .= " COLLATE {$wpdb->collate}";
870 }
871
872 $is_upgrade_from_v1 = $this->is_upgrade_from_v1();
873 $sql_table_settings = "
874 CREATE TABLE `" . $wpdb->prefix . "_taboola_settings` (
875 `id` INT NOT NULL AUTO_INCREMENT ,
876 `publisher_id` VARCHAR(255) DEFAULT NULL,
877 `web_push_enabled` TINYINT(1) NOT NULL DEFAULT FALSE,
878 `publisher_id_push` INT(15) DEFAULT NULL,
879 `first_bc_enabled` TINYINT(1) NOT NULL DEFAULT FALSE,
880 `first_bc_widget_id` VARCHAR(255) DEFAULT NULL,
881 `first_bc_placement` VARCHAR(255) DEFAULT " . ($is_upgrade_from_v1 ? "'below-article'" : "NULL") .",
882 `out_of_content_enabled` TINYINT(1) NOT NULL DEFAULT TRUE,
883 `mid_enabled` TINYINT(1) NOT NULL DEFAULT FALSE,
884 `mid_widgets` TEXT DEFAULT NULL,
885 `home_enabled` TINYINT(1) NOT NULL DEFAULT FALSE,
886 `home_widget_id` VARCHAR(255) DEFAULT NULL,
887 `home_placement` VARCHAR(255) DEFAULT NULL,
888 `home_location_string` TEXT DEFAULT NULL,
889 `home_location_string_occurrence` SMALLINT DEFAULT NULL,
890 `category_enabled` TINYINT(1) NOT NULL DEFAULT FALSE,
891 `category_widget_id` VARCHAR(255) DEFAULT NULL,
892 `category_placement` VARCHAR(255) DEFAULT NULL,
893 `category_location_string` TEXT DEFAULT NULL,
894 `category_location_string_occurrence` SMALLINT DEFAULT NULL,
895 PRIMARY KEY (`id`)
896 ) $charset_collate;";
897 dbDelta($sql_table_settings);
898 }
899 }
900 }
901
902 global $taboolaWP;
903 $taboolaWP = new TaboolaWP();
904
905 function tb_write_log($log_msg)
906 {
907 if (!TABOOLA_DEBUG_MODE)
908 return;
909
910 $log_filename = "logs";
911 if (!file_exists($log_filename))
912 {
913 mkdir($log_filename, 0777, true);
914 }
915 $log_file_data = $log_filename.'/debug.log';
916
917 $date = date('Y-m-d H:i:s');
918 $log_msg_with_date = $date." : ".$log_msg;
919
920 file_put_contents($log_file_data, $log_msg_with_date . "\n", FILE_APPEND);
921 }
922
923 function tb_console_log( $data ){
924
925 If(wp_get_environment_type() === 'development') {
926
927 echo '<script>';
928 echo 'console.log('. json_encode( $data ) .')';
929 echo '</script>';
930
931 }
932 }
933
934 function tb_print_to_page($data) {
935 If(wp_get_environment_type() === 'development') {
936 print_r($data);
937 die;
938 }
939 }
940
941 function enqueue_taboola_scripts() {
942 wp_register_script(
943 'taboola-injector',
944 plugins_url('js/js_inject.min.js', __FILE__),
945 array(),
946 null,
947 true
948 );
949
950 wp_enqueue_script('taboola-injector');
951 }
952 add_action('wp_enqueue_scripts', 'enqueue_taboola_scripts');