balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

manager.php (15072B)


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