PluginProbe
Boxzilla – WordPress Popup Builder / 3.2.23
Boxzilla – WordPress Popup Builder v3.2.23
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.23, at src/class-loader.php

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