PluginProbe
Elementor Website Builder – more than just a page builder / 3.4.0-dev9
Elementor Website Builder – more than just a page builder v3.4.0-dev9
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / breakpoints / manager.php

manager.php in Elementor Website Builder – more than just a page builder 3.4.0-dev9, at core/breakpoints/manager.php

457 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\Breakpoints;
3
4 use Elementor\Core\Base\Module;
5 use Elementor\Core\Kits\Documents\Tabs\Settings_Layout;
6 use Elementor\Core\Responsive\Files\Frontend;
7 use Elementor\Plugin;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 class Manager extends Module {
14
15 const BREAKPOINT_SETTING_PREFIX = 'viewport_';
16 const BREAKPOINT_KEY_MOBILE = 'mobile';
17 const BREAKPOINT_KEY_MOBILE_EXTRA = 'mobile_extra';
18 const BREAKPOINT_KEY_TABLET = 'tablet';
19 const BREAKPOINT_KEY_TABLET_EXTRA = 'tablet_extra';
20 const BREAKPOINT_KEY_LAPTOP = 'laptop';
21 const BREAKPOINT_KEY_WIDESCREEN = 'widescreen';
22
23 /**
24 * Breakpoints
25 *
26 * An array containing instances of the all of the system's available breakpoints.
27 *
28 * @since 3.2.0
29 * @access private
30 *
31 * @var Breakpoint[]
32 */
33 private $breakpoints;
34
35 /**
36 * Active Breakpoints
37 *
38 * An array containing instances of the enabled breakpoints.
39 *
40 * @since 3.2.0
41 * @access private
42 *
43 * @var Breakpoint[]
44 */
45 private $active_breakpoints;
46
47 /**
48 * Responsive Control Duplication Mode.
49 *
50 * Determines the current responsive control generation mode.
51 * Options are:
52 * -- 'on': Responsive controls are duplicated in `add_responsive_control()`.
53 * -- 'off': Responsive controls are NOT duplicated in `add_responsive_control()`.
54 * -- 'dynamic': Responsive controls are only duplicated if their config contains `'dynamic' => 'active' => true`.
55 *
56 * When generating Post CSS, the mode is set to 'on'. When generating Dynamic CSS, the mode is set to 'dynamic'.
57 *
58 * default value is 'off'.
59 *
60 * @since 3.4.0
61 * @access private
62 *
63 * @var string
64 */
65 private $responsive_control_duplication_mode = 'off';
66
67 private $icons_map;
68
69 public function get_name() {
70 return 'breakpoints';
71 }
72
73 /**
74 * Get Breakpoints
75 *
76 * Retrieve the array containing instances of all breakpoints existing in the system, or a single breakpoint if a
77 * name is passed.
78 *
79 * @since 3.2.0
80 *
81 * @param $breakpoint_name
82 * @return Breakpoint[]|Breakpoint
83 */
84 public function get_breakpoints( $breakpoint_name = null ) {
85 if ( ! $this->breakpoints ) {
86 $this->init_breakpoints();
87 }
88 return self::get_items( $this->breakpoints, $breakpoint_name );
89 }
90
91 /**
92 * Get Active Breakpoints
93 *
94 * Retrieve the array of --enabled-- breakpoints, or a single breakpoint if a name is passed.
95 *
96 * @since 3.2.0
97 *
98 * @param string|null $breakpoint_name
99 * @return Breakpoint[]|Breakpoint
100 */
101 public function get_active_breakpoints( $breakpoint_name = null ) {
102 if ( ! $this->active_breakpoints ) {
103 $this->init_active_breakpoints();
104 }
105
106 return self::get_items( $this->active_breakpoints, $breakpoint_name );
107 }
108
109 /** Has Custom Breakpoints
110 *
111 * Checks whether there are currently custom breakpoints saved in the database.
112 * Returns true if there are breakpoint values saved in the active kit.
113 *
114 * @since 3.2.0
115 *
116 * @return boolean
117 */
118 public function has_custom_breakpoints() {
119 $breakpoints = $this->get_breakpoints();
120
121 foreach ( $breakpoints as $breakpoint ) {
122 /** @var Breakpoint $breakpoint */
123 if ( $breakpoint->is_custom() ) {
124 return true;
125 }
126 }
127
128 return false;
129 }
130
131 /**
132 * Get Device Min Breakpoint
133 *
134 * For a given device, return the minimum possible breakpoint. Except for the cases of mobile and widescreen
135 * devices, A device's min breakpoint is determined by the previous device's max breakpoint + 1px.
136 *
137 * @since 3.2.0
138 *
139 * @param string $device_name
140 * @return int the min breakpoint of the passed device
141 */
142 public function get_device_min_breakpoint( $device_name ) {
143 if ( 'desktop' === $device_name ) {
144 return $this->get_desktop_min_point();
145 }
146
147 $active_breakpoints = $this->get_active_breakpoints();
148 $current_device_breakpoint = $active_breakpoints[ $device_name ];
149
150 // Since this method is called multiple times, usage of class variables is to memory and processing time.
151 // Get only the keys for active breakpoints.
152 $breakpoint_keys = array_keys( $active_breakpoints );
153
154 if ( $breakpoint_keys[0] === $device_name ) {
155 // For the lowest breakpoint, the min point is always 320.
156 $min_breakpoint = 320;
157 } elseif ( 'min' === $current_device_breakpoint->get_direction() ) {
158 // 'min-width' breakpoints only have a minimum point. The breakpoint value itself the device min point.
159 $min_breakpoint = $current_device_breakpoint->get_value();
160 } else {
161 // This block handles all other devices.
162 $device_name_index = array_search( $device_name, $breakpoint_keys, true );
163
164 $previous_index = $device_name_index - 1;
165 $previous_breakpoint_key = $breakpoint_keys[ $previous_index ];
166 /** @var Breakpoint $previous_breakpoint */
167 $previous_breakpoint = $active_breakpoints[ $previous_breakpoint_key ];
168
169 $min_breakpoint = $previous_breakpoint->get_value() + 1;
170 }
171
172 return $min_breakpoint;
173 }
174
175 /**
176 * Get Desktop Min Breakpoint
177 *
178 * Returns the minimum possible breakpoint for the default (desktop) device.
179 *
180 * @since 3.2.0
181 *
182 * @return int the min breakpoint of the passed device
183 */
184 public function get_desktop_min_point() {
185 $active_breakpoints = $this->get_active_breakpoints();
186 $desktop_previous_device = $this->get_desktop_previous_device_key();
187
188 return $active_breakpoints[ $desktop_previous_device ]->get_value() + 1;
189 }
190
191 public function refresh() {
192 $this->init_breakpoints();
193 $this->init_active_breakpoints();
194 }
195
196 /**
197 * Get Responsive Icons Classes Map
198 *
199 * If a $device parameter is passed, this method retrieves the device's icon class list (the ones attached to the `<i>`
200 * element). If no parameter is passed, it returns an array of devices containing each device's icon class list.
201 *
202 * This method was created because 'mobile_extra' and 'tablet_extra' breakpoint icons need to be tilted by 90
203 * degrees, and this tilt is achieved in CSS via the class `eicon-tilted`.
204 *
205 * @since 3.4.0
206 *
207 * @return array|string
208 */
209 public function get_responsive_icons_classes_map( $device = null ) {
210 if ( ! $this->icons_map ) {
211 $this->icons_map = [
212 'mobile' => 'eicon-device-mobile',
213 'mobile_extra' => 'eicon-device-mobile eicon-tilted',
214 'tablet' => 'eicon-device-tablet',
215 'tablet_extra' => 'eicon-device-tablet eicon-tilted',
216 'laptop' => 'eicon-device-laptop',
217 'desktop' => 'eicon-device-desktop',
218 'widescreen' => 'eicon-device-wide',
219 ];
220 }
221
222 return self::get_items( $this->icons_map, $device );
223 }
224
225 /**
226 * Get Default Config
227 *
228 * Retrieve the default breakpoints config array. The 'selector' property is used for CSS generation (the
229 * Stylesheet::add_device() method).
230 *
231 * @return array
232 */
233 public static function get_default_config() {
234 return [
235 self::BREAKPOINT_KEY_MOBILE => [
236 'label' => esc_html__( 'Mobile', 'elementor' ),
237 'default_value' => 767,
238 'direction' => 'max',
239 ],
240 self::BREAKPOINT_KEY_MOBILE_EXTRA => [
241 'label' => esc_html__( 'Mobile Extra', 'elementor' ),
242 'default_value' => 880,
243 'direction' => 'max',
244 ],
245 self::BREAKPOINT_KEY_TABLET => [
246 'label' => esc_html__( 'Tablet', 'elementor' ),
247 'default_value' => 1024,
248 'direction' => 'max',
249 ],
250 self::BREAKPOINT_KEY_TABLET_EXTRA => [
251 'label' => esc_html__( 'Tablet Extra', 'elementor' ),
252 'default_value' => 1200,
253 'direction' => 'max',
254 ],
255 self::BREAKPOINT_KEY_LAPTOP => [
256 'label' => esc_html__( 'Laptop', 'elementor' ),
257 'default_value' => 1366,
258 'direction' => 'max',
259 ],
260 self::BREAKPOINT_KEY_WIDESCREEN => [
261 'label' => esc_html__( 'Widescreen', 'elementor' ),
262 'default_value' => 2400,
263 'direction' => 'min',
264 ],
265 ];
266 }
267
268 /**
269 * Get Breakpoints Config
270 *
271 * Iterates over an array of all of the system's breakpoints (both active and inactive), queries each breakpoint's
272 * class instance, and generates an array containing data on each breakpoint: its label, current value, direction
273 * ('min'/'max') and whether it is enabled or not.
274 *
275 * @return array
276 */
277 public function get_breakpoints_config() {
278 $breakpoints = $this->get_breakpoints();
279
280 $config = [];
281
282 foreach ( $breakpoints as $breakpoint_name => $breakpoint ) {
283 $config[ $breakpoint_name ] = [
284 'label' => $breakpoint->get_label(),
285 'value' => $breakpoint->get_value(),
286 'default_value' => $breakpoint->get_default_value(),
287 'direction' => $breakpoint->get_direction(),
288 'is_enabled' => $breakpoint->is_enabled(),
289 ];
290 }
291
292 return $config;
293 }
294
295 /**
296 * Get Responsive Control Duplication Mode
297 *
298 * Retrieve the value of the $responsive_control_duplication_mode private class variable.
299 * See the variable's PHPDoc for details.
300 *
301 * @since 3.4.0
302 * @access public
303 */
304 public function get_responsive_control_duplication_mode() {
305 return $this->responsive_control_duplication_mode;
306 }
307
308 /**
309 * Set Responsive Control Duplication Mode
310 *
311 * Sets the value of the $responsive_control_duplication_mode private class variable.
312 * See the variable's PHPDoc for details.
313 *
314 * @since 3.4.0
315 *
316 * @access public
317 * @param string $mode
318 */
319 public function set_responsive_control_duplication_mode( $mode ) {
320 $this->responsive_control_duplication_mode = $mode;
321 }
322
323 /**
324 * Get Stylesheet Templates Path
325 *
326 * @since 3.2.0
327 * @access public
328 * @static
329 */
330 public static function get_stylesheet_templates_path() {
331 return ELEMENTOR_ASSETS_PATH . 'css/templates/';
332 }
333
334 /**
335 * Compile Stylesheet Templates
336 *
337 * @since 3.2.0
338 * @access public
339 * @static
340 */
341 public static function compile_stylesheet_templates() {
342 foreach ( self::get_stylesheet_templates() as $file_name => $template_path ) {
343 $file = new Frontend( $file_name, $template_path );
344
345 $file->update();
346 }
347 }
348
349 /**
350 * Init Breakpoints
351 *
352 * Creates the breakpoints array, containing instances of each breakpoint. Returns an array of ALL breakpoints,
353 * both enabled and disabled.
354 *
355 * @since 3.2.0
356 */
357 private function init_breakpoints() {
358 $breakpoints = [];
359
360 $setting_prefix = self::BREAKPOINT_SETTING_PREFIX;
361
362 $active_breakpoint_keys = [
363 $setting_prefix . self::BREAKPOINT_KEY_MOBILE,
364 $setting_prefix . self::BREAKPOINT_KEY_TABLET,
365 ];
366
367 if ( Plugin::$instance->experiments->is_feature_active( 'additional_custom_breakpoints' ) ) {
368 $kit_active_id = Plugin::$instance->kits_manager->get_active_id();
369 // Get the breakpoint settings saved in the kit directly from the DB to avoid initializing the kit too early.
370 $raw_kit_settings = get_post_meta( $kit_active_id, '_elementor_page_settings', true );
371
372 // If there is an existing kit with an active breakpoints value saved, use it.
373 if ( isset( $raw_kit_settings[ Settings_Layout::ACTIVE_BREAKPOINTS_CONTROL_ID ] ) ) {
374 $active_breakpoint_keys = $raw_kit_settings[ Settings_Layout::ACTIVE_BREAKPOINTS_CONTROL_ID ];
375 }
376 }
377
378 $default_config = self::get_default_config();
379
380 foreach ( $default_config as $breakpoint_name => $breakpoint_config ) {
381 $args = [ 'name' => $breakpoint_name ] + $breakpoint_config;
382
383 // Make sure the two default breakpoints (mobile, tablet) are always enabled.
384 if ( self::BREAKPOINT_KEY_MOBILE === $breakpoint_name || self::BREAKPOINT_KEY_TABLET === $breakpoint_name ) {
385 // Make sure the default Mobile and Tablet breakpoints are always enabled.
386 $args['is_enabled'] = true;
387 } else {
388 // If the breakpoint is in the active breakpoints array, make sure it's instantiated as enabled.
389 $args['is_enabled'] = in_array( $setting_prefix . $breakpoint_name, $active_breakpoint_keys, true );
390 }
391
392 $breakpoints[ $breakpoint_name ] = new Breakpoint( $args );
393 }
394
395 $this->breakpoints = $breakpoints;
396 }
397
398 /**
399 * Init Active Breakpoints
400 *
401 * Create/Refresh the array of --enabled-- breakpoints.
402 *
403 * @since 3.2.0
404 */
405 private function init_active_breakpoints() {
406 $this->active_breakpoints = array_filter( $this->get_breakpoints(), function( $breakpoint ) {
407 /** @var Breakpoint $breakpoint */
408 return $breakpoint->is_enabled();
409 } );
410 }
411
412 private function get_desktop_previous_device_key() {
413 $config_array_keys = array_keys( $this->get_active_breakpoints() );
414 $num_of_devices = count( $config_array_keys );
415
416 // If the widescreen breakpoint is active, the device that's previous to desktop is the last one before
417 // widescreen.
418 if ( self::BREAKPOINT_KEY_WIDESCREEN === $config_array_keys[ $num_of_devices - 1 ] ) {
419 $desktop_previous_device = $config_array_keys[ $num_of_devices - 2 ];
420 } else {
421 // If the widescreen breakpoint isn't active, we just take the last device returned by the config.
422 $desktop_previous_device = $config_array_keys[ $num_of_devices - 1 ];
423 }
424
425 return $desktop_previous_device;
426 }
427
428 /**
429 * Get Stylesheet Templates
430 *
431 * @since 3.2.0
432 * @access private
433 * @static
434 */
435 private static function get_stylesheet_templates() {
436 $templates_paths = glob( self::get_stylesheet_templates_path() . '*.css' );
437
438 $templates = [];
439
440 foreach ( $templates_paths as $template_path ) {
441 $file_name = 'custom-' . basename( $template_path );
442
443 $templates[ $file_name ] = $template_path;
444 }
445
446 $deprecated_hook = 'elementor/core/responsive/get_stylesheet_templates';
447 $replacement_hook = 'elementor/core/breakpoints/get_stylesheet_template';
448
449 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_hook( $deprecated_hook, '3.2.0', $replacement_hook );
450
451 // TODO: REMOVE THIS DEPRECATED HOOK IN ELEMENTOR v3.10.0/v4.0.0
452 $templates = apply_filters( $deprecated_hook, $templates );
453
454 return apply_filters( $replacement_hook, $templates );
455 }
456 }
457