-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add template editor rendering #69
Changes from all commits
6b7fde5
e681ee0
0c0f005
24adae4
8e60e81
1e66022
b161444
fdc6747
629745b
240834e
5847eb0
f171d77
75fe170
cec474e
fea137b
618b7c2
458c0e2
2fb7086
fe8b84b
8e92ac3
15edeec
06bf5e0
df28138
eb4bc47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,13 +39,21 @@ class Loader extends ComponentAbstract { | |
*/ | ||
protected $data = []; | ||
|
||
/** | ||
* The template editor. | ||
* | ||
* @var TemplateEditor | ||
*/ | ||
protected $template_editor; | ||
|
||
/** | ||
* Load the Loader. | ||
* | ||
* @return $this | ||
*/ | ||
public function init() { | ||
$this->assets = [ | ||
$this->template_editor = new TemplateEditor(); | ||
$this->assets = [ | ||
'path' => [ | ||
'entry' => $this->plugin->get_path( 'js/dist/block-editor.js' ), | ||
'editor_style' => $this->plugin->get_path( 'css/dist/blocks.editor.css' ), | ||
|
@@ -315,23 +323,19 @@ protected function render_block_template( $block, $attributes ) { | |
} | ||
|
||
if ( ! is_admin() ) { | ||
/** | ||
* The block has been added, but its values weren't saved (not even the defaults). This is a phenomenon | ||
* unique to frontend output, as the editor fetches its attributes from the form fields themselves. | ||
*/ | ||
// The block has been added, but its values weren't saved (not even the defaults). | ||
// This is unique to frontend output, as the editor fetches its attributes from the form fields themselves. | ||
$missing_schema_attributes = array_diff_key( $block->fields, $attributes ); | ||
foreach ( $missing_schema_attributes as $attribute_name => $schema ) { | ||
if ( isset( $schema->settings['default'] ) ) { | ||
$attributes[ $attribute_name ] = $schema->settings['default']; | ||
} | ||
} | ||
|
||
$this->enqueue_block_styles( $block->name, 'block' ); | ||
$did_enqueue_styles = $this->enqueue_block_styles( $block->name, 'block' ); | ||
|
||
/** | ||
* The wp_enqueue_style function handles duplicates, so we don't need to worry about multiple blocks | ||
* loading the global styles more than once. | ||
*/ | ||
// The wp_enqueue_style function handles duplicates, so we don't need to worry about multiple blocks | ||
// loading the global styles more than once. | ||
$this->enqueue_global_styles(); | ||
} | ||
|
||
|
@@ -372,16 +376,25 @@ protected function render_block_template( $block, $attributes ) { | |
|
||
ob_start(); | ||
$this->block_template( $block->name, $type ); | ||
$output = ob_get_clean(); | ||
|
||
return $output; | ||
if ( empty( $did_enqueue_styles ) ) { | ||
$this->template_editor->render_css( | ||
isset( $this->blocks[ "genesis-custom-blocks/{$block->name}" ]['templateCss'] ) | ||
? $this->blocks[ "genesis-custom-blocks/{$block->name}" ]['templateCss'] | ||
: '', | ||
$block->name | ||
); | ||
} | ||
|
||
return ob_get_clean(); | ||
} | ||
|
||
/** | ||
* Enqueues styles for the block. | ||
* | ||
* @param string $name The name of the block (slug as defined in UI). | ||
* @param string|array $type The type of template to load. | ||
* @return bool Whether this found styles and enqueued them. | ||
*/ | ||
protected function enqueue_block_styles( $name, $type = 'block' ) { | ||
$locations = []; | ||
|
@@ -397,18 +410,18 @@ protected function enqueue_block_styles( $name, $type = 'block' ) { | |
$stylesheet_path = genesis_custom_blocks()->locate_template( $locations ); | ||
$stylesheet_url = genesis_custom_blocks()->get_url_from_path( $stylesheet_path ); | ||
|
||
/** | ||
* Enqueue the stylesheet, if it exists. The wp_enqueue_style function handles duplicates, so we don't need | ||
* to worry about the same block loading its stylesheets more than once. | ||
*/ | ||
if ( ! empty( $stylesheet_url ) ) { | ||
wp_enqueue_style( | ||
"genesis-custom-blocks__block-{$name}", | ||
$stylesheet_url, | ||
[], | ||
wp_get_theme()->get( 'Version' ) | ||
); | ||
|
||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
|
@@ -473,19 +486,25 @@ protected function block_template( $name, $type = 'block' ) { | |
|
||
// This is not a load once template, so require_once is false. | ||
load_template( $theme_template, false ); | ||
} else { | ||
if ( ! current_user_can( 'edit_posts' ) || ! isset( $templates[0] ) ) { | ||
return; | ||
} | ||
// Hide the template not found notice on the frontend, unless WP_DEBUG is enabled. | ||
if ( ! is_admin() && ! ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) { | ||
return; | ||
} | ||
return; | ||
} | ||
|
||
if ( ! empty( $this->blocks[ "genesis-custom-blocks/{$name}" ]['templateMarkup'] ) ) { | ||
$this->template_editor->render_markup( $this->blocks[ "genesis-custom-blocks/{$name}" ]['templateMarkup'] ); | ||
return; | ||
} | ||
|
||
if ( ! current_user_can( 'edit_posts' ) || ! isset( $templates[0] ) ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it makes sense to introduce a custom user permission for this? Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, we could use genesis_custom_block_edit_block, but I'm not too sure it would make a big difference. Here's the main context they would see this in: If we used But either way would probably be fine. |
||
return; | ||
} | ||
|
||
// Only show the template not found notice on the frontend if WP_DEBUG is enabled. | ||
if ( is_admin() || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) { | ||
printf( | ||
'<div class="notice notice-warning">%s</div>', | ||
wp_kses_post( | ||
// Translators: Placeholder is a file path. | ||
sprintf( __( 'Template file %s not found.', 'genesis-custom-blocks' ), '<code>' . esc_html( $templates[0] ) . '</code>' ) | ||
/* translators: %1$s: file path */ | ||
sprintf( __( 'Template file %1$s not found.', 'genesis-custom-blocks' ), '<code>' . esc_html( $templates[0] ) . '</code>' ) | ||
) | ||
); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
/** | ||
* TemplateEditor. | ||
* | ||
* @package Genesis\CustomBlocks | ||
* @copyright Copyright(c) 2021, Genesis Custom Blocks | ||
* @license http://opensource.org/licenses/GPL-2.0 GNU General Public License, version 2 (GPL-2.0) | ||
*/ | ||
|
||
namespace Genesis\CustomBlocks\Blocks; | ||
|
||
/** | ||
* Class TemplateEditor | ||
*/ | ||
class TemplateEditor { | ||
|
||
/** | ||
* The block names that have had their CSS rendered. | ||
* | ||
* @var string[] | ||
*/ | ||
public $blocks_with_rendered_css = []; | ||
|
||
/** | ||
* Renders markup that was entered in the template editor. | ||
* | ||
* @param string $markup The markup to render. | ||
*/ | ||
public function render_markup( $markup ) { | ||
$rendered = preg_replace_callback( | ||
'#{{(\S+?)}}#', | ||
static function( $matches ) { | ||
ob_start(); | ||
block_field( $matches[1] ); | ||
return ob_get_clean(); | ||
}, | ||
$markup | ||
); | ||
|
||
// Escape characters before { should be stripped, like \{\{example\}\}. | ||
// Like if they have a tutorial on Mustache and need the template to render {{example}}. | ||
$rendered = preg_replace( '#\\\{\\\{(\S+?)\\\}\\\}#', '{{\1}}', $rendered ); | ||
|
||
echo wp_kses_post( $rendered ); | ||
} | ||
|
||
/** | ||
* Renders CSS that was entered in the template editor. | ||
* | ||
* @param string $css The CSS to render, if any. | ||
* @param string $block_name The block name, without the genesis-custom-blocks/ namespace. | ||
*/ | ||
public function render_css( $css, $block_name ) { | ||
if ( empty( $css ) || in_array( $block_name, $this->blocks_with_rendered_css, true ) ) { | ||
return; | ||
} | ||
|
||
$this->blocks_with_rendered_css[] = $block_name; | ||
|
||
?> | ||
<style><?php echo wp_strip_all_tags( $css ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></style> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like it! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @johnstonphilip, thanks a lot! |
||
<?php | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
/** | ||
* A mock template in the template editor, testing all fields. | ||
* | ||
* @package Genesis\CustomBlocks | ||
*/ | ||
|
||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaping could interfere with testing this template output. | ||
|
||
$fields = [ | ||
'textarea', | ||
'url', | ||
'email', | ||
'number', | ||
'color', | ||
'image', | ||
'select', | ||
'toggle', | ||
'range', | ||
'checkbox', | ||
'radio', | ||
'text', | ||
'multiselect', | ||
]; | ||
|
||
ob_start(); | ||
|
||
foreach ( $fields as $field ) : | ||
?> | ||
<p> | ||
<?php | ||
printf( | ||
'Here is the result for %1$s: %2$s', | ||
$field, | ||
'{{' . $field . '}}' | ||
); | ||
?> | ||
</p> | ||
<?php | ||
endforeach; | ||
|
||
echo 'Here are escaped brackets: \{\{example\}\}'; | ||
|
||
return ob_get_clean(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This renders the markup: