-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Changes from all commits
bd4206e
d50d848
05ce98c
98dc70a
3905f24
7404dfc
179806b
062dc68
deb6184
453b98b
075502d
7a1a553
b3feca4
956e28f
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 |
---|---|---|
@@ -0,0 +1,4 @@ | ||
</div> | ||
<?php wp_footer(); ?> | ||
</body> | ||
</html> |
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' ); |
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"> |
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 ); | ||
|
||
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(); |
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,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 ) ) { | ||
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. 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 |
---|---|---|
@@ -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 ) { | ||
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 don't think the component file is the right place for this. I get it (don't like it either) with 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've thought about it, and tbh I might even go as far as creating a new folder ( |
||
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 ) { | ||
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. |
||
registerPlugin( 'fse-template-sidebar', { | ||
render: TemplateSidebar, | ||
} ); | ||
} |
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.
we need something here for post types with no
$template_id
. On my clean install, I triedyeah, null-coalescing operator because PHP 7 has it and I won't listen otherwise.