PluginProbe
Boxzilla – WordPress Popup Builder / 3.2.17
Boxzilla – WordPress Popup Builder v3.2.17
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
boxzilla / src / class-loader.php

class-loader.php in Boxzilla – WordPress Popup Builder 3.2.17, at src/class-loader.php

338 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Boxzilla;
4
5 class BoxLoader {
6
7
8 /**
9 * @var Plugin
10 */
11 private $plugin;
12
13 /**
14 * @var array
15 */
16 private $box_ids_to_load = array();
17
18 /**
19 * @var array
20 */
21 protected $options;
22
23 /**
24 * Constructor
25 *
26 * @param Plugin $plugin
27 * @param array $options
28 */
29 public function __construct( Plugin $plugin, array $options ) {
30 $this->plugin = $plugin;
31 $this->options = $options;
32 }
33
34 /**
35 * Initializes the plugin, runs on `wp` hook.
36 */
37 public function init() {
38 $this->box_ids_to_load = $this->filter_boxes();
39
40 // Only add other hooks if necessary
41 if ( count( $this->box_ids_to_load ) > 0 ) {
42 add_action( 'wp_footer', array( $this, 'print_boxes_content' ), 1 );
43 add_action( 'wp_enqueue_scripts', array( $this, 'load_assets' ), 90 );
44 }
45 }
46
47 /**
48 * Get global rules for all boxes
49 *
50 * @return array
51 */
52 protected function get_filter_rules() {
53 $rules = get_option( 'boxzilla_rules', array() );
54
55 if ( ! is_array( $rules ) ) {
56 return array();
57 }
58
59 return $rules;
60 }
61
62
63 /**
64 * Match a string against an array of patterns, glob-style.
65 *
66 * @param string $string
67 * @param array $patterns
68 *
69 * @return boolean
70 */
71 protected function match_patterns( $string, $patterns, $contains = false ) {
72 $string = strtolower( $string );
73
74 foreach ( $patterns as $pattern ) {
75 $pattern = rtrim( $pattern, '/' );
76 $pattern = strtolower( $pattern );
77
78 // contains means we should do a simple occurrence check
79 // does not support wildcards
80 if ( $contains ) {
81 return strpos( $string, $pattern ) !== false;
82 }
83
84 if ( function_exists( 'fnmatch' ) ) {
85 $match = fnmatch( $pattern, $string );
86 } else {
87 $match = ( $pattern === $string );
88 }
89
90 if ( $match ) {
91 return true;
92 }
93 }
94
95 return false;
96 }
97
98 /**
99 * @return string
100 */
101 protected function get_request_url() {
102 // strip trailing slashes
103 $request_uri = rtrim( $_SERVER['REQUEST_URI'], '/' );
104 return $request_uri;
105 }
106
107 /**
108 * Check if this rule passes (conditional matches expected value)
109 *
110 * @param string $condition
111 * @param string $value
112 * @param boolean $qualifier
113 *
114 * @return bool
115 */
116 protected function match_rule( $condition, $value, $qualifier = true ) {
117 $matched = false;
118
119 // cast value to array & trim whitespace or excess comma's
120 $value = array_map( 'trim', explode( ',', rtrim( trim( $value ), ',' ) ) );
121
122 switch ( $condition ) {
123 case 'everywhere':
124 $matched = true;
125 break;
126
127 case 'is_url':
128 $url = $this->get_request_url();
129 $matched = $this->match_patterns( $url, $value, $qualifier === 'contains' || $qualifier === 'not_contains' );
130 break;
131
132 case 'is_referer':
133 if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
134 $referer = $_SERVER['HTTP_REFERER'];
135 $matched = $this->match_patterns( $referer, $value, $qualifier === 'contains' || $qualifier === 'not_contains' );
136 }
137 break;
138
139 case 'is_post_type':
140 $post_type = (string) get_post_type();
141 $matched = in_array( $post_type, (array) $value, true );
142 break;
143
144 case 'is_single':
145 case 'is_post':
146 // convert to empty string if array with just empty string in it
147 $value = ( $value === array( '' ) ) ? '' : $value;
148 $matched = is_single( $value );
149 break;
150
151 case 'is_post_in_category':
152 $matched = is_singular( 'post' ) && has_category( $value );
153 break;
154
155 case 'is_page':
156 $matched = is_page( $value );
157 break;
158
159 case 'is_post_with_tag':
160 $matched = is_singular( 'post' ) && has_tag( $value );
161 break;
162
163 case 'is_user_logged_in':
164 $matched = is_user_logged_in();
165 break;
166 }
167
168 /**
169 * Filters whether a given box rule matches the condition and expected value.
170 *
171 * The dynamic portion of the hook, `$condition`, refers to the condition being matched.
172 *
173 * @param boolean $matched
174 * @param array $value
175 */
176 $matched = apply_filters( 'boxzilla_box_rule_matches_' . $condition, $matched, $value );
177
178 // if qualifier is set to false, we need to reverse this value here.
179 if ( ! $qualifier || $qualifier === 'not_contains' ) {
180 $matched = ! $matched;
181 }
182
183 return $matched;
184 }
185
186 /**
187 * Checks which boxes should be loaded for this request.
188 *
189 * @return array
190 */
191 private function filter_boxes() {
192 $box_ids_to_load = array();
193 $rules = $this->get_filter_rules();
194
195 foreach ( $rules as $box_id => $box_rules ) {
196 $matched = false;
197 $comparision = isset( $box_rules['comparision'] ) ? $box_rules['comparision'] : 'any';
198
199 // loop through all rules for all boxes
200 foreach ( $box_rules as $rule ) {
201
202 // skip faulty values (and comparision rule)
203 if ( empty( $rule['condition'] ) ) {
204 continue;
205 }
206
207 $qualifier = isset( $rule['qualifier'] ) ? $rule['qualifier'] : true;
208 $matched = $this->match_rule( $rule['condition'], $rule['value'], $qualifier );
209
210 // break out of loop if we've already matched
211 if ( $comparision === 'any' && $matched ) {
212 break;
213 }
214
215 // no need to continue if this rule didn't match
216 if ( $comparision === 'all' && ! $matched ) {
217 break;
218 }
219 }
220
221 // value of $matched at this point determines whether box should be loaded
222 $load_box = $matched;
223
224 /**
225 * Filters whether a box should be loaded into the page HTML.
226 *
227 * The dynamic portion of the hook, `$box_id`, refers to the ID of the box. Return true if you want to output the box.
228 *
229 * @param boolean $load_box
230 */
231 $load_box = apply_filters( 'boxzilla_load_box_' . $box_id, $load_box );
232
233 /**
234 * Filters whether a box should be loaded into the page HTML.
235 *
236 * @param boolean $load_box
237 * @param int $box_id
238 */
239 $load_box = apply_filters( 'boxzilla_load_box', $load_box, $box_id );
240
241 // if matched, box should be loaded on this page
242 if ( $load_box ) {
243 $box_ids_to_load[] = $box_id;
244 }
245 }
246
247 /**
248 * Filters which boxes should be loaded on this page, expects an array of post ID's.
249 *
250 * @param array $box_ids_to_load
251 */
252 return apply_filters( 'boxzilla_load_boxes', $box_ids_to_load );
253 }
254
255 /**
256 * Load plugin styles
257 */
258 public function load_assets() {
259 $pre_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
260 wp_enqueue_script( 'boxzilla', $this->plugin->url( '/assets/js/script' . $pre_suffix . '.js' ), array(), $this->plugin->version(), true );
261
262 // create boxzilla_Global_Options object
263 $plugin_options = $this->options;
264 $boxes = $this->get_matched_boxes();
265
266 $data = array(
267 'testMode' => (bool) $plugin_options['test_mode'],
268 'boxes' => (array) array_map(
269 function ( Box $box ) {
270 return $box->get_client_options();
271 },
272 $boxes
273 ),
274 );
275
276 wp_localize_script( 'boxzilla', 'boxzilla_options', $data );
277
278 do_action( 'boxzilla_load_assets', $this );
279 }
280
281 public function print_boxes_content() {
282 $boxes = $this->get_matched_boxes();
283 if ( empty( $boxes ) ) {
284 return;
285 }
286
287 echo '<div style="display: none;">';
288 foreach ( $boxes as $box ) {
289 echo sprintf( '<div id="boxzilla-box-%d-content">', $box->ID ) . $box->get_content() . '</div>';
290 }
291 echo '</div>';
292 }
293
294 /**
295 * Get an array of Box objects. These are the boxes that will be loaded for the current request.
296 *
297 * @return Box[]
298 */
299 public function get_matched_boxes() {
300 static $boxes;
301
302 if ( is_null( $boxes ) ) {
303 if ( count( $this->box_ids_to_load ) === 0 ) {
304 $boxes = array();
305 return $boxes;
306 }
307
308 // query Box posts
309 $q = new \WP_Query();
310 $posts = $q->query(
311 array(
312 'post_type' => 'boxzilla-box',
313 'post_status' => 'publish',
314 'post__in' => $this->box_ids_to_load,
315 'posts_per_page' => count( $this->box_ids_to_load ),
316 'ignore_sticky_posts' => true,
317 'no_found_rows' => true,
318 )
319 );
320
321 // create `Box` instances out of \WP_Post instances
322 $boxes = array();
323 foreach ( $posts as $key => $post ) {
324 $box = new Box( $post );
325
326 // skip boxes without any content
327 if ( $box->get_content() === '' ) {
328 continue;
329 }
330
331 $boxes[ $key ] = $box;
332 }
333 }
334
335 return $boxes;
336 }
337 }
338