diff --git a/php/class-plugin.php b/php/class-plugin.php index 2a775b2d..8fc84875 100644 --- a/php/class-plugin.php +++ b/php/class-plugin.php @@ -14,6 +14,7 @@ use Cloudinary\Delivery\Lazy_Load; use Cloudinary\Delivery\Responsive_Breakpoints; use Cloudinary\Assets as CLD_Assets; +use Cloudinary\Integrations\Elementor; use Cloudinary\Integrations\WPML; use Cloudinary\Media\Gallery; use Cloudinary\Sync\Storage; @@ -31,7 +32,7 @@ final class Plugin { * * @since 0.1 * - * @var Admin|CLD_Assets|Connect|Dashboard|Deactivation|Delivery|Extensions|Gallery|Lazy_Load|Media|Meta_Box|Relate|Report|Responsive_Breakpoints|REST_API|State|Storage|SVG|Sync|URL[]|WPML|null + * @var Admin|CLD_Assets|Connect|Dashboard|Deactivation|Delivery|Extensions|Gallery|Lazy_Load|Media|Meta_Box|Relate|Report|Responsive_Breakpoints|REST_API|State|Storage|SVG|Sync|URL[]|WPML|Elementor|null */ public $components; /** @@ -136,6 +137,7 @@ public function plugins_loaded() { $this->components['metabox'] = new Meta_Box( $this ); $this->components['url'] = new URL( $this ); $this->components['wpml'] = new WPML( $this ); + $this->components['elementor'] = new Elementor( $this ); $this->components['special_offer'] = new Special_Offer( $this ); } diff --git a/php/integrations/class-elementor.php b/php/integrations/class-elementor.php new file mode 100644 index 00000000..01e1fe31 --- /dev/null +++ b/php/integrations/class-elementor.php @@ -0,0 +1,130 @@ + array( + 'device' => 'desktop', + 'suffix' => '', + ), + '_background_hover_image' => array( + 'device' => 'desktop', + 'suffix' => ':hover', + ), + '_background_image_tablet' => array( + 'device' => 'tablet', + 'suffix' => '', + ), + '_background_hover_image_tablet' => array( + 'device' => 'tablet', + 'suffix' => ':hover', + ), + '_background_image_mobile' => array( + 'device' => 'mobile', + 'suffix' => '', + ), + '_background_hover_image_mobile' => array( + 'device' => 'mobile', + 'suffix' => ':hover', + ), + ); + + /** + * Check if the integration can be enabled. + * + * @return bool + */ + public function can_enable() { + return class_exists( 'Elementor\Plugin' ); + } + + /** + * Register hooks for the integration. + * + * @return void + */ + public function register_hooks() { + add_action( 'elementor/element/parse_css', array( $this, 'replace_background_images_in_css' ), 10, 2 ); + add_action( 'cloudinary_flush_cache', array( $this, 'clear_elementor_css_cache' ) ); + } + + /** + * Replace all background images URLs with Cloudinary URLs, within the generated Elementor CSS file. + * + * @param Post $post_css The post CSS object. + * @param Element_Base $element The Elementor element. + * @return void + */ + public function replace_background_images_in_css( $post_css, $element ) { + $settings = $element->get_settings_for_display(); + $media = $this->plugin->get_component( 'media' ); + $delivery = $this->plugin->get_component( 'delivery' ); + + if ( ! $media || ! $delivery ) { + return; + } + + foreach ( self::ELEMENTOR_BACKGROUND_IMAGES as $background_key => $background_data ) { + // We need to have the ID from the image to proceed. + if ( ! isset( $settings[ $background_key ]['id'] ) ) { + continue; + } + + $media_id = $settings[ $background_key ]['id']; + $media_size = isset( $settings[ $background_key ]['size'] ) ? $settings[ $background_key ]['size'] : array(); + + // Skip if the media is not deliverable via Cloudinary. + if ( ! $delivery->is_deliverable( $media_id ) ) { + continue; + } + + // Generate the Cloudinary URL. + $cloudinary_url = $media->cloudinary_url( $media_id, $media_size ); + + // Build the CSS selector and rule. + $css_selector = $post_css->get_element_unique_selector( $element ) . $background_data['suffix']; + $css_rule = array( 'background-image' => "url('$cloudinary_url')" ); + + // Retrieve the specific media query rule for non-desktop devices. + $media_query = null; + if ( 'desktop' !== $background_data['device'] ) { + $media_query = array( 'max' => $background_data['device'] ); + } + + // Override the CSS rule in Elementor. + $post_css->get_stylesheet()->add_rules( $css_selector, $css_rule, $media_query ); + } + } + + /** + * Clear Elementor CSS cache. + * This is called when Cloudinary cache is flushed, so that any change in media URLs is reflected in Elementor CSS files. + * + * @return void + */ + public function clear_elementor_css_cache() { + if ( class_exists( 'Elementor\Plugin' ) ) { + $elementor = Plugin::instance(); + $elementor->files_manager->clear_cache(); + } + } +}