PluginProbe
Boxzilla – WordPress Popup Builder / 3.2.6
Boxzilla – WordPress Popup Builder v3.2.6
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.6, at src/class-loader.php

333 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 * @var Plugin
9 */
10 private $plugin;
11
12 /**
13 * @var array
14 */
15 private $box_ids_to_load = array();
16
17 /**
18 * @var array
19 */
20 protected $options;
21
22 /**
23 * Constructor
24 *
25 * @param Plugin $plugin
26 * @param array $options
27 */
28 public function __construct( Plugin $plugin, array $options ) {
29 $this->plugin = $plugin;
30 $this->options = $options;
31 }
32
33 /**
34 * Initializes the plugin, runs on `wp` hook.
35 */
36 public function init() {
37
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
118 $matched = false;
119
120 // cast value to array & trim whitespace or excess comma's
121 $value = array_map( 'trim', explode( ',', rtrim( trim( $value ), ',' ) ) );
122
123 switch ( $condition ) {
124 case 'everywhere';
125 $matched = true;
126 break;
127
128 case 'is_url':
129 $url = $this->get_request_url();
130 $matched = $this->match_patterns( $url, $value, $qualifier === 'contains' || $qualifier === 'not_contains' );
131 break;
132
133 case 'is_referer':
134 if( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
135 $referer = $_SERVER['HTTP_REFERER'];
136 $matched = $this->match_patterns( $referer, $value, $qualifier === 'contains' || $qualifier === 'not_contains' );
137 }
138 break;
139
140 case 'is_post_type':
141 $post_type = (string) get_post_type();
142 $matched = in_array( $post_type, (array) $value );
143 break;
144
145 case 'is_single':
146 case 'is_post':
147 // convert to empty string if array with just empty string in it
148 $value = ( $value === array( '' ) ) ? '' : $value;
149 $matched = is_single( $value );
150 break;
151
152 case 'is_post_in_category':
153 $matched = is_singular( 'post' ) && has_category( $value );
154 break;
155
156
157 case 'is_page':
158 $matched = is_page( $value );
159 break;
160
161 case 'is_post_with_tag':
162 $matched = is_singular( 'post' ) && has_tag( $value );
163 break;
164
165 case 'is_user_logged_in':
166 $matched = is_user_logged_in();
167 break;
168 }
169
170 /**
171 * Filters whether a given box rule matches the condition and expected value.
172 *
173 * The dynamic portion of the hook, `$condition`, refers to the condition being matched.
174 *
175 * @param boolean $matched
176 * @param array $value
177 */
178 $matched = apply_filters( 'boxzilla_box_rule_matches_' . $condition, $matched, $value );
179
180 // if qualifier is set to false, we need to reverse this value here.
181 if( ! $qualifier || $qualifier === 'not_contains' ) {
182 $matched = ! $matched;
183 }
184
185 return $matched;
186 }
187
188 /**
189 * Checks which boxes should be loaded for this request.
190 *
191 * @return array
192 */
193 private function filter_boxes() {
194
195 $box_ids_to_load = array();
196 $rules = $this->get_filter_rules();
197
198 foreach( $rules as $box_id => $box_rules ) {
199
200 $matched = false;
201 $comparision = isset( $box_rules['comparision'] ) ? $box_rules['comparision'] : 'any';
202
203 // loop through all rules for all boxes
204 foreach ( $box_rules as $rule ) {
205
206 // skip faulty values (and comparision rule)
207 if( empty( $rule['condition'] ) ) {
208 continue;
209 }
210
211 $qualifier = isset( $rule['qualifier'] ) ? $rule['qualifier'] : true;
212 $matched = $this->match_rule( $rule['condition'], $rule['value'], $qualifier );
213
214 // break out of loop if we've already matched
215 if( $comparision === 'any' && $matched ) {
216 break;
217 }
218
219 // no need to continue if this rule didn't match
220 if( $comparision === 'all' && ! $matched ) {
221 break;
222 }
223 }
224
225 // value of $matched at this point determines whether box should be loaded
226 $load_box = $matched;
227
228 /**
229 * Filters whether a box should be loaded into the page HTML.
230 *
231 * The dynamic portion of the hook, `$box_id`, refers to the ID of the box. Return true if you want to output the box.
232 *
233 * @param boolean $load_box
234 */
235 $load_box = apply_filters( 'boxzilla_load_box_' . $box_id, $load_box );
236
237 /**
238 * Filters whether a box should be loaded into the page HTML.
239 *
240 * @param boolean $load_box
241 * @param int $box_id
242 */
243 $load_box = apply_filters( 'boxzilla_load_box', $load_box, $box_id );
244
245 // if matched, box should be loaded on this page
246 if ( $load_box ) {
247 $box_ids_to_load[] = $box_id;
248 }
249
250 }
251
252 return $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( function(Box $box) { return $box->get_client_options(); }, $boxes ),
269 );
270
271 wp_localize_script( 'boxzilla', 'boxzilla_options', $data );
272
273 do_action( 'boxzilla_load_assets', $this );
274 }
275
276 public function print_boxes_content() {
277 $boxes = $this->get_matched_boxes();
278 if( empty( $boxes ) ) {
279 return;
280 }
281
282 echo '<div style="display: none;">';
283 foreach( $boxes as $box ) {
284 echo sprintf( '<div id="boxzilla-box-%d-content">', $box->ID ) . $box->get_content() . '</div>';
285 }
286 echo '</div>';
287 }
288
289 /**
290 * Get an array of Box objects. These are the boxes that will be loaded for the current request.
291 *
292 * @return Box[]
293 */
294 public function get_matched_boxes() {
295 static $boxes;
296
297 if( is_null( $boxes ) ) {
298
299 if( count( $this->box_ids_to_load ) === 0 ) {
300 $boxes = array();
301 return $boxes;
302 }
303
304 // query Box posts
305 $posts = get_posts(
306 array(
307 'post_type' => 'boxzilla-box',
308 'post_status' => 'publish',
309 'post__in' => $this->box_ids_to_load,
310 'numberposts' => -1
311 )
312 );
313
314 // create `Box` instances out of \WP_Post instances
315 $boxes = array();
316 foreach ( $posts as $key => $post ) {
317 // skip posts with no content
318 $post_content = trim( strip_tags( nl2br( $post->post_content ) ) );
319 if( empty( $post_content ) ) {
320 continue;
321 }
322
323 $boxes[ $key ] = new Box( $post );
324 }
325 }
326
327 return $boxes;
328 }
329
330 }
331
332
333