PluginProbe
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts / 2.3.1
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts v2.3.1
2.7.6 2.7.5 2.7.4 trunk 1.3 2.0.4 2.0.6 2.1.91 2.2.4 2.2.7 2.2.9 2.3.1 2.3.10 2.4.10 2.4.2 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.6.0 2.6.1 2.7.0 2.7.1 All 27 releases
insert-php / includes / class.execute.snippet.php

class.execute.snippet.php in Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts 2.3.1, at includes/class.execute.snippet.php

966 lines 30.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Execute snippet
4 *
5 * @author Webcraftic <wordpress.webraftic@gmail.com>
6 * @copyright (c) 16.11.2018, Webcraftic
7 * @version 1.0
8 */
9
10 // Exit if accessed directly
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 class WINP_Execute_Snippet {
16
17 /**
18 * WINP_Execute_Snippet constructor.
19 */
20 public function __construct() {
21 if ( ! defined( 'WINP_UPLOAD_DIR' ) ) {
22 $dir = wp_upload_dir();
23 define( 'WINP_UPLOAD_DIR', $dir['basedir'] . '/winp-css-js' );
24 }
25
26 if ( ! defined( 'WINP_UPLOAD_URL' ) ) {
27 $dir = wp_upload_dir();
28 define( 'WINP_UPLOAD_URL', $dir['baseurl'] . '/winp-css-js' );
29 }
30 }
31
32 /**
33 * Register hooks
34 */
35 public function registerHooks() {
36 add_action( 'plugins_loaded', [ $this, 'executeEverywhereSnippets' ], 1 );
37
38 if ( ! is_admin() ) { #issue PCS-45 fix bug with WPBPage Builder Frontend Editor
39 add_action( 'wp_head', [ $this, 'executeHeaderSnippets' ] );
40 add_action( 'wp_footer', [ $this, 'executeFooterSnippets' ] );
41 add_filter( 'the_post', [ $this, 'executePostSnippets' ], 10, 2 );
42 add_filter( 'the_content', [ $this, 'executeContentSnippets' ] );
43 add_filter( 'the_excerpt', [ $this, 'executeExcerptSnippets' ] );
44 add_filter( 'wp_list_comments_args', [ $this, 'executeListCommentsSnippets' ] );
45 }
46 }
47
48 /**
49 * Execute the evrywhere snippets once the plugins are loaded
50 */
51 public function executeEverywhereSnippets() {
52 echo $this->executeActiveSnippets( 'evrywhere' );
53 }
54
55 /**
56 * Execute the snippets in header of page once the plugins are loaded
57 */
58 public function executeHeaderSnippets() {
59 echo $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_HEADER );
60 }
61
62 /**
63 * Execute the snippets in footer of page once the plugins are loaded
64 */
65 public function executeFooterSnippets() {
66 echo $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_FOOTER );
67 }
68
69 /**
70 * Execute the snippets before post
71 *
72 * @param $data
73 * @param $query
74 */
75 public function executePostSnippets( $data, $query ) {
76 global $post;
77
78 $content = '';
79
80 $post_type = ! empty( $post ) ? $post->post_type : get_post( $data->ID )->post_type;
81 if ( is_singular( [ $post_type ] ) && $post->ID == $data->ID ) {
82 if ( did_action( 'get_header' ) ) {
83 // Перед заголовком
84 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BEFORE_POST );
85 }
86 } else {
87 if ( $query->post_count > 0 ) {
88 if ( $query->post_count > 1 && $query->current_post > 0 && $query->post_count > $query->current_post ) {
89 // Между записями
90 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BETWEEN_POSTS );
91 }
92 // Перед записью
93 $content .= $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BEFORE_POSTS, '', $query );
94
95 // После записи
96 $content .= $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_POSTS, '', $query );
97 }
98 }
99
100 echo $content;
101 }
102
103 /**
104 * Handle paragraph content
105 *
106 * @param $content
107 * @param $snippet_content
108 * @param $paragraph_number
109 * @param $type
110 *
111 * @return mixed
112 */
113 private function handleParagraphContent( $content, $snippet_content, $paragraph_number, $type = 'before' ) {
114 if ( 'before' == $type ) {
115 preg_match_all( "/<p(.*?)>/", $content, $matches );
116 } else {
117 preg_match_all( "/<\/p>/", $content, $matches );
118 }
119 $paragraphs = $matches[0];
120
121 if ( $paragraph_number == 0 ) {
122 $paragraph_number = 1;
123 }
124
125 if ( $content && $snippet_content && $paragraphs && $paragraph_number <= count( $paragraphs ) ) {
126 $offset = 0;
127 foreach ( $paragraphs as $paragraph_key => $paragraph ) {
128 $position = strpos( $content, $paragraph, $offset ); // Позиция тега параграфа
129 // Если указанный номер параграфа совпадает с текущим
130 if ( $paragraph_key + 1 == $paragraph_number ) {
131 if ( 'before' == $type ) {
132 $content = substr( $content, 0, $position ) . $snippet_content . substr( $content, $position );
133 } else {
134 $content = substr( $content, 0, $position + 4 ) . $snippet_content . substr( $content, $position + 4 );
135 }
136 break;
137 } else {
138 $offset = $position + 1;
139 }
140 }
141 }
142
143 return $content;
144 }
145
146 /**
147 * Handle posts content
148 *
149 * @param string $content
150 * @param string $snippet_content
151 * @param integer $post_number
152 * @param string $type
153 * @param object $query
154 *
155 * @return mixed
156 */
157 private function handlePostsContent( $content, $snippet_content, $post_number, $type, $query ) {
158 global $winp_after_post_content;
159 if ( $query->post_count > 0 ) {
160 if ( $post_number == 0 ) {
161 $post_number = 1;
162 }
163
164 if ( 'before' == $type && $query->current_post + 1 == $post_number ) {
165 return $snippet_content;
166 } else if ( 'after' == $type ) {
167 // Номер поста совпадает
168 if ( $query->current_post == $post_number ) {
169 return $snippet_content;
170 // Если это последний пост и указанный номер поста больше общего количества постов,
171 // то нужно со�
172 ранить контент сниппета для вывода в конце данного поста
173 } else if ( $query->current_post + 1 == $query->post_count && $post_number >= $query->post_count ) {
174 $winp_after_post_content[ $query->post->ID ] = $snippet_content;
175 }
176 }
177 }
178
179 return $content;
180 }
181
182 /**
183 * Execute the snippets page content
184 *
185 * @param $content
186 *
187 * @return mixed
188 */
189 public function executeContentSnippets( $content ) {
190 global $post, $winp_after_post_content;
191
192 $post_type = ! empty( $post ) ? $post->post_type : false;
193
194 if ( is_category() || is_archive() || is_tag() || is_tax() || is_search() ) {
195 // Перед коротким описанием
196 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BEFORE_EXCERPT ) . $content;
197
198 // После короткого описания
199 $content .= $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_EXCERPT );
200 }
201
202 if ( is_singular( [ $post_type ] ) ) {
203 // Перед параграфом
204 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BEFORE_PARAGRAPH, $content );
205
206 // После параграфа
207 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_PARAGRAPH, $content );
208
209 // После заголовка
210 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BEFORE_CONTENT ) . $content;
211
212 // После текста
213 $content .= $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_CONTENT );
214
215 // После поста
216 $content .= $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_POST );
217
218 if ( ! comments_open( $post->ID ) && ! get_comments_number( $post->ID ) ) {
219 remove_filter( 'wp_list_comments_args', [ $this, 'executeListCommentsSnippets' ] );
220 }
221 } else if ( ! is_null( $post ) && isset( $winp_after_post_content[ $post->ID ] ) ) {
222 // После последнего поста в списке
223 $content .= $winp_after_post_content[ $post->ID ];
224 unset( $winp_after_post_content[ $post->ID ] );
225 }
226
227 return $content;
228 }
229
230 /**
231 * Execute the snippets page excerpt
232 *
233 * @param $excerpt
234 *
235 * @return mixed
236 */
237 public function executeExcerptSnippets( $excerpt ) {
238 if ( is_category() || is_archive() || is_tag() || is_tax() || is_search() ) {
239 // Перед коротким описанием
240 $excerpt = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_BEFORE_EXCERPT ) . $excerpt;
241
242 // После короткого описания
243 $excerpt .= $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_EXCERPT );
244 }
245
246 return $excerpt;
247 }
248
249 /**
250 * Execute the list comments filter
251 *
252 * @param $args
253 *
254 * @return mixed
255 */
256 public function executeListCommentsSnippets( $args ) {
257 global $winp_wp_data;
258
259 $winp_wp_data['winp_comments_saved_end_callback'] = $args['end-callback'];
260 $args['end-callback'] = [ $this, 'executeCommentsSnippets' ];
261
262 return $args;
263 }
264
265 /**
266 * Execute the snippets after page comments
267 *
268 * @param $comment
269 * @param $args
270 * @param $depth
271 */
272 public function executeCommentsSnippets( $comment, $args, $depth ) {
273 global $winp_wp_data, $post;
274
275 if ( ! empty ( $winp_wp_data['winp_comments_saved_end_callback'] ) ) {
276 echo call_user_func( $winp_wp_data['winp_comments_saved_end_callback'], $comment, $args, $depth );
277 }
278
279 $content = '';
280
281 $post_type = ! empty( $post ) ? $post->post_type : false;
282 if ( is_singular( [ $post_type ] ) ) {
283 // После комментариев
284 $content = $this->executeActiveSnippets( 'auto', WINP_SNIPPET_AUTO_AFTER_POST );
285 }
286
287 echo $content;
288 }
289
290 /**
291 * Execute the snippets once the plugins are loaded
292 *
293 * @param string $scope
294 * @param string $auto
295 * @param string $content
296 * @param array $custom_params
297 *
298 * @return string
299 */
300 public function executeActiveSnippets( $scope = 'evrywhere', $auto = '', $content = '', $custom_params = [] ) {
301 global $wpdb;
302
303 $snippets = $wpdb->get_results( "SELECT {$wpdb->posts}.ID, {$wpdb->posts}.post_content
304 FROM {$wpdb->posts}
305 INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)
306 WHERE (( {$wpdb->postmeta}.meta_key = '" . WINP_Plugin::app()->getPrefix() . "snippet_scope'
307 AND {$wpdb->postmeta}.meta_value = '{$scope}'))
308 AND {$wpdb->posts}.post_type = '" . WINP_SNIPPETS_POST_TYPE . "'
309 AND (({$wpdb->posts}.post_status = 'publish'))" );
310
311
312 if ( empty( $snippets ) ) {
313 return $content;
314 }
315
316 foreach ( (array) $snippets as $snippet ) {
317 $id = (int) $snippet->ID;
318
319 $is_active = (int) WINP_Helper::getMetaOption( $id, 'snippet_activate', 0 );
320 // Если это сниппет с автовставкой и выбранное место под�
321 одит под активный action
322 $avail_place = ( 'auto' == $scope ? $auto == WINP_Helper::getMetaOption( $id, 'snippet_location', '' ) : true );
323 // Если условие отображения сниппена выполняется
324 $snippet_type = WINP_Helper::getMetaOption( $id, 'snippet_type', WINP_SNIPPET_TYPE_PHP );
325 $is_condition = $snippet_type != WINP_SNIPPET_TYPE_PHP ? $this->checkCondition( $id ) : true;
326
327 if ( $is_active && $avail_place && $is_condition ) {
328 $post_id = (int) WINP_Plugin::app()->request->post( 'post_ID', 0 );
329
330 if ( isset( $_POST['wbcr_inp_snippet_scope'] ) && $post_id === $id && WINP_Plugin::app()->currentUserCan() ) {
331 return $content;
332 }
333
334 if ( WINP_Helper::is_safe_mode() ) {
335 return $content;
336 }
337
338 $snippet_code = WINP_Helper::get_snippet_code( $snippet );
339
340 if ( $snippet_type === WINP_SNIPPET_TYPE_TEXT ) {
341 $snippet_content = '<div class="winp-text-snippet-contanier">' . $snippet_code . '</div>';
342 } else if ( $snippet_type === WINP_SNIPPET_TYPE_CSS || $snippet_type === WINP_SNIPPET_TYPE_JS ) {
343 $snippet_content = self::getJsCssSnippetData( $id );
344 } else if ( $snippet_type === WINP_SNIPPET_TYPE_HTML ) {
345 $snippet_content = $snippet_code;
346 } else {
347 $code = $this->prepareCode( $snippet_code, $id );
348 ob_start();
349 $this->executeSnippet( $code, $id, false );
350 $snippet_content = ob_get_contents();
351 ob_end_clean();
352 }
353
354 if ( 'auto' == $scope ) {
355 switch ( $auto ) {
356 case WINP_SNIPPET_AUTO_BEFORE_PARAGRAPH: // Перед параграфом
357 $location_number = WINP_Helper::getMetaOption( $id, 'snippet_p_number', 0 );
358 $content = $this->handleParagraphContent( $content, $snippet_content, $location_number );
359 break;
360 case WINP_SNIPPET_AUTO_AFTER_PARAGRAPH: // После параграфа
361 $location_number = WINP_Helper::getMetaOption( $id, 'snippet_p_number', 0 );
362 $content = $this->handleParagraphContent( $content, $snippet_content, $location_number, 'after' );
363 break;
364 case WINP_SNIPPET_AUTO_BEFORE_POSTS: // Перед записью
365 $location_number = WINP_Helper::getMetaOption( $id, 'snippet_p_number', 0 );
366 $content = $this->handlePostsContent( $content, $snippet_content, $location_number, 'before', $custom_params );
367 break;
368 case WINP_SNIPPET_AUTO_AFTER_POSTS: // После записи
369 $location_number = WINP_Helper::getMetaOption( $id, 'snippet_p_number', 0 );
370 $content = $this->handlePostsContent( $content, $snippet_content, $location_number, 'after', $custom_params );
371 break;
372 default:
373 $content = $snippet_content . $content;
374 }
375 } else {
376 $content = $snippet_content . $content;
377 }
378 }
379 }
380
381 return $content;
382 }
383
384 /**
385 * Get js or css snippet data
386 *
387 * @param $snippet_id
388 *
389 * @return mixed|string
390 */
391 public static function getJsCssSnippetData( $snippet_id ) {
392 $snippet_type = WINP_Helper::get_snippet_type( $snippet_id );
393
394 $linking = WINP_Helper::getMetaOption( $snippet_id, 'snippet_linking' );
395 $filetype = WINP_Helper::getMetaOption( $snippet_id, 'filetype', $snippet_type );
396
397 $file_name = $snippet_id . '.' . $filetype;
398 $slug = WINP_Helper::getMetaOption( $snippet_id, 'css_js_slug' );
399 if ( ! empty( $slug ) ) {
400 $file_name = $slug . '.' . $filetype;
401 }
402
403 if ( file_exists( WINP_UPLOAD_DIR . '/' . $file_name ) ) {
404 if ( 'inline' == $linking ) {
405 return file_get_contents( WINP_UPLOAD_DIR . '/' . $file_name );
406 }
407
408 if ( 'external' == $linking ) {
409 $file_name .= '?ver=' . WINP_Helper::getMetaOption( $snippet_id, 'css_js_version', time() );
410
411 if ( 'js' == $snippet_type ) {
412 return PHP_EOL . "<script type='text/javascript' src='" . WINP_UPLOAD_URL . '/' . $file_name . "'></script>" . PHP_EOL;
413 }
414
415 if ( 'css' == $snippet_type ) {
416 $short_filename = preg_replace( '@\.css\?ver=.*$@', '', $file_name );
417
418 return PHP_EOL . "<link rel='stylesheet' id='" . $short_filename . "-css' href='" . WINP_UPLOAD_URL . '/' . $file_name . "' type='text/css' media='all' />" . PHP_EOL;
419 }
420 }
421 }
422
423 return "";
424 }
425
426 /**
427 * Execute a snippet
428 *
429 * Code must NOT be escaped, as
430 * it will be executed directly
431 *
432 * @param string $code The snippet code to execute
433 * @param int $id The snippet ID
434 * @param bool $catch_output Whether to attempt to suppress the output of execution using buffers
435 *
436 * @return mixed The result of the code execution
437 */
438 public function executeSnippet( $code, $id = 0, $catch_output = true ) {
439 $id = (int) $id;
440
441 if ( ! $id || empty( $code ) ) {
442 return false;
443 }
444
445 if ( $catch_output ) {
446 ob_start();
447 }
448
449 $snippet = get_post( $id );
450
451 if ( empty( $snippet ) || $snippet->post_type !== WINP_SNIPPETS_POST_TYPE ) {
452 return false;
453 }
454
455 $snippet_type = WINP_Helper::getMetaOption( $id, 'snippet_type', true );
456
457 if ( $snippet_type == WINP_SNIPPET_TYPE_UNIVERSAL ) {
458 $result = eval( "?>" . $code . "<?php " );
459 } else if ( $snippet_type == WINP_SNIPPET_TYPE_PHP ) {
460 $result = eval( $code );
461 } else {
462 $result = ! empty( $code );
463 }
464
465 if ( $catch_output ) {
466 ob_end_clean();
467 }
468
469 return $result;
470 }
471
472 /**
473 * Get property value
474 *
475 * @param $value
476 * @param $property
477 *
478 * @return null
479 */
480 private function getPropertyValue( $value, $property ) {
481 if ( is_object( $value ) ) {
482 return $value->$property;
483 } else if ( isset( $value[ $property ] ) ) {
484 return $value[ $property ];
485 }
486
487 return null;
488 }
489
490 /**
491 * Check conditional execution logic for the snippet
492 *
493 * @param $snippet_id
494 *
495 * @return bool
496 */
497 public function checkCondition( $snippet_id ) {
498 // Итоговый результат условий
499 $result = true;
500 // Получаем со�
501 ранённые параметры условий
502 $filters = get_post_meta( $snippet_id, WINP_Plugin::app()->getPrefix() . 'snippet_filters' );
503 // Если условия указаны
504 if ( ! ( empty( $filters ) || isset( $filters[0] ) && empty( $filters[0] ) ) ) {
505 foreach ( $filters[0] as $filter ) {
506 $conditions = $this->getPropertyValue( $filter, 'conditions' );
507 // Если условия пусты, то пропускаем цикл
508 if ( empty( $conditions ) ) {
509 continue;
510 }
511 // Промежуточный результат AND условий
512 $and_conditions = null;
513 // Про�
514 одим по AND условиям
515 foreach ( $conditions as $scope ) {
516 $scope_conditions = $this->getPropertyValue( $scope, 'conditions' );
517 // Если условия пусты, то пропускаем цикл
518 if ( empty( $scope_conditions ) ) {
519 continue;
520 }
521 // Промежуточный результат OR условий
522 $or_conditions = null;
523 // Про�
524 одим по OR условиям
525 foreach ( $scope_conditions as $condition ) {
526 $method_name = str_replace( '-', '_', $this->getPropertyValue( $condition, 'param' ) );
527 $operator = $this->getPropertyValue( $condition, 'operator' );
528 $value = $this->getPropertyValue( $condition, 'value' );
529 // Получаем результат OR условий
530 $or_conditions = is_null( $or_conditions ) ? $this->call_method( $method_name, $operator, $value ) : $or_conditions || $this->call_method( $method_name, $operator, $value );
531 }
532 // Получаем результат AND условий
533 $and_conditions = is_null( $and_conditions ) ? $or_conditions : $and_conditions && $or_conditions;
534 }
535 // Получаем результат блока условий
536 $result = $this->getPropertyValue( $filter, 'type' ) == 'showif' ? $and_conditions : ! $and_conditions;
537 }
538 }
539
540 return $result;
541 }
542
543 /**
544 * Call specified method
545 *
546 * @param $method_name
547 * @param $operator
548 * @param $value
549 *
550 * @return bool
551 */
552 private function call_method( $method_name, $operator, $value ) {
553 if ( method_exists( $this, $method_name ) ) {
554 return $this->$method_name( $operator, $value );
555 } else {
556 return apply_filters( 'wbcr/inp/execute/check_condition', false, $method_name, $operator, $value );
557 }
558 }
559
560 /**
561 * Retrieve the first error in a snippet's code
562 *
563 * @param int $snippet_id
564 *
565 * @return array|bool
566 */
567 public function getSnippetError( $snippet_id ) {
568 if ( ! intval( $snippet_id ) ) {
569 return false;
570 }
571
572 $snippet = get_post( $snippet_id );
573
574 if ( ! $snippet ) {
575 return false;
576 }
577
578 $snippet_code = WINP_Helper::get_snippet_code( $snippet );
579 $snippet_code = $this->prepareCode( $snippet_code, $snippet_id );
580
581 $result = $this->executeSnippet( $snippet_code, $snippet_id );
582
583 if ( false !== $result ) {
584 return false;
585 }
586
587 $error = error_get_last();
588
589 if ( is_null( $error ) ) {
590 return false;
591 }
592
593 return $error;
594 }
595
596 /**
597 * Prepare the code by removing php tags from beginning and end
598 *
599 * @param string $code
600 * @param integer $snippet_id
601 *
602 * @return string
603 */
604 public function prepareCode( $code, $snippet_id ) {
605 $snippet_type = WINP_Helper::get_snippet_type( $snippet_id );
606 if ( $snippet_type != WINP_SNIPPET_TYPE_UNIVERSAL && $snippet_type != WINP_SNIPPET_TYPE_CSS && $snippet_type != WINP_SNIPPET_TYPE_JS && $snippet_type != WINP_SNIPPET_TYPE_HTML ) {
607 /* Remove <?php and <? from beginning of snippet */
608 $code = preg_replace( '|^[\s]*<\?(php)?|', '', $code );
609
610 /* Remove ?> from end of snippet */
611 $code = preg_replace( '|\?>[\s]*$|', '', $code );
612 }
613
614 return $code;
615 }
616
617 /**
618 * Get current URL
619 *
620 * @return string
621 */
622 private function getCurrentUrl() {
623 $out = "";
624 $url = explode( '?', $_SERVER['REQUEST_URI'], 2 );
625 if ( isset( $url[0] ) ) {
626 $out = trim( $url[0], '/' );
627 }
628
629 return $out ? urldecode( $out ) : '/';
630 }
631
632 /**
633 * Get referer URL
634 *
635 * @return string
636 */
637 private function getRefererUrl() {
638 $out = "";
639 $url = explode( '?', str_replace( site_url(), '', $_SERVER['HTTP_REFERER'] ), 2 );
640 if ( isset( $url[0] ) ) {
641 $out = trim( $url[0], '/' );
642 }
643
644 return $out ? urldecode( $out ) : '/';
645 }
646
647 /**
648 * Check by operator
649 *
650 * @param $operation
651 * @param $first
652 * @param $second
653 * @param $third
654 *
655 * @return bool
656 */
657 public function checkByOperator( $operation, $first, $second, $third = false ) {
658 switch ( $operation ) {
659 case 'equals':
660 return $first === $second;
661 case 'notequal':
662 return $first !== $second;
663 case 'less':
664 case 'older':
665 return $first > $second;
666 case 'greater':
667 case 'younger':
668 return $first < $second;
669 case 'contains':
670 return strpos( $first, $second ) !== false;
671 case 'notcontain':
672 return strpos( $first, $second ) === false;
673 case 'between':
674 return $first < $second && $second < $third;
675
676 default:
677 return $first === $second;
678 }
679 }
680
681 /**
682 * A role of the user who views your website. The role "guest" is applied for unregistered users.
683 *
684 * @param string $operator
685 * @param string $value
686 *
687 * @return boolean
688 */
689 private function user_role( $operator, $value ) {
690 if ( ! is_user_logged_in() ) {
691 return $this->checkByOperator( $operator, $value, 'guest' );
692 } else {
693 $current_user = wp_get_current_user();
694 if ( ! ( $current_user instanceof WP_User ) ) {
695 return false;
696 }
697
698 return $this->checkByOperator( $operator, $value, $current_user->roles[0] );
699 }
700 }
701
702 /**
703 * Get timestamp
704 *
705 * @param $units
706 * @param $count
707 *
708 * @return integer
709 */
710 private function getTimestamp( $units, $count ) {
711 switch ( $units ) {
712 case 'seconds':
713 return $count;
714 case 'minutes':
715 return $count * MINUTE_IN_SECONDS;
716 case 'hours':
717 return $count * HOUR_IN_SECONDS;
718 case 'days':
719 return $count * DAY_IN_SECONDS;
720 case 'weeks':
721 return $count * WEEK_IN_SECONDS;
722 case 'months':
723 return $count * MONTH_IN_SECONDS;
724 case 'years':
725 return $count * YEAR_IN_SECONDS;
726
727 default:
728 return $count;
729 }
730 }
731
732 /**
733 * Get date timestamp
734 *
735 * @param $value
736 *
737 * @return integer
738 */
739 public function getDateTimestamp( $value ) {
740 if ( is_object( $value ) ) {
741 return ( current_time( 'timestamp' ) - $this->getTimestamp( $value->units, $value->unitsCount ) ) * 1000;
742 } else {
743 return $value;
744 }
745 }
746
747 /**
748 * The date when the user who views your website was registered.
749 * For unregistered users this date always equals to 1 Jan 1970.
750 *
751 * @param string $operator
752 * @param string $value
753 *
754 * @return boolean
755 */
756 private function user_registered( $operator, $value ) {
757 if ( ! is_user_logged_in() ) {
758 return false;
759 } else {
760 $user = wp_get_current_user();
761 $registered = strtotime( $user->data->user_registered ) * 1000;
762
763 if ( $operator == 'equals' || $operator == 'notequal' ) {
764 $registered = $registered / 1000;
765 $timestamp = round( $this->getDateTimestamp( $value ) / 1000 );
766
767 return $this->checkByOperator( $operator, date( "Y-m-d", $timestamp ), date( "Y-m-d", $registered ) );
768 } else if ( $operator == 'between' ) {
769 $start_timestamp = $this->getDateTimestamp( $value->start );
770 $end_timestamp = $this->getDateTimestamp( $value->end );
771
772 return $this->checkByOperator( $operator, $start_timestamp, $registered, $end_timestamp );
773 } else {
774 $timestamp = $this->getDateTimestamp( $value );
775
776 return $this->checkByOperator( $operator, $timestamp, $registered );
777 }
778 }
779 }
780
781 /**
782 * Check the user views your website from mobile device or not
783 *
784 * @param string $operator
785 * @param string $value
786 *
787 * @return boolean
788 *
789 * @link https://stackoverflow.com/a/4117597
790 */
791 private function user_mobile( $operator, $value ) {
792 $useragent = $_SERVER['HTTP_USER_AGENT'];
793
794 if ( preg_match( '/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $useragent ) || preg_match( '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', substr( $useragent, 0, 4 ) ) ) {
795 return $operator === 'equals' && $value === 'yes' || $operator === 'notequal' && $value === 'no';
796 } else {
797 return $operator === 'notequal' && $value === 'yes' || $operator === 'equals' && $value === 'no';
798 }
799 }
800
801 /**
802 * Determines whether the user's browser has a cookie with a given name
803 *
804 * @param $operator
805 * @param $value
806 *
807 * @return boolean
808 */
809 private function user_cookie_name( $operator, $value ) {
810 if ( isset( $_COOKIE[ $value ] ) ) {
811 return $operator === 'equals';
812 } else {
813 return $operator === 'notequal';
814 }
815 }
816
817 /**
818 * A some selected page
819 *
820 * @param $operator
821 * @param $value
822 *
823 * @return boolean
824 */
825 private function location_some_page( $operator, $value ) {
826 $post_id = ( ! is_404() && ! is_search() && ! is_archive() && ! is_home() ) ? get_the_ID() : false;
827
828 switch ( $value ) {
829 case 'base_web': // Basic - Entire Website
830 $result = true;
831 break;
832 case 'base_sing': // Basic - All Singulars
833 $result = is_singular();
834 break;
835 case 'base_arch': // Basic - All Archives
836 $result = is_archive();
837 break;
838 case 'spec_404': // Special Pages - 404 Page
839 $result = is_404();
840 break;
841 case 'spec_search': // Special Pages - Search Page
842 $result = is_search();
843 break;
844 case 'spec_blog': // Special Pages - Blog / Posts Page
845 $result = is_home();
846 break;
847 case 'spec_front': // Special Pages - Front Page
848 $result = is_front_page();
849 break;
850 case 'spec_date': // Special Pages - Date Archive
851 $result = is_date();
852 break;
853 case 'spec_auth': // Special Pages - Author Archive
854 $result = is_author();
855 break;
856 case 'post_all': // Posts - All Posts
857 case 'page_all': // Pages - All Pages
858 $result = false;
859 if ( false !== $post_id ) {
860 $post_type = 'post_all' == $value ? 'post' : 'page';
861 $result = $post_type == get_post_type( $post_id );
862 }
863 break;
864 case 'post_arch': // Posts - All Posts Archive
865 case 'page_arch': // Pages - All Pages Archive
866 $result = false;
867 if ( is_archive() ) {
868 $post_type = 'post_arch' == $value ? 'post' : 'page';
869 $result = $post_type == get_post_type();
870 }
871 break;
872 case 'post_cat': // Posts - All Categories Archive
873 case 'post_tag': // Posts - All Tags Archive
874 $result = false;
875 if ( is_archive() && 'post' == get_post_type() ) {
876 $taxonomy = 'post_tag' == $value ? 'post_tag' : 'category';
877 $obj = get_queried_object();
878
879 $current_taxonomy = '';
880 if ( '' !== $obj && null !== $obj ) {
881 $current_taxonomy = $obj->taxonomy;
882 }
883
884 if ( $current_taxonomy == $taxonomy ) {
885 $result = true;
886 }
887 }
888 break;
889
890 default:
891 $result = true;
892 }
893
894 return $this->checkByOperator( $operator, $result, true );
895 }
896
897 /**
898 * An URL of the current page where a user who views your website is located
899 *
900 * @param $operator
901 * @param $value
902 *
903 * @return boolean
904 */
905 private function location_page( $operator, $value ) {
906 $url = $this->getCurrentUrl();
907
908 return $url ? $this->checkByOperator( $operator, trim( $url, '/' ), trim( $value, '/' ) ) : false;
909 }
910
911 /**
912 * A referrer URL which has brought a user to the current page
913 *
914 * @param $operator
915 * @param $value
916 *
917 * @return boolean
918 */
919 private function location_referrer( $operator, $value ) {
920 $url = $this->getRefererUrl();
921
922 return $url ? $this->checkByOperator( $operator, trim( $url, '/' ), trim( $value, '/' ) ) : false;
923 }
924
925 /**
926 * A post type of the current page
927 *
928 * @param $operator
929 * @param $value
930 *
931 * @return boolean
932 */
933 private function location_post_type( $operator, $value ) {
934 if ( is_singular() ) {
935 return $this->checkByOperator( $operator, $value, get_post_type() );
936 }
937
938 return false;
939 }
940
941 /**
942 * A taxonomy of the current page
943 *
944 * @since 2.2.8 The bug is fixed, the condition was not checked
945 * for tachonomies, only posts.
946 *
947 * @param $operator
948 * @param $value
949 *
950 * @return boolean
951 */
952 private function location_taxonomy( $operator, $value ) {
953 $term_id = null;
954
955 if ( is_tax() || is_tag() || is_category() ) {
956 $term_id = get_queried_object()->term_id;
957
958 if ( $term_id ) {
959 return $this->checkByOperator( $operator, intval( $value ), $term_id );
960 }
961 }
962
963 return false;
964 }
965
966 }