} $this->run_install( $this->cache_base_path ); $this->is_installed = true; wp_send_json_success(); } /** * Run Install Font Awesome library from our server. * * @since 1.8.3 * * @param string $destination Destination path. */ public function run_install( $destination ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks // WordPress assumes it's a plugin/theme and tries to get translations. We don't need that, and it breaks JS output. remove_action( 'upgrader_process_complete', [ 'Language_Pack_Upgrader', 'async_upgrade' ], 20 ); if ( ! function_exists( 'request_filesystem_credentials' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } // Create the Upgrader with our custom skin that reports errors as WP JSON. $installer = new PluginSilentUpgrader( new WP_Ajax_Upgrader_Skin() ); // The installer skin reports any errors via wp_send_json_error() with generic error messages. $installer->init(); $installer->run( [ 'package' => self::FONT_AWESOME_URL, 'destination' => $destination, ] ); } /** * Load all necessary Font Awesome assets. * * @since 1.7.9 * * @param string $view Current Form Builder view (panel). */ public function enqueues( $view ) { if ( ! $this->is_installed() ) { return; } wp_enqueue_style( 'wpforms-icon-choices-font-awesome', $this->cache_base_url . '/css/fontawesome.min.css', [], self::FONT_AWESOME_VERSION ); wp_enqueue_style( 'wpforms-icon-choices-font-awesome-brands', $this->cache_base_url . '/css/brands.min.css', [], self::FONT_AWESOME_VERSION ); wp_enqueue_style( 'wpforms-icon-choices-font-awesome-regular', $this->cache_base_url . '/css/regular.min.css', [], self::FONT_AWESOME_VERSION ); wp_enqueue_style( 'wpforms-icon-choices-font-awesome-solid', $this->cache_base_url . '/css/solid.min.css', [], self::FONT_AWESOME_VERSION ); } /** * Define additional field properties specific to Icon Choices feature. * * @since 1.7.9 * * @see WPForms_Field_Checkbox::field_properties() * @see WPForms_Field_Radio::field_properties() * @see WPForms_Field_Payment_Checkbox::field_properties() * @see WPForms_Field_Payment_Multiple::field_properties() * * @param array $properties Field properties. * @param array $field Field settings. * * @return array */ public function field_properties( $properties, $field ) { $properties['input_container']['class'][] = 'wpforms-icon-choices'; $properties['input_container']['class'][] = sanitize_html_class( 'wpforms-icon-choices-' . $field['choices_icons_style'] ); $properties['input_container']['class'][] = sanitize_html_class( 'wpforms-icon-choices-' . $field['choices_icons_size'] ); $icon_color = isset( $field['choices_icons_color'] ) ? wpforms_sanitize_hex_color( $field['choices_icons_color'] ) : ''; $icon_color = empty( $icon_color ) ? self::get_default_color() : $icon_color; $properties['input_container']['attr']['style'] = "--wpforms-icon-choices-color: {$icon_color};"; foreach ( $properties['inputs'] as $key => $inputs ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-icon-choices-item'; if ( in_array( $field['choices_icons_style'], [ 'default', 'modern', 'classic' ], true ) ) { $properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element'; } } return $properties; } /** * Display a single choice on the form front-end. * * @since 1.7.9 * * @see WPForms_Field_Checkbox::field_display() * @see WPForms_Field_Radio::field_display() * @see WPForms_Field_Payment_Checkbox::field_display() * @see WPForms_Field_Payment_Multiple::field_display() * * @param array $field Field settings. * @param array $choice Single choice item settings. * @param string $type Field input type. * @param string|null $label Custom label, used by Payment fields. */ public function field_display( $field, $choice, $type, $label = null ) { // Only Payment fields supply a custom label. if ( ! $label ) { $label = $choice['label']['text']; } if ( is_array( $choice['label']['class'] ) && wpforms_is_empty_string( $label ) ) { $choice['label']['class'][] = 'wpforms-field-label-inline-empty'; } printf( '', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $this->get_icon( $choice['icon'], $choice['icon_style'], $field['choices_icons_size'] ), esc_attr( $type ), wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ), wp_kses_post( $label ) ); } /** * Output inline CSS custom properties (vars). * * @since 1.7.9 * * @param null|array $forms Frontend forms, if available. * * @return void */ public function css_custom_properties( $forms = null ) { $hook = current_action(); // On the frontend, we need these properties only if Icon Choices is in use. if ( $hook === 'wpforms_frontend_css' && ! wpforms_has_field_setting( 'choices_icons', $forms, true ) ) { return; } $selectors = [ 'wpforms_frontend_css' => '.wpforms-container', 'admin_head' => '#wpforms-builder, .wpforms-icon-picker-container', ]; /** * Add CSS custom properties. * * @since 1.7.9 * * @param array $properties CSS custom properties using CSS syntax. */ $custom_properties = (array) apply_filters( 'wpforms_forms_icon_choices_css_custom_properties', [] ); $icon_sizes = $this->get_icon_sizes(); foreach ( $icon_sizes as $slug => $data ) { $custom_properties[ "wpforms-icon-choices-size-{$slug}" ] = $data['size'] . 'px'; } $custom_properties_css = ''; foreach ( $custom_properties as $property => $value ) { $custom_properties_css .= "--{$property}: {$value};"; } printf( '', esc_attr( $selectors[ $hook ] ), esc_html( $custom_properties_css ) ); } /** * Get available icon sizes. * * @since 1.7.9 * * @return array A list of all icon sizes. */ public function get_icon_sizes() { /** * Allow modifying the icon sizes. * * @since 1.7.9 * * @param array $icon_sizes { * Default icon sizes. * * @type string $key The icon slug. * @type array $value { * Individual icon size data. * * @type string $label Translatable label. * @type int $size The size value. * } * } * @param array $default_icon_sizes Default icon sizes for reference. */ $sizes = (array) apply_filters( 'wpforms_forms_icon_choices_get_icon_sizes', [], $this->default_icon_sizes ); return array_merge( $this->default_icon_sizes, $sizes ); } /** * Read icons metadata from disk. * * @since 1.7.9 * * @param array $strings Strings and values sent to the frontend. * @param array $form Current form. * * @return array */ public function get_strings( $strings, $form ) { $strings['continue'] = esc_html__( 'Continue', 'wpforms-lite' ); $strings['done'] = esc_html__( 'Done!', 'wpforms-lite' ); $strings['uh_oh'] = esc_html__( 'Uh oh!', 'wpforms-lite' ); $strings['icon_choices'] = [ 'is_installed' => false, 'is_active' => $this->is_active(), 'default_icon' => self::DEFAULT_ICON, 'default_icon_style' => self::DEFAULT_ICON_STYLE, 'default_color' => self::get_default_color(), 'icons' => [], 'icons_per_page' => self::DEFAULT_ICONS_PER_PAGE, 'strings' => [ 'install_prompt_content' => esc_html__( 'In order to use the Icon Choices feature, an icon library must be downloaded and installed. It\'s quick and easy, and you\'ll only have to do this once.', 'wpforms-lite' ), 'install_title' => esc_html__( 'Installing Icon Library', 'wpforms-lite' ), 'install_content' => esc_html__( 'This should only take a minute. Please don’t close or reload your browser window.', 'wpforms-lite' ), 'install_success_content' => esc_html__( 'The icon library has been installed successfully. We will now save your form and reload the form builder.', 'wpforms-lite' ), 'install_error_content' => wp_kses( sprintf( /* translators: %s - WPForms Support URL. */ __( 'There was an error installing the icon library. Please try again later or contact support if the issue persists.', 'wpforms-lite' ), esc_url( wpforms_utm_link( 'https://wpforms.com/account/support/', 'builder-modal', 'Icon Library Install Failure' ) ) ), [ 'a' => [ 'href' => true, 'target' => true, 'rel' => true, ], ] ), 'reinstall_prompt_content' => esc_html__( 'The icon library appears to be missing or damaged. It will now be reinstalled.', 'wpforms-lite' ), 'icon_picker_title' => esc_html__( 'Icon Picker', 'wpforms-lite' ), 'icon_picker_description' => esc_html__( 'Browse or search for the perfect icon.', 'wpforms-lite' ), 'icon_picker_search_placeholder' => esc_html__( 'Search 2000+ icons...', 'wpforms-lite' ), 'icon_picker_not_found' => esc_html__( 'Sorry, we didn\'t find any matching icons.', 'wpforms-lite' ), ], ]; if ( ! $this->is_installed() ) { return $strings; } $strings['icon_choices']['is_installed'] = true; $strings['icon_choices']['icons'] = $this->get_icons(); return $strings; } /** * Get an SVG icon code from a file for inline output in HTML. * * Note: the output does not need to escape. * * @since 1.7.9 * * @param string $icon Font Awesome icon name. * @param string $style Font Awesome style (solid, brands). * @param string|int $size Icon display size. * * @return string */ private function get_icon( string $icon, string $style, $size ): string { // Sanitize inputs. $icon = sanitize_key( $icon ); $style = sanitize_key( $style ); $size = sanitize_key( (string) $size ); $icon_sizes = $this->get_icon_sizes(); $filename = wp_normalize_path( (string) realpath( "{$this->cache_base_path}/svgs/{$style}/{$icon}.svg" ) ); $allowed_dir = wp_normalize_path( (string) realpath( $this->cache_base_path . '/svgs' ) ); // Verify the file is within the allowed directory. if ( strpos( $filename, $allowed_dir ) !== 0 ) { return ''; } if ( ! is_file( $filename ) || ! is_readable( $filename ) ) { return ''; } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents $svg = (string) file_get_contents( $filename ); if ( strpos( $svg, ' Fatal error: Uncaught Error: Class "Elementor\Modules\Ai\SitePlannerConnect\Module" not found in /htdocs/surfshop.ma/wp-content/plugins/elementor/modules/ai/module.php:41 Stack trace: #0 /htdocs/surfshop.ma/wp-content/plugins/elementor/core/base/module.php(86): Elementor\Modules\Ai\Module->__construct() #1 /htdocs/surfshop.ma/wp-content/plugins/elementor/core/modules-manager.php(64): Elementor\Core\Base\Module::instance() #2 /htdocs/surfshop.ma/wp-content/plugins/elementor/includes/plugin.php(709): Elementor\Core\Modules_Manager->__construct() #3 /htdocs/surfshop.ma/wp-content/plugins/elementor/includes/plugin.php(627): Elementor\Plugin->init_components() #4 /htdocs/surfshop.ma/wp-includes/class-wp-hook.php(324): Elementor\Plugin->init('') #5 /htdocs/surfshop.ma/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #6 /htdocs/surfshop.ma/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #7 /htdocs/surfshop.ma/wp-settings.php(704): do_action('init') #8 /htdocs/surfshop.ma/wp-config.php(98): require_once('/htdocs/surfsho...') #9 /htdocs/surfshop.ma/wp-load.php(50): require_once('/htdocs/surfsho...') #10 /htdocs/surfshop.ma/wp-blog-header.php(13): require_once('/htdocs/surfsho...') #11 /htdocs/surfshop.ma/index.php(17): require('/htdocs/surfsho...') #12 {main} thrown in /htdocs/surfshop.ma/wp-content/plugins/elementor/modules/ai/module.php on line 41