<?php
/*
Plugin Name: Responsive Divi Backgrounds
Description: Serve properly sized backgrounds to your visitors! Improve your website performance and decrease the load time for every page that has a slider or a section with background image. This plugin works only with the <a href="https://www.elegantthemes.com/plugins/divi-builder/">Divi Builder</a>, usually part of the Divi Theme. No configuration required.
Version: 1.0.2
Plugin URI: https://wordpress.org/plugins/responsive-divi-backgrounds/
Author: Danail Emandiev
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html
*/

// Check if there are any Divi Builder sliders with background-image set on the page
function responsive_divi_bgs_check_if_needed() {
	if ( is_admin() ) {
		return;
	}

	global $post;

	$modules = ['slide', 'section'];

	foreach ( $modules as $module ) {
		$regex = '/\[et_pb_' . $module . '\s[^\]]*background_image="(.*?)"/';

		// Check if a supported Divi Builder module with a background image is used
		if ( preg_match( $regex, $post->post_content ) ) {
			add_action(
				'wp_footer',
				function() use ( $module ) { 
					responsive_divi_bgs_print_css( $module );
				}, 99999
			);
		}
	}
}

function responsive_divi_bgs_print_css( $module ) {
	global $post;

	// Regex to get all slides
	$all_elements_regex = '/\[et_pb_' . $module . '\s(.*?)[\]]/';
	
	preg_match_all( $all_elements_regex, $post->post_content, $all_elements );
	
	// Get the slides with background
	$all_elements = $all_elements[0];

	foreach ( $all_elements as $key => $value ) {
		
		// Find all slides with background image
		if ( strpos($value, "background_image") !== false ) {
			
			// Get each slide's backround image url
			preg_match('/background_image="(.*?)"/', $value, $url);
			
			// Save the slide's class and image url
			$elements['.et_pb_' . $module . '_' . $key]['full'] = $url[1];
		}
		
		// Check if background is parallax
		if ( strpos( $value, 'parallax="on"' ) !== false ) {
			$elements['.et_pb_' . $module . '_' . $key]['parallax'] = true;
		}
	}
	
	// Create an array of all image sizes we are going to use
	$image_sizes = ['large', 'medium_large', 'medium'];
	
	// Get the image sizes we are going to use
	foreach ( $image_sizes as $key => $value ) {
		$image_sizes[ $value ] = intval( get_option( $value . '_size_w' ) * 1.1 ) . 'px';
		
		unset( $image_sizes[ $key ] );
	}
	
	// Get all background image URLs and find the other sizes
	foreach ( $elements as $element => $element_keys ) {		
		global $wpdb;
		
		// Get image attachment ID
		$attachment_id = $wpdb->get_col(
			$wpdb->prepare( 'SELECT ID FROM ' . $wpdb->posts . ' WHERE guid="%s";', $element_keys['full'] )
		);

		$attachment_metadata = wp_get_attachment_metadata( $attachment_id[0] );
		
		if ( empty( $attachment_metadata ) ) {
			continue;
		}
		
		// Get all image sizes' urls and save them in $elements
		foreach ( $image_sizes as $letter_size => $pixel_size ) {
			$base_filename_length = strripos( $elements[ $element ]['full'], '.' );

			$elements[ $element ][ $letter_size ] =
			substr( $elements[ $element ]['full'], 0, $base_filename_length ) .
			'-' . $attachment_metadata['sizes'][ $letter_size ]['width'] . 'x' .
			$attachment_metadata['sizes'][ $letter_size ]['height'] .
			substr( $elements[ $element ]['full'], $base_filename_length );
		}
	}

	// Build the inline CSS output
	$inline_css = '<style id="responsive-divi-' . $module . '-backgrounds">';
	
	foreach ( $image_sizes as $letter_size => $pixel_size ) {
		$inline_css .= '@media(max-width:' . $pixel_size . '){';
		
		foreach ( $elements as $element => $element_keys ) {
			if ( empty( $elements[ $element ][ $letter_size ] ) ) {
				continue;
			}
			
			// Handle parallax backgrounds
			if ( isset( $element_keys['parallax'] ) && $element_keys['parallax'] === true ) {
				$inline_css .= 'div.et_pb_' . $module . $element . ' .et_parallax_bg{background-image:url(' .
				$elements[ $element ][ $letter_size ] . ')!important}';
			}
			// then the non-parallax ones
			else {
				$inline_css .= 'div.et_pb_' . $module . $element . '{background-image:url(' .
				$elements[ $element ][ $letter_size ] . ')!important}';
			}	
		}
		$inline_css .= '}';
	}
	
	// Close the <style> tag
	$inline_css .= '</style>';
	
	echo $inline_css;
}

// Add check as early as possible
add_action( 'wp', 'responsive_divi_bgs_check_if_needed' );