Skip to content
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

Full Site Editing: Theme and Front-end Rendering #32865

Closed
wants to merge 14 commits into from
4 changes: 4 additions & 0 deletions apps/full-site-editing/blank-theme/footer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
</div>
<?php wp_footer(); ?>
</body>
</html>
8 changes: 8 additions & 0 deletions apps/full-site-editing/blank-theme/functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

function fse_setup() {
add_theme_support( 'align-wide' );
add_theme_support( 'title-tag' );
}

add_action( 'after_setup_theme', 'fse_setup' );
10 changes: 10 additions & 0 deletions apps/full-site-editing/blank-theme/header.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="profile" href="https://gmpg.org/xfn/11" />
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<div id="content" class="site-content">
50 changes: 50 additions & 0 deletions apps/full-site-editing/blank-theme/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

get_header();

$template_hierarchy = json_decode( get_option( 'template_hierarchy' ) );

if ( is_singular() && have_posts() ) {
the_post();

$post_id = get_the_ID();
$template_id = get_post_meta( $post_id, 'wp_template_id', true );

if ( ! $template_id ) {
if ( isset( $template_hierarchy->singular ) ) {
$template_id = $template_hierarchy->singular;
} else if ( isset( $template_hierarchy->index ) ) {
$template_id = $template_hierarchy->index;
}
}

$template = get_post( $template_id );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need something here for post types with no $template_id. On my clean install, I tried

$template = get_post( $template_id ?? null );

yeah, null-coalescing operator because PHP 7 has it and I won't listen otherwise.

Before After
before after


if ( $template_id !== $post_id && $template ) {
echo apply_filters( 'the_content', $template->post_content );
} else {
the_content();
}
} else {
$post_type = get_post_type();

if ( isset( $template_hierarchy->$post_type ) ) {
$template_id = $template_hierarchy->$post_type;
} else if ( isset( $template_hierarchy->index ) ) {
$template_id = $template_hierarchy->index;
}

$template = get_post( $template_id );

if ( $template ) {
echo apply_filters( 'the_content', $template->post_content );
} else {
while( have_posts() ) {
the_post(); ?>
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>
<div><?php the_content(); ?></div>
<?php }
}
}

get_footer();
3 changes: 3 additions & 0 deletions apps/full-site-editing/blank-theme/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/**
* Theme Name: Blank Theme
*/
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global fullSiteEditing */
/**
* WordPress dependencies
*/
Expand All @@ -10,18 +11,20 @@ import { __ } from '@wordpress/i18n';
import edit from './edit';
import './style.scss';

