Viewing File: /home/maglabs/bnb2you/wp-content/plugins/mailpoet/lib/EmailEditor/Engine/Templates/Templates.php

<?php declare(strict_types = 1);

namespace MailPoet\EmailEditor\Engine\Templates;

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


use MailPoet\EmailEditor\Engine\EmailStylesSchema;
use WP_Block_Template;

// phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
class Templates {
  const MAILPOET_EMAIL_META_THEME_TYPE = 'mailpoet_email_theme';
  const MAILPOET_TEMPLATE_EMPTY_THEME = ['version' => 2]; // The version 2 is important to merge themes correctly

  private Utils $utils;
  private string $pluginSlug = 'mailpoet/mailpoet';
  private string $postType = 'mailpoet_email';
  private string $templateDirectory;
  private array $templates = [];
  private array $themeJson = [];

  public function __construct(
    Utils $utils
  ) {
    $this->utils = $utils;
    $this->templateDirectory = dirname(__FILE__) . DIRECTORY_SEPARATOR;
  }

  public function initialize(): void {
    add_filter('pre_get_block_file_template', [$this, 'getBlockFileTemplate'], 10, 3);
    add_filter('get_block_templates', [$this, 'addBlockTemplates'], 10, 3);
    add_filter('theme_templates', [$this, 'addThemeTemplates'], 10, 4); // Needed when saving post – template association
    add_filter('get_block_template', [$this, 'addBlockTemplateDetails'], 10, 1);
    add_filter('rest_pre_insert_wp_template', [$this, 'forcePostContent'], 9, 1);
    $this->initializeTemplates();
    $this->initializeApi();
  }

  /**
   * Get a block template by ID.
   */
  public function getBlockTemplate($templateId) {
    $templates = $this->getBlockTemplates();
    return $templates[$templateId] ?? null;
  }

  /**
   * Get a predefined or user defined theme for a block template.
   *
   * @param string $templateId
   * @param int|null $templateWpId
   * @return array
   */
  public function getBlockTemplateTheme($templateId, $templateWpId = null) {
    // First check if there is a user updated theme saved
    $theme = $this->getCustomTemplateTheme($templateWpId);

    if ($theme) {
      return $theme;
    }

    // If there is no user edited theme, look for default template themes in files.
    ['prefix' => $templatePrefix, 'slug' => $templateSlug] = $this->utils->getTemplateIdParts($templateId);

    if ($this->pluginSlug !== $templatePrefix) {
      return self::MAILPOET_TEMPLATE_EMPTY_THEME;
    }

    if (!isset($this->themeJson[$templateSlug])) {
      $jsonFile = $this->templateDirectory . $templateSlug . '.json';

      if (file_exists($jsonFile)) {
        $this->themeJson[$templateSlug] = json_decode((string)file_get_contents($jsonFile), true);
      }
    }

    return $this->themeJson[$templateSlug] ?? self::MAILPOET_TEMPLATE_EMPTY_THEME;
  }

  public function getBlockFileTemplate($return, $templateId, $template_type) {
    ['prefix' => $templatePrefix, 'slug' => $templateSlug] = $this->utils->getTemplateIdParts($templateId);

    if ($this->pluginSlug !== $templatePrefix) {
        return $return;
    }

    $templatePath = $templateSlug . '.html';

    if (!is_readable($this->templateDirectory . $templatePath)) {
        return $return;
    }

    return $this->getBlockTemplateFromFile($templatePath);
  }

  public function addBlockTemplates($query_result, $query, $template_type) {
    if ('wp_template' !== $template_type) {
      return $query_result;
    }

    $post_type = isset($query['post_type']) ? $query['post_type'] : '';

    if ($post_type && $post_type !== $this->postType) {
      return $query_result;
    }

    foreach ($this->getBlockTemplates() as $blockTemplate) {
      $fits_slug_query = !isset($query['slug__in']) || in_array($blockTemplate->slug, $query['slug__in'], true);
      $fits_area_query = !isset($query['area']) || ( property_exists($blockTemplate, 'area') && $blockTemplate->area === $query['area'] );
      $should_include = $fits_slug_query && $fits_area_query;

      if ($should_include) {
          $query_result[] = $blockTemplate;
      }
    }

    return $query_result;
  }

  public function addThemeTemplates($templates, $theme, $post, $post_type) {
    if ($post_type && $post_type !== $this->postType) {
      return $templates;
    }
    foreach ($this->getBlockTemplates() as $blockTemplate) {
      $templates[$blockTemplate->slug] = $blockTemplate;
    }
    return $templates;
  }

  /**
   * This is a workaround to ensure the post object passed to `inject_ignored_hooked_blocks_metadata_attributes` contains
   * content to prevent the template being empty when saved. The issue currently occurs when WooCommerce enables block hooks,
   * and when older versions of `inject_ignored_hooked_blocks_metadata_attributes` are
   * used (before https://github.com/WordPress/WordPress/commit/725f302121c84c648c38789b2e88dbd1eb41fa48).
   * This can be removed in the future.
   *
   * To test the issue create a new email, revert template changes, save a color change, then save a color change again.
   * When you refresh if the post is blank, the issue is present.
   *
   * @param \stdClass $changes
   */
  public function forcePostContent($changes) {
    if (empty($changes->post_content) && !empty($changes->ID)) {
      // Find the existing post object.
      $post = get_post($changes->ID);
      if ($post && !empty($post->post_content)) {
        $changes->post_content = $post->post_content;
      }
    }
    return $changes;
  }

