XylotrechusZ
<?php
class Brizy_Admin_Templates
{
const CP_TEMPLATE = 'editor-template';
const TEMPLATE_TYPE_KEY = 'brizy_template_type';
const CP_TEMPLATES = 'brizy_templates';
const RULE_LIST_VEIW = 'brizy_rule_list_view';
const RULE_TAXONOMY_LIST = 'brizy_taxonomy_list';
const RULE_CREATE = 'brizy_create';
const TYPE_SINGLE = 'single';
const TYPE_ARCHIVE = 'archive';
const TYPE_SINGLE_PRODUCT = 'single_product';
const TYPE_PRODUCT_ARCHIVE = 'product_archive';
private $isExcerpt;
/**
* @var Brizy_Editor_Post
*/
private static $template;
private static $templateContent;
/**
* Brizy_Admin_Templates constructor.
*/
protected function __construct() {
add_action( 'wp_loaded', array( $this, 'initializeActions' ) );
}
/**
* @return Brizy_Editor_Post
*/
public static function getTemplate()
{
return self::$template;
}
public function initializeActions()
{
// do other stuff here
if (is_admin()) {
add_filter('post_updated_messages', array($this, 'filterTemplateMessages'));
add_action('add_meta_boxes', array($this, 'registerTemplateMetaBox'), 9);
add_action('transition_post_status', array($this, 'actionTransitionPostStatus'), 10, 3);
add_action('wp_ajax_'.self::RULE_LIST_VEIW, array($this, 'getTemplateRuleBox'));
add_filter('post_row_actions', array($this, 'removeRowActions'), 10, 1);
add_action('admin_enqueue_scripts', array($this, 'action_register_static'));
add_filter('save_post', array($this, 'saveTemplateRules'), 10, 2);
add_filter('pre_post_update', array($this, 'validate_template_rules'), 10, 2);
add_action('admin_notices', array($this, 'saveTemplateRulesNotices'));
} elseif (!defined('DOING_AJAX') &&
!is_admin() &&
!isset($_REQUEST[Brizy_Editor::prefix('_media')]) &&
!Brizy_Public_Main::is_editing() &&
!isset($_REQUEST[Brizy_Editor::prefix('_file')]) &&
!isset($_REQUEST[Brizy_Editor::prefix('_attachment')]) &&
!isset($_REQUEST[Brizy_Editor::prefix('_block_screenshot')]) &&
!isset($_REQUEST[Brizy_Editor::prefix('')])) {
add_action('wp', array($this, 'templateFrontEnd'));
}
}
/**
* @return Brizy_Admin_Templates
* @deprecated
*/
public static function _init()
{
return self::instance();
}
public static function instance()
{
static $instance;
if (!$instance) {
$instance = new self();
}
return $instance;
}
function action_register_static()
{
if (is_customize_preview() || get_post_type() !== Brizy_Admin_Templates::CP_TEMPLATE) {
return;
}
$urlBuilder = new Brizy_Editor_UrlBuilder();
// hyperapp.js is also used in PRO
wp_enqueue_script(
Brizy_Editor::get_slug().'-hyperapp-js',
$urlBuilder->plugin_url('admin/static/js/hyperapp.js'),
array('jquery', 'underscore'),
BRIZY_VERSION,
true
);
wp_enqueue_style(
Brizy_Editor::get_slug().'-select2',
$urlBuilder->plugin_url('vendor/select2/select2/dist/css/select2.min.css'),
array(),
true
);
wp_enqueue_script(
Brizy_Editor::get_slug().'-select2',
$urlBuilder->plugin_url('vendor/select2/select2/dist/js/select2.full.min.js'),
array('jquery')
);
wp_enqueue_script(
Brizy_Editor::get_slug().'-rules',
$urlBuilder->plugin_url('admin/static/js/rules.js'),
array(Brizy_Editor::get_slug().'-hyperapp-js'),
BRIZY_VERSION,
true
);
$templateGroups = [
'single' => __('Single', 'brizy'),
'archive' => __('Archive', 'brizy'),
];
if (class_exists('WooCommerce')) {
$templateGroups['single_product'] = __('Product', 'brizy');
$templateGroups['product_archive'] = __('Product Archive', 'brizy');
}
$ruleManager = new Brizy_Admin_Rules_Manager();
wp_localize_script(
Brizy_Editor::get_slug().'-rules',
'Brizy_Admin_Rules',
array(
'url' => set_url_scheme(admin_url('admin-ajax.php')),
'rules' => $ruleManager->getRules(get_the_ID()),
'hash' => wp_create_nonce(Brizy_Admin_Rules_Api::nonce),
'id' => get_the_ID(),
'templateType' => Brizy_Admin_Templates::getTemplateType(get_the_ID()),
'labels' => $templateGroups,
'prefix' => Brizy_Editor::prefix(),
)
);
}
/**
* @param $messages
*
* @return mixed
*/
function filterTemplateMessages($messages)
{
$post = get_post();
$post_type = get_post_type($post);
$post_type_object = get_post_type_object($post_type);
$messages[self::CP_TEMPLATE] = array(
0 => '', // Unused. Messages start at index 1.
1 => __('Template updated.'),
2 => __('Custom field updated.'),
3 => __('Custom field deleted.'),
4 => __('Template updated.'),
/* translators: %s: date and time of the revision */
5 => isset($_GET['revision']) ? sprintf(
__('Template restored to revision from %s'),
wp_post_revision_title((int)$_GET['revision'], false)
) : false,
6 => __('Template published.'),
7 => __('Template saved.'),
8 => __('Template submitted.'),
9 => sprintf(
__('Template scheduled for: <strong>%1$s</strong>.'),
// translators: Publish box date format, see http://php.net/date
date_i18n(__('M j, Y @ G:i'), strtotime($post->post_date))
),
10 => __('Template draft updated.'),
);
if ($post_type_object->publicly_queryable && 'Template' === $post_type) {
$permalink = get_permalink($post->ID);
$view_link = sprintf(' <a href="%s">%s</a>', esc_url($permalink), __('View Template'));
$messages[$post_type][1] .= $view_link;
$messages[$post_type][6] .= $view_link;
$messages[$post_type][9] .= $view_link;
$preview_permalink = add_query_arg('preview', 'true', $permalink);
$preview_link = sprintf(
' <a target="_blank" href="%s">%s</a>',
esc_url($preview_permalink),
__('Preview Template')
);
$messages[$post_type][8] .= $preview_link;
$messages[$post_type][10] .= $preview_link;
}
return $messages;
}
static public function registerCustomPostTemplate()
{
$labels = array(
'name' => _x('Templates', 'post type general name', 'brizy'),
'singular_name' => _x('Template', 'post type singular name', 'brizy'),
'menu_name' => _x('Templates', 'admin menu', 'brizy'),
'name_admin_bar' => _x('Template', 'add new on admin bar', 'brizy'),
'add_new' => _x('Add New', self::CP_TEMPLATE, 'brizy'),
'add_new_item' => __('Add New Template', 'brizy'),
'new_item' => __('New Template', 'brizy'),
'edit_item' => __('Edit Template', 'brizy'),
'view_item' => __('View Template', 'brizy'),
'all_items' => __('Templates', 'brizy'),
'search_items' => __('Search Templates', 'brizy'),
'parent_item_colon' => __('Parent Templates:', 'brizy'),
'not_found' => __('No Templates found.', 'brizy'),
'not_found_in_trash' => __('No Templates found in Trash.', 'brizy'),
);
register_post_type(
self::CP_TEMPLATE,
array(
'labels' => $labels,
'public' => false,
'has_archive' => false,
'description' => __bt('brizy', 'Brizy').' '.__('templates', 'brizy').'.',
'publicly_queryable' => Brizy_Editor_User::is_user_allowed(),
'show_ui' => true,
'show_in_menu' => Brizy_Admin_Settings::menu_slug(),
'query_var' => false,
'rewrite' => array('slug' => 'editor-template'),
'capability_type' => 'page',
'hierarchical' => false,
'show_in_rest' => false,
'can_export' => true,
'exclude_from_search' => true,
'supports' => array('title', 'revisions', 'page-attributes'),
)
);
add_filter(
'brizy_supported_post_types',
function ($posts) {
$posts[] = self::CP_TEMPLATE;
return $posts;
}
);
}
public function registerTemplateMetaBox()
{
add_meta_box(
'template-rules',
__('Display Conditions', 'brizy'),
array(
$this,
'templateRulesBox',
),
self::CP_TEMPLATE,
'normal',
'high'
);
}
public function removeRowActions($actions)
{
if (get_post_type() === self::CP_TEMPLATE) {
unset($actions['view']);
}
return $actions;
}
public function templateRulesBox()
{
try {
$templateId = isset($_REQUEST['post']) ? (int)$_REQUEST['post'] : get_the_ID();
if (!$templateId) {
throw new Exception();
}
echo '<div class="brizy-template-rules submitbox"><div id="rules"></div></div>';
} catch (Exception $e) {
Brizy_Logger::instance()->error($e->getMessage(), array('exception' => $e));
esc_html_e('Unable to show the rule box.', 'brizy');
}
}
public function getTemplateRuleBox()
{
$this->templateRulesBox();
exit;
}
/**
* @return Brizy_Editor_Post|mixed|null
* @throws Exception
*/
public function getTemplateForCurrentPage()
{
$ruleMatches = Brizy_Admin_Rules_Manager::getCurrentPageGroupAndType();
$pid = Brizy_Editor::get()->currentPostId();
if ($pid && Brizy_Editor_Post::isBrizyEnabled(get_post($pid))) {
return null;
}
$is_preview = is_preview();
$templates = get_posts(
array(
'post_type' => self::CP_TEMPLATE,
'numberposts' => -1,
'post_status' => $is_preview ? 'any' : 'publish',
)
);
$ruleManager = new Brizy_Admin_Rules_Manager();
$ruleSets = [];
foreach ($templates as $atemplate) {
$ruleSets[$atemplate->ID] = $ruleManager->getRuleSet($atemplate->ID);
}
foreach ((array)$ruleMatches as $rule_match) {
$applyFor = $rule_match['applyFor'];
$entityType = $rule_match['entityType'];
$entityValues = $rule_match['entityValues'];
$templates = Brizy_Admin_Rules_Manager::sortEntitiesByRuleWeight(
$templates,
[
'type' => $applyFor,
'entityType' => $entityType,
'entityValues' => $entityValues,
]
);
foreach ($templates as $atemplate) {
try {
if ($ruleSets[$atemplate->ID]->isMatching($applyFor, $entityType, $entityValues)) {
return Brizy_Editor_Post::get($atemplate->ID);
}
} catch (\Exception $e) {
continue; // we catch here the exclusions
}
}
}
return null;
}
/**
* @param $template
*
* @return string
*/
public function templateInclude($template)
{
if (!self::getTemplate()) {
return $template;
}
$templateName = self::getTemplate()->get_template();
$urlBuilder = new Brizy_Editor_UrlBuilder();
if (!$templateName || $templateName == 'default') {
return $urlBuilder->plugin_path('public/views/templates/'.Brizy_Config::BRIZY_TEMPLATE_FILE_NAME);
}
if (in_array(
$templateName,
array(
Brizy_Config::BRIZY_BLANK_TEMPLATE_FILE_NAME,
Brizy_Config::BRIZY_TEMPLATE_FILE_NAME,
)
)) {
return $urlBuilder->plugin_path('/public/views/templates/'.$templateName);
}
return $template;
}
public function templateFrontEnd()
{
global $wp_query;
$pid = Brizy_Editor::get()->currentPostId();
$is_using_brizy = false;
try {
if (in_array(get_post_type($pid), Brizy_Editor::get()->supported_post_types())) {
$is_using_brizy = Brizy_Editor_Entity::isBrizyEnabled($pid);
}
} catch (Exception $e) {
}
try {
if (is_null($pid) || !$is_using_brizy) {
self::$template = $this->getTemplateForCurrentPage();
if (!self::getTemplate()) {
return;
}
do_action('brizy_preview_mode', self::getTemplate());
add_filter('template_include', array($this, 'templateInclude'), 20000);
try {
$compiler = new Brizy_Editor_Compiler(
Brizy_Editor_Project::get(),
new Brizy_Admin_Blocks_Manager(Brizy_Admin_Blocks_Main::CP_GLOBAL),
new Brizy_Editor_UrlBuilder(Brizy_Editor_Project::get(), self::getTemplate()),
Brizy_Config::getCompilerUrls(),
Brizy_Config::getCompilerDownloadUrl()
);
if ($compiler->needsCompile(self::getTemplate())) {
$editorConfig = Brizy_Editor_Editor_Editor::get(
Brizy_Editor_Project::get(),
self::getTemplate()
)
->config(Brizy_Editor_Editor_Editor::COMPILE_CONTEXT);
$compiler->compilePost(self::getTemplate(), $editorConfig);
}
} catch (Exception $e) {
Brizy_Logger::instance()->exception($e);
}
remove_filter('the_content', 'wpautop');
remove_filter('the_content', 'wptexturize');
remove_filter('the_content', 'shortcode_unautop');
add_filter('brizy_asset_manager_post', function ($post) use ($pid) {
if ($post->post_type !== self::CP_TEMPLATE) {
return $post;
}
return get_post($pid);
});
// insert the compiled head and content
add_filter('body_class', array($this, 'bodyClassFrontend'));
//add_action( 'wp_head', array( $this, 'insertTemplateHead' ) );
add_action('brizy_template_content', array($this, 'showTemplateContent'), -12000);
add_action('wp_enqueue_scripts', array($this, 'enqueue_preview_assets'), 9999);
add_filter('the_content', [$this, 'filterPageContent'], -12000);
add_filter('get_the_excerpt', [$this, 'start_the_excerpt'], 1);
add_filter('get_the_excerpt', [$this, 'end_the_excerpt'], 20);
}
} catch (Exception $e) {
//ignore
Brizy_Logger::instance()->error($e->getMessage(), []);
}
}
/**
* @internal
*/
public function enqueue_preview_assets()
{
if (wp_script_is('jquery') === false) {
wp_register_script('jquery-core', "/wp-includes/js/jquery/jquery.js");
wp_register_script('jquery-migrate', "/wp-includes/js/jquery/jquery-migrate.min.js");
wp_register_script('jquery', false, array('jquery-core', 'jquery-migrate'));
}
Brizy_Public_AssetEnqueueManager::_init()->enqueuePost(self::getTemplate());
}
public function bodyClassFrontend($classes)
{
$classes[] = 'brz';
return $classes;
}
/**
* @param $content
*
* @return null|string|string[]
* @throws Exception
*/
public function showTemplateContent()
{
$content = $this->getTemplateContent();
echo apply_filters('the_content', $content);
}
private function getTemplateContent()
{
if (!self::getTemplate()) {
return;
}
if(self::$templateContent) {
return self::$templateContent;
}
$pid = Brizy_Editor::get()->currentPostId();
$post = self::getTemplate()->getWpPost();
if ($pid) {
$post = get_post($pid);
}
$compiled_html = self::getTemplate()->get_compiled_html();
$content = apply_filters(
'brizy_content',
$compiled_html,
Brizy_Editor_Project::get(),
$post,
'body'
);
$content = apply_filters('brizy_template_content_compiled', $content);
return self::$templateContent = $content;
}
/**
* @param $content
*
* @return null|string|string[]
* @throws Exception
*/
public function filterPageContent($content)
{
if (!self::getTemplate() || doing_filter('brizy_content') || $this->isExcerpt) {
return $content;
}
$pid = Brizy_Editor::get()->currentPostId();
$brizyPost = null;
if ($pid) {
$brizyPost = get_post($pid);
}
return $this->getTemplateContent();
}
/**
* Check for rules conflicts on transition post from trash to another post status.
* If we have some conflicts between the rules from the transition post rules and other rules from existing posts,
* then we remove conflicting rules from the restored post.
*
* @param string $new_status New post status.
* @param string $old_status Old post status.
* @param WP_Post $post Transition post.
*/
public function actionTransitionPostStatus($new_status, $old_status, $post)
{
if ('trash' !== $old_status || self::CP_TEMPLATE !== $post->post_type) {
return;
}
$post_id = $post->ID;
$rule_manager = new Brizy_Admin_Rules_Manager();
$post_rules = $rule_manager->getRules($post_id);
if (!$post_rules) {
return;
}
$all_rules = $rule_manager->getAllRulesSet(array('post__not_in' => array($post_id)))->getRules();
$has_conflicts = false;
foreach ($post_rules as $post_rule) {
foreach ($all_rules as $arule) {
if ($post_rule->isEqual($arule)) {
$rule_manager->deleteRule($post_id, $post_rule->getId());
$has_conflicts = true;
}
}
}
if ($has_conflicts) {
Brizy_Admin_Flash::instance()->add_error(
'Conflict of rules: Some rules have been deleted for restored posts. Please check them.'
);
}
}
public static function getPostSample($templateId)
{
$wp_post = get_post($templateId);
if ($wp_post->post_type !== Brizy_Admin_Templates::CP_TEMPLATE &&
$wp_post->post_type !== Brizy_Admin_Popups_Main::CP_POPUP) {
return $wp_post;
}
$ruleManager = new Brizy_Admin_Rules_Manager();
$rules = $ruleManager->getRules($wp_post->ID);
$rule = null;
// find first include rule
foreach ($rules as $rule) {
/**
* @var Brizy_Admin_Rule $rule ;
*/
if ($rule->getType() == Brizy_Admin_Rule::TYPE_INCLUDE) {
break;
}
}
if ($rule) {
switch ($rule->getAppliedFor()) {
case Brizy_Admin_Rule::POSTS :
$args = array(
'post_type' => $rule->getEntityType(),
);
$entities = $rule->getEntityValues();
// if this is an array with more that one items
if (count($rule->getEntityValues()) > 1) {
$args['post__in'] = $rule->getEntityValues();
}
// check if there are complex rules like in category or child of category
if (count($rule->getEntityValues()) == 1) {
if (is_numeric($entities[0])) {
$args['post__in'] = $rule->getEntityValues();
} else {
$parts = explode('|', $entities[0]);
if (count($parts) > 1) {
$args[$parts[1]] = [$parts[2]];
}
}
}
$args["meta_query"] = array(
array(
"key" => "brizy",
'compare' => 'NOT EXISTS',
),
);
$array = get_posts($args);
return array_pop($array);
break;
case Brizy_Admin_Rule::TAXONOMY :
$args = array(
'taxonomy' => $rule->getEntityType(),
'hide_empty' => false,
);
$entities = $rule->getEntityValues();
foreach ($entities as $val) {
if (is_numeric($val)) {
$args['term_taxonomy_id'][] = $val;
} else {
$parts = explode('|', $entities[0]);
if (count($parts) > 1) {
$args['term_taxonomy_id'][] = $parts[2];
}
}
}
$array = get_terms($args);
$term = array_pop($array);
$array = get_posts(
[
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => $term->taxonomy,
'field' => 'term_id',
'terms' => $term->term_id,
),
),
]
);
return array_pop($array);
break;
case Brizy_Admin_Rule::ARCHIVE :
return null;
break;
case Brizy_Admin_Rule::TEMPLATE :
switch ($rule->getEntityType()) {
case 'author':
$authors = get_users();
return array_pop($authors);
break;
case '404':
case 'search':
return null;
break;
case 'home_page':
$get_option = get_option('page_for_posts');
if ($get_option) {
return Brizy_Editor_Entity::isBrizyEnabled($get_option) ? null : get_post($get_option);
}
break;
case 'front_page':
$get_option = get_option('page_on_front');
if ($get_option) {
return Brizy_Editor_Entity::isBrizyEnabled($get_option) ? null : get_post($get_option);
}
break;
}
break;
}
}
}
public function saveTemplateRulesNotices()
{
global $pagenow;
if ($pagenow !== 'post.php' || get_post_type() !== Brizy_Admin_Templates::CP_TEMPLATE) {
return;
}
$post_id = get_the_ID();
if ($error = get_transient("editor_tpl_rule_errors_{$post_id}")) {
$prefix = ucfirst(Brizy_Editor::prefix());
echo '<div class="error"><p>'.$prefix.': '.$error.'</p></div>';
delete_transient("editor_tpl_rule_errors_{$post_id}");
}
}
private function obtainRulesFromPostSubmit($post_id)
{
if ($parent_id = wp_is_post_revision($post_id)) {
$post_id = $parent_id;
}
// set template type from $_POST
$type = null;
if (isset($_POST['brizy-template-type'])) {
$type = strtolower($_POST['brizy-template-type']);
if (in_array(
$type,
[
self::TYPE_SINGLE,
self::TYPE_ARCHIVE,
self::TYPE_PRODUCT_ARCHIVE,
self::TYPE_SINGLE_PRODUCT,
]
)) {
self::setTemplateType($post_id, $type);
}
} else {
return [];
}
// get rules from $_POST
$rules = [];
if ($type && isset($_POST['brizy-'.$type.'-rule-type']) && is_array($_POST['brizy-'.$type.'-rule-type'])) {
foreach ($_POST['brizy-'.$type.'-rule-type'] as $i => $ruleType) {
// ignore this rule if type is invalid
if (!in_array(
(int)$ruleType,
[
Brizy_Admin_Rule::TYPE_EXCLUDE,
Brizy_Admin_Rule::TYPE_INCLUDE,
]
)) {
continue;
}
$values = explode("|", $_POST['brizy-'.$type.'-rule-group'][$i]);
list($appliedFor, $entityType) = $values;
// ingnore invalid group value
if (!$appliedFor) {
continue;
}
$entityValues = [];
if (isset($_POST['brizy-'.$type.'-rule-entity-values'][$i])) {
$entityValues = (array)$_POST['brizy-'.$type.'-rule-entity-values'][$i];
}
$rules[] = new Brizy_Admin_Rule(null, $ruleType, $appliedFor, $entityType, $entityValues);
}
}
return $rules;
}
public function validate_template_rules($post_id, $data)
{
if (!isset($_REQUEST['brizy-template-type'])) {
return;
}
$rules = $this->obtainRulesFromPostSubmit($post_id);
if (count($rules) == 0) {
return;
}
try {
// validate rule
$ruleValidator = Brizy_Admin_Rules_ValidatorFactory::getValidator($post_id);
if (!$ruleValidator) {
$this->addError($post_id, esc_html__('Unable to get the rule validator for this post type.', 'brizy'));
header('Location: '.get_edit_post_link($post_id, 'redirect'));
exit;
}
$ruleValidator->validateRulesForPostId($rules, $post_id);
} catch (Brizy_Editor_Exceptions_DataVersionMismatch $e) {
$this->addError($post_id, esc_html__('Invalid data version.', 'brizy'));
header('Location: '.get_edit_post_link($post_id, 'redirect'));
exit;
} catch (Exception $e) {
$this->addError($post_id, $e->getMessage());
header('Location: '.get_edit_post_link($post_id, 'redirect'));
exit;
}
}
public function saveTemplateRules($post_id)
{
try {
if (!isset($_REQUEST['brizy-template-type'])) {
return;
}
$rules = $this->obtainRulesFromPostSubmit($post_id);
$ruleManager = new Brizy_Admin_Rules_Manager();
$ruleManager->setRules($post_id, $rules);
} catch (Brizy_Editor_Exceptions_DataVersionMismatch $e) {
$this->addError($post_id, esc_html__('Invalid data version.', 'brizy'));
} catch (Exception $e) {
$this->addError($post_id, $e->getMessage());
}
}
public function addError($post_id, $message)
{
set_transient("editor_tpl_rule_errors_{$post_id}", $message, 45);
}
/**
* @param $id
*
* @return mixed
*/
public static function getTemplateType($id)
{
return get_post_meta($id, self::TEMPLATE_TYPE_KEY, true);
}
/**
* @param $id
* @param $type
*/
public static function setTemplateType($id, $type)
{
update_post_meta($id, self::TEMPLATE_TYPE_KEY, $type);
}
public function start_the_excerpt($excerpt)
{
$this->isExcerpt = true;
return $excerpt;
}
public function end_the_excerpt($excerpt)
{
$this->isExcerpt = false;
return $excerpt;
}
}