| 1 |
<?php |
| 2 |
namespace Elementor; |
| 3 |
|
| 4 |
use Elementor\Core\Files\Assets\Svg\Svg_Handler; |
| 5 |
|
| 6 |
if ( ! defined( 'ABSPATH' ) ) { |
| 7 |
exit; // Exit if accessed directly. |
| 8 |
} |
| 9 |
|
| 10 |
/** |
| 11 |
* Elementor icons manager. |
| 12 |
* |
| 13 |
* Elementor icons manager handler class |
| 14 |
* |
| 15 |
* @since 2.4.0 |
| 16 |
*/ |
| 17 |
class Icons_Manager { |
| 18 |
|
| 19 |
const NEEDS_UPDATE_OPTION = 'icon_manager_needs_update'; |
| 20 |
/** |
| 21 |
* Tabs. |
| 22 |
* |
| 23 |
* Holds the list of all the tabs. |
| 24 |
* |
| 25 |
* @access private |
| 26 |
* @static |
| 27 |
* @since 2.4.0 |
| 28 |
* @var array |
| 29 |
*/ |
| 30 |
private static $tabs; |
| 31 |
|
| 32 |
private static function get_needs_upgrade_option() { |
| 33 |
return get_option( 'elementor_' . self::NEEDS_UPDATE_OPTION, null ); |
| 34 |
} |
| 35 |
|
| 36 |
/** |
| 37 |
* register styles |
| 38 |
* |
| 39 |
* Used to register all icon types stylesheets so they could be enqueued later by widgets |
| 40 |
*/ |
| 41 |
public function register_styles() { |
| 42 |
$config = self::get_icon_manager_tabs_config(); |
| 43 |
|
| 44 |
$shared_styles = []; |
| 45 |
|
| 46 |
foreach ( $config as $type => $icon_type ) { |
| 47 |
if ( ! isset( $icon_type['url'] ) ) { |
| 48 |
continue; |
| 49 |
} |
| 50 |
$dependencies = []; |
| 51 |
if ( ! empty( $icon_type['enqueue'] ) ) { |
| 52 |
foreach ( (array) $icon_type['enqueue'] as $font_css_url ) { |
| 53 |
if ( ! in_array( $font_css_url, array_keys( $shared_styles ) ) ) { |
| 54 |
$style_handle = 'elementor-icons-shared-' . count( $shared_styles ); |
| 55 |
wp_register_style( |
| 56 |
$style_handle, |
| 57 |
$font_css_url, |
| 58 |
[], |
| 59 |
$icon_type['ver'] |
| 60 |
); |
| 61 |
$shared_styles[ $font_css_url ] = $style_handle; |
| 62 |
} |
| 63 |
$dependencies[] = $shared_styles[ $font_css_url ]; |
| 64 |
} |
| 65 |
} |
| 66 |
wp_register_style( |
| 67 |
'elementor-icons-' . $icon_type['name'], |
| 68 |
$icon_type['url'], |
| 69 |
$dependencies, |
| 70 |
$icon_type['ver'] |
| 71 |
); |
| 72 |
} |
| 73 |
} |
| 74 |
|
| 75 |
/** |
| 76 |
* Init Tabs |
| 77 |
* |
| 78 |
* Initiate Icon Manager Tabs. |
| 79 |
* |
| 80 |
* @access private |
| 81 |
* @static |
| 82 |
* @since 2.4.0 |
| 83 |
*/ |
| 84 |
private static function init_tabs() { |
| 85 |
self::$tabs = apply_filters( 'elementor/icons_manager/native', [ |
| 86 |
'fa-regular' => [ |
| 87 |
'name' => 'fa-regular', |
| 88 |
'label' => __( 'Font Awesome - Regular', 'elementor' ), |
| 89 |
'url' => self::get_fa_asset_url( 'regular' ), |
| 90 |
'enqueue' => [ self::get_fa_asset_url( 'fontawesome' ) ], |
| 91 |
'prefix' => 'fa-', |
| 92 |
'displayPrefix' => 'far', |
| 93 |
'labelIcon' => 'fab fa-font-awesome-alt', |
| 94 |
'ver' => '5.15.1', |
| 95 |
'fetchJson' => self::get_fa_asset_url( 'regular', 'js', false ), |
| 96 |
'native' => true, |
| 97 |
], |
| 98 |
'fa-solid' => [ |
| 99 |
'name' => 'fa-solid', |
| 100 |
'label' => __( 'Font Awesome - Solid', 'elementor' ), |
| 101 |
'url' => self::get_fa_asset_url( 'solid' ), |
| 102 |
'enqueue' => [ self::get_fa_asset_url( 'fontawesome' ) ], |
| 103 |
'prefix' => 'fa-', |
| 104 |
'displayPrefix' => 'fas', |
| 105 |
'labelIcon' => 'fab fa-font-awesome', |
| 106 |
'ver' => '5.15.1', |
| 107 |
'fetchJson' => self::get_fa_asset_url( 'solid', 'js', false ), |
| 108 |
'native' => true, |
| 109 |
], |
| 110 |
'fa-brands' => [ |
| 111 |
'name' => 'fa-brands', |
| 112 |
'label' => __( 'Font Awesome - Brands', 'elementor' ), |
| 113 |
'url' => self::get_fa_asset_url( 'brands' ), |
| 114 |
'enqueue' => [ self::get_fa_asset_url( 'fontawesome' ) ], |
| 115 |
'prefix' => 'fa-', |
| 116 |
'displayPrefix' => 'fab', |
| 117 |
'labelIcon' => 'fab fa-font-awesome-flag', |
| 118 |
'ver' => '5.15.1', |
| 119 |
'fetchJson' => self::get_fa_asset_url( 'brands', 'js', false ), |
| 120 |
'native' => true, |
| 121 |
], |
| 122 |
] ); |
| 123 |
} |
| 124 |
|
| 125 |
/** |
| 126 |
* Get Icon Manager Tabs |
| 127 |
* @return array |
| 128 |
*/ |
| 129 |
public static function get_icon_manager_tabs() { |
| 130 |
if ( ! self::$tabs ) { |
| 131 |
self::init_tabs(); |
| 132 |
} |
| 133 |
$additional_tabs = apply_filters( 'elementor/icons_manager/additional_tabs', [] ); |
| 134 |
return array_merge( self::$tabs, $additional_tabs ); |
| 135 |
} |
| 136 |
|
| 137 |
public static function enqueue_shim() { |
| 138 |
wp_enqueue_script( |
| 139 |
'font-awesome-4-shim', |
| 140 |
self::get_fa_asset_url( 'v4-shims', 'js' ), |
| 141 |
[], |
| 142 |
ELEMENTOR_VERSION |
| 143 |
); |
| 144 |
// Make sure that the CSS in the 'all' file does not override FA Pro's CSS |
| 145 |
if ( ! wp_script_is( 'font-awesome-pro' ) ) { |
| 146 |
wp_enqueue_style( |
| 147 |
'font-awesome-5-all', |
| 148 |
self::get_fa_asset_url( 'all' ), |
| 149 |
[], |
| 150 |
ELEMENTOR_VERSION |
| 151 |
); |
| 152 |
} |
| 153 |
wp_enqueue_style( |
| 154 |
'font-awesome-4-shim', |
| 155 |
self::get_fa_asset_url( 'v4-shims' ), |
| 156 |
[], |
| 157 |
ELEMENTOR_VERSION |
| 158 |
); |
| 159 |
} |
| 160 |
|
| 161 |
private static function get_fa_asset_url( $filename, $ext_type = 'css', $add_suffix = true ) { |
| 162 |
static $is_test_mode = null; |
| 163 |
if ( null === $is_test_mode ) { |
| 164 |
$is_test_mode = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || defined( 'ELEMENTOR_TESTS' ) && ELEMENTOR_TESTS; |
| 165 |
} |
| 166 |
$url = ELEMENTOR_ASSETS_URL . 'lib/font-awesome/' . $ext_type . '/' . $filename; |
| 167 |
if ( ! $is_test_mode && $add_suffix ) { |
| 168 |
$url .= '.min'; |
| 169 |
} |
| 170 |
return $url . '.' . $ext_type; |
| 171 |
} |
| 172 |
|
| 173 |
public static function get_icon_manager_tabs_config() { |
| 174 |
$tabs = [ |
| 175 |
'all' => [ |
| 176 |
'name' => 'all', |
| 177 |
'label' => __( 'All Icons', 'elementor' ), |
| 178 |
'labelIcon' => 'eicon-filter', |
| 179 |
'native' => true, |
| 180 |
], |
| 181 |
]; |
| 182 |
|
| 183 |
return array_values( array_merge( $tabs, self::get_icon_manager_tabs() ) ); |
| 184 |
} |
| 185 |
|
| 186 |
private static function render_svg_icon( $value ) { |
| 187 |
if ( ! isset( $value['id'] ) ) { |
| 188 |
return ''; |
| 189 |
} |
| 190 |
|
| 191 |
return Svg_Handler::get_inline_svg( $value['id'] ); |
| 192 |
} |
| 193 |
|
| 194 |
private static function render_icon_html( $icon, $attributes = [], $tag = 'i' ) { |
| 195 |
$icon_types = self::get_icon_manager_tabs(); |
| 196 |
if ( isset( $icon_types[ $icon['library'] ]['render_callback'] ) && is_callable( $icon_types[ $icon['library'] ]['render_callback'] ) ) { |
| 197 |
return call_user_func_array( $icon_types[ $icon['library'] ]['render_callback'], [ $icon, $attributes, $tag ] ); |
| 198 |
} |
| 199 |
|
| 200 |
if ( empty( $attributes['class'] ) ) { |
| 201 |
$attributes['class'] = $icon['value']; |
| 202 |
} else { |
| 203 |
if ( is_array( $attributes['class'] ) ) { |
| 204 |
$attributes['class'][] = $icon['value']; |
| 205 |
} else { |
| 206 |
$attributes['class'] .= ' ' . $icon['value']; |
| 207 |
} |
| 208 |
} |
| 209 |
return '<' . $tag . ' ' . Utils::render_html_attributes( $attributes ) . '></' . $tag . '>'; |
| 210 |
} |
| 211 |
|
| 212 |
/** |
| 213 |
* Render Icon |
| 214 |
* |
| 215 |
* Used to render Icon for \Elementor\Controls_Manager::ICONS |
| 216 |
* @param array $icon Icon Type, Icon value |
| 217 |
* @param array $attributes Icon HTML Attributes |
| 218 |
* @param string $tag Icon HTML tag, defaults to <i> |
| 219 |
* |
| 220 |
* @return mixed|string |
| 221 |
*/ |
| 222 |
public static function render_icon( $icon, $attributes = [], $tag = 'i' ) { |
| 223 |
if ( empty( $icon['library'] ) ) { |
| 224 |
return false; |
| 225 |
} |
| 226 |
$output = ''; |
| 227 |
// handler SVG Icon |
| 228 |
if ( 'svg' === $icon['library'] ) { |
| 229 |
$output = self::render_svg_icon( $icon['value'] ); |
| 230 |
} else { |
| 231 |
$output = self::render_icon_html( $icon, $attributes, $tag ); |
| 232 |
} |
| 233 |
|
| 234 |
echo $output; |
| 235 |
|
| 236 |
return true; |
| 237 |
} |
| 238 |
|
| 239 |
/** |
| 240 |
* Font Awesome 4 to font Awesome 5 Value Migration |
| 241 |
* |
| 242 |
* used to convert string value of Icon control to array value of Icons control |
| 243 |
* ex: 'fa fa-star' => [ 'value' => 'fas fa-star', 'library' => 'fa-solid' ] |
| 244 |
* |
| 245 |
* @param $value |
| 246 |
* |
| 247 |
* @return array |
| 248 |
*/ |
| 249 |
public static function fa4_to_fa5_value_migration( $value ) { |
| 250 |
static $migration_dictionary = false; |
| 251 |
if ( '' === $value ) { |
| 252 |
return [ |
| 253 |
'value' => '', |
| 254 |
'library' => '', |
| 255 |
]; |
| 256 |
} |
| 257 |
if ( false === $migration_dictionary ) { |
| 258 |
$migration_dictionary = json_decode( file_get_contents( ELEMENTOR_ASSETS_PATH . 'lib/font-awesome/migration/mapping.js' ), true ); |
| 259 |
} |
| 260 |
if ( isset( $migration_dictionary[ $value ] ) ) { |
| 261 |
return $migration_dictionary[ $value ]; |
| 262 |
} |
| 263 |
|
| 264 |
return [ |
| 265 |
'value' => 'fas ' . str_replace( 'fa ', '', $value ), |
| 266 |
'library' => 'fa-solid', |
| 267 |
]; |
| 268 |
} |
| 269 |
|
| 270 |
/** |
| 271 |
* on_import_migration |
| 272 |
* @param array $element settings array |
| 273 |
* @param string $old_control old control id |
| 274 |
* @param string $new_control new control id |
| 275 |
* @param bool $remove_old boolean weather to remove old control or not |
| 276 |
* |
| 277 |
* @return array |
| 278 |
*/ |
| 279 |
public static function on_import_migration( array $element, $old_control = '', $new_control = '', $remove_old = false ) { |
| 280 |
|
| 281 |
if ( ! isset( $element['settings'][ $old_control ] ) || isset( $element['settings'][ $new_control ] ) ) { |
| 282 |
return $element; |
| 283 |
} |
| 284 |
|
| 285 |
// Case when old value is saved as empty string |
| 286 |
$new_value = [ |
| 287 |
'value' => '', |
| 288 |
'library' => '', |
| 289 |
]; |
| 290 |
|
| 291 |
// Case when old value needs migration |
| 292 |
if ( ! empty( $element['settings'][ $old_control ] ) && ! self::is_migration_allowed() ) { |
| 293 |
$new_value = self::fa4_to_fa5_value_migration( $element['settings'][ $old_control ] ); |
| 294 |
} |
| 295 |
|
| 296 |
$element['settings'][ $new_control ] = $new_value; |
| 297 |
|
| 298 |
//remove old value |
| 299 |
if ( $remove_old ) { |
| 300 |
unset( $element['settings'][ $old_control ] ); |
| 301 |
} |
| 302 |
|
| 303 |
return $element; |
| 304 |
} |
| 305 |
|
| 306 |
/** |
| 307 |
* is_migration_allowed |
| 308 |
* @return bool |
| 309 |
*/ |
| 310 |
public static function is_migration_allowed() { |
| 311 |
static $migration_allowed = false; |
| 312 |
if ( false === $migration_allowed ) { |
| 313 |
$migration_allowed = null === self::get_needs_upgrade_option(); |
| 314 |
|
| 315 |
/** |
| 316 |
* allowed to filter migration allowed |
| 317 |
*/ |
| 318 |
$migration_allowed = apply_filters( 'elementor/icons_manager/migration_allowed', $migration_allowed ); |
| 319 |
} |
| 320 |
return $migration_allowed; |
| 321 |
} |
| 322 |
|
| 323 |
/** |
| 324 |
* Register_Admin Settings |
| 325 |
* |
| 326 |
* adds Font Awesome migration / update admin settings |
| 327 |
* @param Settings $settings |
| 328 |
*/ |
| 329 |
public function register_admin_settings( Settings $settings ) { |
| 330 |
$settings->add_field( |
| 331 |
Settings::TAB_ADVANCED, |
| 332 |
Settings::TAB_ADVANCED, |
| 333 |
'load_fa4_shim', |
| 334 |
[ |
| 335 |
'label' => __( 'Load Font Awesome 4 Support', 'elementor' ), |
| 336 |
'field_args' => [ |
| 337 |
'type' => 'select', |
| 338 |
'std' => 1, |
| 339 |
'options' => [ |
| 340 |
'' => __( 'No', 'elementor' ), |
| 341 |
'yes' => __( 'Yes', 'elementor' ), |
| 342 |
], |
| 343 |
'desc' => __( 'Font Awesome 4 support script (shim.js) is a script that makes sure all previously selected Font Awesome 4 icons are displayed correctly while using Font Awesome 5 library.', 'elementor' ), |
| 344 |
], |
| 345 |
] |
| 346 |
); |
| 347 |
} |
| 348 |
|
| 349 |
public function register_admin_tools_settings( Tools $settings ) { |
| 350 |
$settings->add_tab( 'fontawesome4_migration', [ 'label' => __( 'Font Awesome Upgrade', 'elementor' ) ] ); |
| 351 |
|
| 352 |
$settings->add_section( 'fontawesome4_migration', 'fontawesome4_migration', [ |
| 353 |
'callback' => function() { |
| 354 |
echo '<h2>' . esc_html__( 'Font Awesome Upgrade', 'elementor' ) . '</h2>'; |
| 355 |
echo '<p>' . |
| 356 |
__( 'Access 1,500+ amazing Font Awesome 5 icons and enjoy faster performance and design flexibility.', 'elementor' ) . '<br>' . |
| 357 |
__( 'By upgrading, whenever you edit a page containing a Font Awesome 4 icon, Elementor will convert it to the new Font Awesome 5 icon.', 'elementor' ) . |
| 358 |
'</p><p><strong>' . |
| 359 |
__( 'Please note that the upgrade process may cause some of the previously used Font Awesome 4 icons to look a bit different due to minor design changes made by Font Awesome.', 'elementor' ) . |
| 360 |
'</strong></p><p>' . |
| 361 |
__( 'The upgrade process includes a database update', 'elementor' ) . ' - ' . |
| 362 |
__( 'We highly recommend backing up your database before performing this upgrade.', 'elementor' ) . |
| 363 |
'</p>' . |
| 364 |
__( 'This action is not reversible and cannot be undone by rolling back to previous versions.', 'elementor' ) . |
| 365 |
'</p>'; |
| 366 |
}, |
| 367 |
'fields' => [ |
| 368 |
[ |
| 369 |
'label' => __( 'Font Awesome Upgrade', 'elementor' ), |
| 370 |
'field_args' => [ |
| 371 |
'type' => 'raw_html', |
| 372 |
'html' => sprintf( '<span data-action="%s" data-_nonce="%s" class="button" id="elementor_upgrade_fa_button">%s</span>', |
| 373 |
self::NEEDS_UPDATE_OPTION . '_upgrade', |
| 374 |
wp_create_nonce( self::NEEDS_UPDATE_OPTION ), |
| 375 |
__( 'Upgrade To Font Awesome 5', 'elementor' ) |
| 376 |
), |
| 377 |
], |
| 378 |
], |
| 379 |
], |
| 380 |
] ); |
| 381 |
} |
| 382 |
|
| 383 |
/** |
| 384 |
* Ajax Upgrade to FontAwesome 5 |
| 385 |
*/ |
| 386 |
public function ajax_upgrade_to_fa5() { |
| 387 |
check_ajax_referer( self::NEEDS_UPDATE_OPTION, '_nonce' ); |
| 388 |
|
| 389 |
delete_option( 'elementor_' . self::NEEDS_UPDATE_OPTION ); |
| 390 |
|
| 391 |
wp_send_json_success( [ 'message' => '<p>' . __( 'Hurray! The upgrade process to Font Awesome 5 was completed successfully.', 'elementor' ) . '</p>' ] ); |
| 392 |
} |
| 393 |
|
| 394 |
/** |
| 395 |
* Add Update Needed Flag |
| 396 |
* @param array $settings |
| 397 |
* |
| 398 |
* @return array; |
| 399 |
*/ |
| 400 |
public function add_update_needed_flag( $settings ) { |
| 401 |
$settings['icons_update_needed'] = true; |
| 402 |
return $settings; |
| 403 |
} |
| 404 |
|
| 405 |
public function enqueue_fontawesome_css() { |
| 406 |
if ( ! self::is_migration_allowed() ) { |
| 407 |
wp_enqueue_style( 'font-awesome' ); |
| 408 |
} else { |
| 409 |
$current_filter = current_filter(); |
| 410 |
$load_shim = get_option( 'elementor_load_fa4_shim', false ); |
| 411 |
if ( 'elementor/editor/after_enqueue_styles' === $current_filter ) { |
| 412 |
self::enqueue_shim(); |
| 413 |
} else if ( 'yes' === $load_shim ) { |
| 414 |
self::enqueue_shim(); |
| 415 |
} |
| 416 |
} |
| 417 |
} |
| 418 |
|
| 419 |
/** |
| 420 |
* @deprecated 3.1.0 |
| 421 |
*/ |
| 422 |
public function add_admin_strings() { |
| 423 |
Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0' ); |
| 424 |
|
| 425 |
return []; |
| 426 |
} |
| 427 |
|
| 428 |
/** |
| 429 |
* @since 3.0.0 |
| 430 |
* @deprecated 3.0.0 |
| 431 |
*/ |
| 432 |
public function register_ajax_actions() { |
| 433 |
_deprecated_function( __METHOD__, '3.0.0' ); |
| 434 |
} |
| 435 |
|
| 436 |
/** |
| 437 |
* @since 3.0.0. |
| 438 |
* @deprecated 3.0.0 |
| 439 |
*/ |
| 440 |
public function ajax_enable_svg_uploads() { |
| 441 |
_deprecated_function( __METHOD__, '3.0.0' ); |
| 442 |
} |
| 443 |
|
| 444 |
/** |
| 445 |
* Icons Manager constructor |
| 446 |
*/ |
| 447 |
public function __construct() { |
| 448 |
if ( is_admin() ) { |
| 449 |
// @todo: remove once we deprecate fa4 |
| 450 |
add_action( 'elementor/admin/after_create_settings/' . Settings::PAGE_ID, [ $this, 'register_admin_settings' ], 100 ); |
| 451 |
} |
| 452 |
|
| 453 |
add_action( 'elementor/editor/after_enqueue_styles', [ $this, 'enqueue_fontawesome_css' ] ); |
| 454 |
add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'enqueue_fontawesome_css' ] ); |
| 455 |
|
| 456 |
add_action( 'elementor/frontend/after_register_styles', [ $this, 'register_styles' ] ); |
| 457 |
|
| 458 |
if ( ! self::is_migration_allowed() ) { |
| 459 |
add_filter( 'elementor/editor/localize_settings', [ $this, 'add_update_needed_flag' ] ); |
| 460 |
add_action( 'elementor/admin/after_create_settings/' . Tools::PAGE_ID, [ $this, 'register_admin_tools_settings' ], 100 ); |
| 461 |
|
| 462 |
if ( ! empty( $_POST ) ) { // phpcs:ignore -- nonce validation done in callback |
| 463 |
add_action( 'wp_ajax_' . self::NEEDS_UPDATE_OPTION . '_upgrade', [ $this, 'ajax_upgrade_to_fa5' ] ); |
| 464 |
} |
| 465 |
} |
| 466 |
} |
| 467 |
} |
| 468 |
|