  /**
   * Add details to templates in editor.
   *
   * @param WP_Block_Template $block_template Block template object.
   * @return WP_Block_Template
   */
  public function addBlockTemplateDetails($block_template) {
    if (!$block_template || !isset($this->templates[$block_template->slug])) {
      return $block_template;
    }
    if (empty($block_template->title)) {
      $block_template->title = $this->templates[$block_template->slug]['title'];
    }
    if (empty($block_template->description)) {
      $block_template->description = $this->templates[$block_template->slug]['description'];
    }
    return $block_template;
  }

  /**
   * Initialize template details. This is done at runtime because of localisation.
   */
  private function initializeTemplates(): void {
    $this->templates['email-general'] = [
      'title' => __('General Email', 'mailpoet'),
      'description' => __('A general template for emails.', 'mailpoet'),
    ];
    $this->templates['awesome-one'] = [
      'title' => __('Awesome Template One', 'mailpoet'),
      'description' => __('A template used in testing.', 'mailpoet'),
    ];
    $this->templates['awesome-two'] = [
      'title' => __('Awesome Template Two', 'mailpoet'),
      'description' => __('A template used in testing.', 'mailpoet'),
    ];
    $this->templates['email-computing-mag'] = [
      'title' => __('Retro Computing Mag', 'mailpoet'),
      'description' => __('A retro themed template.', 'mailpoet'),
    ];
  }

  private function initializeApi(): void {
    register_post_meta(
      'wp_template',
      self::MAILPOET_EMAIL_META_THEME_TYPE,
      [
        'show_in_rest' => [
          'schema' => (new EmailStylesSchema())->getSchema(),
        ],
        'single' => true,
        'type' => 'object',
        'default' => self::MAILPOET_TEMPLATE_EMPTY_THEME,
      ]
    );
    register_rest_field(
      'wp_template',
      self::MAILPOET_EMAIL_META_THEME_TYPE,
      [
      'get_callback' => function($object) {
         return $this->getBlockTemplateTheme($object['id'], $object['wp_id']);
      },
      'update_callback' => function($value, $template) {
        return update_post_meta($template->wp_id, self::MAILPOET_EMAIL_META_THEME_TYPE, $value);
      },
      'schema' => (new EmailStylesSchema())->getSchema(),
      ]
    );
  }

  /**
   * Gets block templates indexed by ID.
   */
  private function getBlockTemplates() {
    $blockTemplates = array_map(function($templateSlug) {
      return $this->getBlockTemplateFromFile($templateSlug . '.html');
    }, array_keys($this->templates));
    $customTemplates = $this->getCustomTemplates(); // From the DB.
    $customTemplateIds = wp_list_pluck($customTemplates, 'id');

    // Combine to remove duplicates if a custom template has the same ID as a file template.
    return array_column(
      array_merge(
        $customTemplates,
        array_filter(
          $blockTemplates,
          function($blockTemplate) use ($customTemplateIds) {
              return !in_array($blockTemplate->id, $customTemplateIds, true);
          }
        ),
      ),
      null,
      'id'
    );
  }

  private function getBlockTemplateFromFile(string $template) {
    $template_slug = $this->utils->getBlockTemplateSlugFromPath($template);
    $templateObject = (object)[
      'slug' => $template_slug,
      'id' => $this->pluginSlug . '//' . $template_slug,
      'title' => $this->templates[$template_slug]['title'] ?? '',
      'description' => $this->templates[$template_slug]['description'] ?? '',
      'path' => $this->templateDirectory . $template,
      'type' => 'wp_template',
      'theme' => $this->pluginSlug,
      'source' => 'plugin',
      'post_types' => [
        $this->postType,
      ],
    ];
    return $this->utils->buildBlockTemplateFromFile($templateObject);
  }

  private function getCustomTemplates($slugs = [], $template_type = 'wp_template') {
    $check_query_args = [
        'post_type' => $template_type,
        'posts_per_page' => -1,
        'no_found_rows' => true,
        'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
            [
                'taxonomy' => 'wp_theme',
                'field' => 'name',
                'terms' => [ $this->pluginSlug, get_stylesheet() ],
            ],
        ],
    ];

    if (is_array($slugs) && count($slugs) > 0) {
        $check_query_args['post_name__in'] = $slugs;
    }

    $check_query = new \WP_Query($check_query_args);
    $custom_templates = $check_query->posts;

    return array_map(
      function($custom_template) {
          return $this->utils->buildBlockTemplateFromPost($custom_template);
      },
      $custom_templates
    );
  }

  private function getCustomTemplateTheme($templateWpId) {
    if (!$templateWpId) {
      return null;
    }
    $theme = get_post_meta($templateWpId, self::MAILPOET_EMAIL_META_THEME_TYPE, true);
    if (is_array($theme) && isset($theme['styles'])) {
      return $theme;
    }
    return null;
  }
}
Back to Directory File Manager