PluginProbe
Boxzilla – WordPress Popup Builder / 3.2.10
Boxzilla – WordPress Popup Builder v3.2.10
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.10, at src/class-loader.php

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