registerBlockType( 'a8c/post-content', {
title: __( 'Content Slot' ),
description: __( 'Placeholder for a post or a page.' ),
icon: 'layout',
category: 'layout',
supports: {
align: [ 'wide', 'full' ],
anchor: true,
html: false,
multiple: false,
reusable: false,
},
edit,
save: () => null,
} );
if ( 'wp_template' === fullSiteEditing.editorPostType ) {
registerBlockType( 'a8c/post-content', {
title: __( 'Content Slot' ),
description: __( 'Placeholder for a post or a page.' ),
icon: 'layout',
category: 'layout',
supports: {
align: [ 'wide', 'full' ],
anchor: true,
html: false,
multiple: false,
reusable: false,
},
edit,
save: () => null,
} );
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
<?php

function render_post_content_block( $attributes, $content ) {
rodrigoi marked this conversation as resolved.
Show resolved Hide resolved
// Early return to avoid infinite loops in the REST API
if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity what does the trace look like? Are there similar rendering conditions we need to be aware of?

return $content;
}

$align = isset( $attributes['align'] ) ? ' align' . $attributes['align'] : '';

$content = '<div class="post-content'. $align . '">'
. __( '[Renders some content]' )
. '</div>';
if ( is_singular() ) {
$post_id = get_the_ID();
$post_type = get_post_type();
$template_id = get_post_meta( $post_id, 'wp_template_id', true );

return $content;
// Early return to avoid the infinite loop of a template rendering itself.
if ( 'wp_template' === $post_type || $template_id === $post_id ) {
return $content;
}

$content = '<div class="post-content'. $align . '">'
. apply_filters( 'the_content', get_the_content() )
. '</div>';

return $content;
} else {
$content = '<div class="post-content'. $align . '">';
while( have_posts() ) {
the_post();
$content .= '<h2><a href="' . get_the_permalink(). '">' . apply_filters( 'the_title', get_the_title() ) . '</a></h2>';
$content .= '<div>' . apply_filters( 'the_content', get_the_content() ) . '</div>';
}
$content .= '</div>';

return $content;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global fullSiteEditing */
/**
* WordPress dependencies
*/
Expand All @@ -10,21 +11,23 @@ import { __ } from '@wordpress/i18n';
import edit from './edit';
import './style.scss';

registerBlockType( 'a8c/template', {
title: __( 'Template Part' ),
description: __( 'Display a template part.' ),
icon: 'layout',
category: 'layout',
attributes: {
selectedPostId: { type: 'number' },
selectedPostType: { type: 'string' },
},
supports: {
align: [ 'wide', 'full' ],
anchor: true,
html: false,
reusable: false,
},
edit,
save: () => null,
} );
if ( 'wp_template' === fullSiteEditing.editorPostType ) {
registerBlockType( 'a8c/template', {
title: __( 'Template Part' ),
description: __( 'Display a template part.' ),
icon: 'layout',
category: 'layout',
attributes: {
selectedPostId: { type: 'number' },
selectedPostType: { type: 'string' },
},
supports: {
align: [ 'wide', 'full' ],
anchor: true,
html: false,
reusable: false,
},
edit,
save: () => null,
} );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* global fullSiteEditing */
/**
* External dependencies
*/
import { debounce, get, filter, map, omit } from 'lodash';

/**
* WordPress dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { CheckboxControl, PanelBody } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
import { Fragment, useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';

const getTemplateHierarchyOption = postTypes => {
const options = map( filter( postTypes, 'viewable' ), postType => ( {
label: get( postType, [ 'labels', 'name' ] ),
slug: get( postType, 'slug' ),
} ) );
return [
{ label: __( 'Default' ), slug: 'index' },
{ label: __( 'Default Singular' ), slug: 'singular' },
...options,
];
};

const updateTemplateHierarchyOption = debounce( async hierarchy => {
await apiFetch( {
path: '/wp/v2/settings',
data: {
template_hierarchy: JSON.stringify( hierarchy ),
},
method: 'POST',
} );
}, 500 );

const TemplateHierarchySidebar = withSelect( select => ( {
templateHierarchyOptions: getTemplateHierarchyOption(
select( 'core' ).getEntityRecords( 'root', 'postType' )
),
templateId: select( 'core/editor' ).getCurrentPostId(),
} ) )( ( { templateHierarchyOptions, templateId } ) => {
const [ hierarchy, setHierarchy ] = useState( {} );

useEffect( () => {
const fetchTemplateHierarchySetting = async () => {
const settings = await apiFetch( {
path: '/wp/v2/settings',
} );
setHierarchy( JSON.parse( get( settings, 'template_hierarchy' ) ) );
};
fetchTemplateHierarchySetting();
}, [] );

const isCurrentTemplateAssignedToScreen = slug => templateId === hierarchy[ slug ];

const hasScreenAnotherTemplate = slug => !! hierarchy[ slug ] && templateId !== hierarchy[ slug ];

const onChange = slug => () => {
const newHierarchy = isCurrentTemplateAssignedToScreen( slug )
? omit( hierarchy, slug )
: { ...hierarchy, [ slug ]: templateId };
setHierarchy( newHierarchy );
updateTemplateHierarchyOption( newHierarchy );
};

return (
<Fragment>
<PluginSidebarMoreMenuItem target="fse-template-sidebar" icon="layout">
{ __( 'Template Hierarchy' ) }
</PluginSidebarMoreMenuItem>
<PluginSidebar icon="layout" name="fse-template-sidebar" title={ __( 'Template Hierarchy' ) }>
<PanelBody>
<p>{ __( 'Assign this template to any of these screens:' ) }</p>
{ map( templateHierarchyOptions, ( { label, slug } ) => (
<div>
<CheckboxControl
checked={ isCurrentTemplateAssignedToScreen( slug ) }
disabled={ hasScreenAnotherTemplate( slug ) }
help={
hasScreenAnotherTemplate( slug ) && (
<Fragment>
{ __( 'Another template is assigned to this screen. ' ) }
<a href={ `post.php?post=${ hierarchy[ slug ] }&action=edit` }>
{ __( 'Edit' ) }
</a>
</Fragment>
)
}
label={ label }
onChange={ onChange( slug ) }
/>
</div>
) ) }
</PanelBody>
</PluginSidebar>
</Fragment>
);
} );

if ( 'wp_template' === fullSiteEditing.editorPostType ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the component file is the right place for this. I get it (don't like it either) with blocks, but I expect components to export. How do we feel about moving this (and import { registerPlugin } from '@wordpress/plugins';) to full-site-editing-plugin/index.js ??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've thought about it, and tbh I might even go as far as creating a new folder (plugins?), and keep the index as clean as possible.

registerPlugin( 'fse-template-hierarchy-sidebar', {
render: TemplateHierarchySidebar,
} );
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* global fullSiteEditing */
/* eslint-disable wpcalypso/import-docblock */
/**
* External dependencies
*/
import { get } from 'lodash';

/**
* WordPress dependencies
*/
import { PanelBody } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import { withDispatch, withSelect } from '@wordpress/data';
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
import { Fragment } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';

/**
* Internal dependencies
*/
import PostAutocomplete from '../post-autocomplete';

const TemplateSidebar = compose(
withDispatch( dispatch => ( {
setTemplateId: templateId =>
dispatch( 'core/editor' ).editPost( { meta: { wp_template_id: templateId } } ),
} ) ),
withSelect( select => {
const { getEntityRecord } = select( 'core' );
const templateId = get(
select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
'wp_template_id'
);
return {
selectedTemplate: getEntityRecord( 'postType', 'wp_template', templateId ),
};
} )
)( ( { setTemplateId, selectedTemplate } ) => {
const onSelectTemplate = ( { id } ) => {
setTemplateId( parseInt( id, 10 ) );
};

return (
<Fragment>
<PluginSidebarMoreMenuItem target="fse-template-sidebar" icon="layout">
{ __( 'Template' ) }
</PluginSidebarMoreMenuItem>
<PluginSidebar icon="layout" name="fse-template-sidebar" title={ __( 'Template' ) }>
<PanelBody>
{ __( 'Select a template' ) }
<PostAutocomplete
initialValue={ get( selectedTemplate, [ 'title', 'rendered' ] ) }
onSelectPost={ onSelectTemplate }
postType="wp_template"
/>
</PanelBody>
</PluginSidebar>
</Fragment>
);
} );

if ( 'wp_template' !== fullSiteEditing.editorPostType ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registerPlugin( 'fse-template-sidebar', {
render: TemplateSidebar,
} );
}
Loading