HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux sa-dev.otherchirps.net 5.15.0-139-generic #149-Ubuntu SMP Fri Apr 11 22:06:13 UTC 2025 x86_64
User: www-data (33)
PHP: 8.0.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/html/wp-content/plugins/editorplus/includes/class-editorplus-styles-manager.php
<?php

/**
 * Main file for styles manager
 *
 * @package EditorPlus
 */

if (!defined('ABSPATH')) {
	exit;
}

require_once EDPL_EDITORPLUS_PLUGIN_DIR . 'includes/class-editorplus-styles-generator.php';

/**
 * Main class for handling editorplus stylings
 */
class EditorPlus_Styles_Manager {

	/**
	 * Editorplus styles generator.
	 *
	 * @var EditorPlus_Styles_Generator
	 */
	private $generator;

	/**
	 * Contructor.
	 *
	 * @return void
	 */
	public function __construct() {

		$this->generator = new EditorPlus_Styles_Generator();

		// Rendering styles for header.
		add_action(
			'wp_head',
			function () {
				return $this->render_styles();
			}
		);

		// Rendering styles for footer.
		add_action(
			'wp_footer',
			function () {
				return $this->render_styles(true);
			}
		);

		add_action('body_class', array($this, 'insert_editorplus_body_class'));
		add_filter('editor_plus_css_code', array($this, 'merge_global_styles'), 10, 2);
		add_action('init', array($this, 'register'));
		add_filter('render_block', array($this, 'prepare_blocks_for_styles'), 10, 2);
	}

	/**
	 * Will prepare each block for styling by assigning them unique classes.
	 *
	 * @param string $block_content - Block inner content.
	 * @param array  $block - Parsed block.
	 *
	 * @return string - Block content with unique class assigned.
	 */
	public function prepare_blocks_for_styles($block_content, $block) {

		$slug = $block['blockName'];

		// Excluding unsupported blocks.
		if (!editorplus_is_supported_block($slug) || !editorplus_has_block_styles($block)) {
			return $block_content;
		}

		libxml_use_internal_errors(true); // For surpressing any document error.

		$document = new DOMDocument();

		if ('' === $block_content) {
			return $block_content;
		}

		$document->loadHTML('<?xml encoding="utf-8" ?>' . $block_content);

		$finder = new DOMXPath($document);

		$selector = $block['attrs']['epGeneratedClass'] ?? '';

		if ('' === $selector) {
			return $block_content;
		}

		$block_element = $finder->query("//*[contains(@class, '$selector')]")->item(0);

		if (is_null($block_element)) {
			// Using the top wrapper element as an alternative, if editorplus wrapper class not found.
			$first_element = $document->getElementsByTagName('body')->item(0)->firstChild;

			if (!is_null($first_element)) {
				$block_element = $first_element;
			} else {
				return $block_content;
			}
		}

		$classlist = explode(' ', $block_element->getAttribute('class') ?? '');

		$classlist[] = 'eplus-styles-uid-' . editorplus_generate_unique_uid_for_block($block);

		if (!is_null($block_element)) {
			$block_element->setAttribute(
				'class',
				join(' ', $classlist)
			);
		}

		libxml_clear_errors();

		return $document->saveHTML($document->getElementsByTagName('body')->item(0)->firstChild);
	}

	/**
	 * All registerations should be done here.
	 *
	 * @return void
	 */
	public function register() {

		$post_types = get_post_types(
			array(
				'_builtin' => false,
			),
			'names',
			'and'
		);

		$post_types['post'] = 'post';

		foreach ($post_types as $post_type) {

			// TODO: "copy styling feature" is still using metadata, refactor the client script to utilize state for this.
			register_meta(
				$post_type,
				'editor_plus_copied_stylings',
				array(
					'show_in_rest' => true,
					'single'       => true,
					'type'         => 'string',
					'default'      => '{}',
				)
			);
		}
	}

	/**
	 * Will insert editorplus body class.
	 *
	 * @param array $classes - Body classes.
	 * @return array - body classes merged with editorplus class.
	 */
	public function insert_editorplus_body_class($classes) {
		$classes['editorplus_styles'] = 'eplus_styles';
		return $classes;
	}

	/**
	 * Will merge global styles to the given css code.
	 *
	 * @param string $css_code - CSS Code.
	 * @param bool   $in_footer - True if the css code is being processed for the footer, otherwise false.
	 *
	 * @return string - CSS Code with global styles merged.
	 */
	public function merge_global_styles($css_code, $in_footer) {

		// It should be enqueued in footer, if this option is set to 'true'.
		$required_global_position = get_option('ep_custom_global_styles_position', 'false');

		if ('true' === $required_global_position && $in_footer) {
			$css_code .= get_option('ep_custom_global_css', '');
			return $css_code;
		}

		if ('true' !== $required_global_position && !$in_footer) {
			$css_code .= get_option('ep_custom_global_css', '');
			return $css_code;
		}

		return $css_code;
	}

	/**
	 * This method is responsible to output editorplus styles, scoped to a post.
	 *
	 * @param bool $in_footer - True if enqueueing in the footer, otherwise false.
	 *
	 * @return void
	 */
	public function render_styles($in_footer = false) {

		$current_post_id = get_the_ID();
		$current_post    = get_post($current_post_id);

		if (is_null($current_post)) {
			return;
		}

		$generated_editorplus_styles = '';

		// Generating styles specifically for post content.
		$current_post_content = $current_post->post_content;

		// Skipping blocks styles for footer scope.
		if (false === $in_footer) {
			$parsed_blocks                = parse_blocks($current_post_content);
			$generated_editorplus_styles .= $this->generator->generate_styles_from_blocks($parsed_blocks);
		}

		$generated_editorplus_styles = apply_filters('editor_plus_css_code', $generated_editorplus_styles, $in_footer);

		/**
		 * The generated CSS should not contain any html markup.
		 * Using regex to match and strip these html tags.
		 *
		 * WordPress is also using some regex to validate the CSS output.
		 *
		 * @see https://github.com/WordPress/WordPress/blob/56c162fbc9867f923862f64f1b4570d885f1ff03/wp-includes/customize/class-wp-customize-custom-css-setting.php#L157-L168
		 */
		if (preg_match('#</?\w+#', $generated_editorplus_styles)) {

			// Replacing all the matched tags.
			$generated_editorplus_styles = preg_replace('#</?\w+#', '', $generated_editorplus_styles);
		}

		if ('' !== $generated_editorplus_styles) {

			// Creating an style id based on the position.
			$styles_id_suffix = $in_footer ? '-footer' : '-header';

?>
			<style id="editorplus-generated-styles<?php echo $styles_id_suffix; ?>">
				<?php echo $generated_editorplus_styles; ?>
			</style>
<?php
		}
	}
}