Full Site Editing - Version 0.2

Version Description

  • Bug fixes and performance improvements.
Download this release

Release Info

Developer obenland
Plugin Icon wp plugin Full Site Editing
Version 0.2
Comparing to
See all releases

Code changes from version 0.1.1 to 0.2

Files changed (43) hide show
  1. full-site-editing-plugin.php +65 -7
  2. full-site-editing/blocks/navigation-menu/edit.js +46 -0
  3. full-site-editing/blocks/navigation-menu/index.js +38 -0
  4. full-site-editing/blocks/navigation-menu/index.php +95 -0
  5. full-site-editing/blocks/navigation-menu/style.scss +140 -0
  6. full-site-editing/blocks/post-content/index.js +18 -17
  7. full-site-editing/blocks/post-content/index.php +8 -5
  8. full-site-editing/blocks/site-description/edit.js +92 -0
  9. full-site-editing/blocks/site-description/index.js +25 -0
  10. full-site-editing/blocks/site-description/index.php +27 -0
  11. full-site-editing/blocks/site-description/style.scss +10 -0
  12. full-site-editing/blocks/site-logo/edit.js +41 -0
  13. full-site-editing/blocks/site-logo/index.js +21 -0
  14. full-site-editing/blocks/site-logo/index.php +44 -0
  15. full-site-editing/blocks/site-logo/style.scss +3 -0
  16. full-site-editing/blocks/template/edit.js +29 -7
  17. full-site-editing/blocks/template/index.js +1 -1
  18. full-site-editing/blocks/template/index.php +5 -3
  19. full-site-editing/blocks/template/style.scss +17 -0
  20. full-site-editing/class-full-site-editing.php +254 -2
  21. full-site-editing/dist/full-site-editing.css +1 -1
  22. full-site-editing/dist/full-site-editing.deps.json +1 -1
  23. full-site-editing/dist/full-site-editing.js +2 -2
  24. full-site-editing/dist/full-site-editing.rtl.css +1 -1
  25. full-site-editing/index.js +5 -0
  26. full-site-editing/plugins/close-button-override/index.js +24 -0
  27. full-site-editing/plugins/template-update-confirmation/button.js +143 -0
  28. full-site-editing/plugins/template-update-confirmation/index.js +21 -0
  29. full-site-editing/plugins/template-update-confirmation/panel.js +40 -0
  30. full-site-editing/utils/class-a8c-wp-template-data-inserter.php +105 -0
  31. full-site-editing/utils/class-a8c-wp-template.php +200 -0
  32. full-site-editing/utils/replace-template-parts.php +68 -0
  33. lib/feature-flags/class-a8c-full-site-editing-feature-flags.php +118 -0
  34. readme.txt +4 -1
  35. starter-page-templates/class-starter-page-templates.php +97 -22
  36. starter-page-templates/dist/starter-page-templates.css +1 -1
  37. starter-page-templates/dist/starter-page-templates.deps.json +1 -1
  38. starter-page-templates/dist/starter-page-templates.js +2 -2
  39. starter-page-templates/dist/starter-page-templates.rtl.css +1 -1
  40. starter-page-templates/page-template-modal/components/template-selector-control.js +1 -1
  41. starter-page-templates/page-template-modal/index.js +113 -62
  42. starter-page-templates/page-template-modal/styles/starter-page-templates-editor.scss +33 -13
  43. starter-page-templates/page-template-modal/utils/tracking.js +59 -0
full-site-editing-plugin.php CHANGED
@@ -2,7 +2,7 @@
2
/**
3
* Plugin Name: Full Site Editing
4
* Description: Enhances your page creation workflow within the Block Editor.
5
- * Version: 0.1.1
6
* Author: Automattic
7
* Author URI: https://automattic.com/wordpress-plugins/
8
* License: GPLv2 or later
@@ -15,25 +15,48 @@
15
* Load Full Site Editing.
16
*/
17
function a8c_load_full_site_editing() {
18
- require_once __DIR__ . '/lib/feature-flags/feature-flags.php';
19
require_once __DIR__ . '/full-site-editing/blocks/post-content/index.php';
20
require_once __DIR__ . '/full-site-editing/blocks/template/index.php';
21
require_once __DIR__ . '/full-site-editing/class-a8c-rest-templates-controller.php';
22
require_once __DIR__ . '/full-site-editing/class-full-site-editing.php';
23
24
Full_Site_Editing::get_instance();
25
}
26
- //add_action( 'plugins_loaded', 'a8c_load_full_site_editing' );
27
28
/**
29
* Load Posts List Block.
30
*/
31
function a8c_load_posts_list_block() {
32
- if ( function_exists( 'is_automattician' ) && ! is_automattician() ) {
33
return;
34
}
35
36
- if ( class_exists( 'Posts_List_Block' ) ) {
37
return;
38
}
39
@@ -48,7 +71,14 @@ add_action( 'plugins_loaded', 'a8c_load_posts_list_block' );
48
* Load Starter_Page_Templates.
49
*/
50
function a8c_load_starter_page_templates() {
51
- if ( function_exists( 'is_automattician' ) && ! is_automattician() ) {
52
return;
53
}
54
@@ -56,4 +86,32 @@ function a8c_load_starter_page_templates() {
56
57
Starter_Page_Templates::get_instance();
58
}
59
- //add_action( 'plugins_loaded', 'a8c_load_starter_page_templates' );
2
/**
3
* Plugin Name: Full Site Editing
4
* Description: Enhances your page creation workflow within the Block Editor.
5
+ * Version: 0.2
6
* Author: Automattic
7
* Author URI: https://automattic.com/wordpress-plugins/
8
* License: GPLv2 or later
15
* Load Full Site Editing.
16
*/
17
function a8c_load_full_site_editing() {
18
+ /**
19
+ * Can be used to disable Full Site Editing functionality.
20
+ *
21
+ * @since 0.2
22
+ *
23
+ * @param bool true if Full Site Editing should be disabled, false otherwise.
24
+ */
25
+ if ( apply_filters( 'a8c_disable_full_site_editing', false ) ) {
26
+ return;
27
+ }
28
+
29
+ require_once __DIR__ . '/lib/feature-flags/class-a8c-full-site-editing-feature-flags.php';
30
+ require_once __DIR__ . '/full-site-editing/blocks/navigation-menu/index.php';
31
require_once __DIR__ . '/full-site-editing/blocks/post-content/index.php';
32
+ require_once __DIR__ . '/full-site-editing/blocks/site-description/index.php';
33
require_once __DIR__ . '/full-site-editing/blocks/template/index.php';
34
+ require_once __DIR__ . '/full-site-editing/blocks/site-logo/index.php';
35
require_once __DIR__ . '/full-site-editing/class-a8c-rest-templates-controller.php';
36
require_once __DIR__ . '/full-site-editing/class-full-site-editing.php';
37
+ require_once __DIR__ . '/full-site-editing/utils/class-a8c-wp-template.php';
38
+ require_once __DIR__ . '/full-site-editing/utils/replace-template-parts.php';
39
40
Full_Site_Editing::get_instance();
41
}
42
+ add_action( 'plugins_loaded', 'a8c_load_full_site_editing' );
43
44
/**
45
* Load Posts List Block.
46
*/
47
function a8c_load_posts_list_block() {
48
+ if ( class_exists( 'Posts_List_Block' ) ) {
49
return;
50
}
51
52
+ /**
53
+ * Can be used to disable the Post List Block.
54
+ *
55
+ * @since 0.2
56
+ *
57
+ * @param bool true if Post List Block should be disabled, false otherwise.
58
+ */
59
+ if ( apply_filters( 'a8c_disable_post_list_block', false ) ) {
60
return;
61
}
62
71
* Load Starter_Page_Templates.
72
*/
73
function a8c_load_starter_page_templates() {
74
+ /**
75
+ * Can be used to disable the Starter Page Templates.
76
+ *
77
+ * @since 0.2
78
+ *
79
+ * @param bool true if Starter Page Templates should be disabled, false otherwise.
80
+ */
81
+ if ( apply_filters( 'a8c_disable_starter_page_templates', false ) ) {
82
return;
83
}
84
86
87
Starter_Page_Templates::get_instance();
88
}
89
+ add_action( 'plugins_loaded', 'a8c_load_starter_page_templates' );
90
+
91
+ /**
92
+ * Set up the required plugin data on activation.
93
+ *
94
+ * Creates the default template that all pages use along with
95
+ * the required template parts like header and footer.
96
+ */
97
+ function a8c_fse_on_plugin_activation() {
98
+ /**
99
+ * Can be used to disable Full Site Editing functionality.
100
+ *
101
+ * @since 0.1
102
+ *
103
+ * @param bool true if Full Site Editing should be disabled, false otherwise.
104
+ */
105
+ if ( apply_filters( 'a8c_disable_full_site_editing', false ) ) {
106
+ return;
107
+ }
108
+
109
+ require_once __DIR__ . '/full-site-editing/class-full-site-editing.php';
110
+ $fse = Full_Site_Editing::get_instance();
111
+ $fse->register_template_post_types();
112
+
113
+ require_once __DIR__ . '/full-site-editing/utils/class-a8c-wp-template-data-inserter.php';
114
+ $data_inserter = new A8C_WP_Template_Data_Inserter();
115
+ $data_inserter->insert_default_template_data();
116
+ }
117
+ register_activation_hook( __FILE__, 'a8c_fse_on_plugin_activation' );
full-site-editing/blocks/navigation-menu/edit.js ADDED
@@ -0,0 +1,46 @@
1
+ /* eslint-disable wpcalypso/jsx-classname-namespace */
2
+ /**
3
+ * External dependencies
4
+ */
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { IconButton, ServerSideRender, Toolbar } from '@wordpress/components';
10
+ import { BlockControls } from '@wordpress/editor';
11
+ import { addQueryArgs } from '@wordpress/url';
12
+ import { Fragment } from '@wordpress/element';
13
+ import { __ } from '@wordpress/i18n';
14
+
15
+ /**
16
+ * Internal dependencies
17
+ */
18
+
19
+ const NavigationMenuEdit = ( { attributes } ) => {
20
+ const url = addQueryArgs( 'customize.php', {
21
+ 'autofocus[panel]': 'nav_menus',
22
+ return: window.location.href,
23
+ } );
24
+
25
+ return (
26
+ <Fragment>
27
+ <BlockControls>
28
+ <Toolbar className="wp-block-a8c-navigation-menu-toolbar">
29
+ <IconButton
30
+ icon="edit"
31
+ label={ __( 'Edit Menu' ) }
32
+ href={ url }
33
+ className="components-toolbar__control"
34
+ />
35
+ </Toolbar>
36
+ </BlockControls>
37
+ <ServerSideRender
38
+ attributes={ attributes }
39
+ block="a8c/navigation-menu"
40
+ className="wp-block-a8c-navigation-menu"
41
+ />
42
+ </Fragment>
43
+ );
44
+ };
45
+
46
+ export default NavigationMenuEdit;
full-site-editing/blocks/navigation-menu/index.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { registerBlockType } from '@wordpress/blocks';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import edit from './edit';
11
+ import './style.scss';
12
+
13
+ const icon = (
14
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
15
+ <path fill="none" d="M0 0h24v24H0V0z" />
16
+ <path d="M12 7.27l4.28 10.43-3.47-1.53-.81-.36-.81.36-3.47 1.53L12 7.27M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z" />
17
+ </svg>
18
+ );
19
+
20
+ registerBlockType( 'a8c/navigation-menu', {
21
+ title: __( 'Navigation Menu' ),
22
+ description: __( 'Visual placeholder for site-wide navigation and menus.' ),
23
+ icon,
24
+ category: 'layout',
25
+ supports: {
26
+ html: false,
27
+ multiple: false,
28
+ reusable: false,
29
+ },
30
+ attributes: {
31
+ themeLocation: {
32
+ type: 'string',
33
+ default: 'main-1',
34
+ },
35
+ },
36
+ edit,
37
+ save: () => null,
38
+ } );
full-site-editing/blocks/navigation-menu/index.php ADDED
@@ -0,0 +1,95 @@
1
+ <?php
2
+ /**
3
+ * Render navigation menus.
4
+ *
5
+ * @package full-site-editing
6
+ */
7
+
8
+ /**
9
+ * Determines necessary wp_nav_menu() parameters by given theme location.
10
+ *
11
+ * @param string $location Theme location.
12
+ * @return array
13
+ */
14
+ function get_menu_params_by_theme_location( $location ) {
15
+ switch ( $location ) {
16
+ case 'footer':
17
+ $params = [
18
+ 'theme_location' => 'footer',
19
+ 'menu_class' => 'footer-menu',
20
+ 'depth' => 1,
21
+ ];
22
+ break;
23
+ case 'social':
24
+ $params = [
25
+ 'theme_location' => 'social',
26
+ 'menu_class' => 'social-links-menu',
27
+ 'link_before' => '<span class="screen-reader-text">',
28
+ 'link_after' => '</span>' . twentynineteen_get_icon_svg( 'link' ),
29
+ 'depth' => 1,
30
+ ];
31
+ break;
32
+ case 'main-1':
33
+ default:
34
+ $params = [
35
+ 'theme_location' => 'menu-1',
36
+ 'menu_class' => 'main-menu',
37
+ 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
38
+ 'depth' => 1,
39
+ ];
40
+ break;
41
+ }
42
+ return $params;
43
+ }
44
+
45
+ /**
46
+ * Determines necessary attributes for the wrapping `nav` element.
47
+ *
48
+ * @param string $location Theme location.
49
+ * @return array
50
+ */
51
+ function get_wrapper_attributes_by_theme_location( $location ) {
52
+ switch ( $location ) {
53
+ case 'footer':
54
+ $attributes = [
55
+ 'class' => 'footer-navigation',
56
+ 'label' => 'Footer Menu',
57
+ ];
58
+ break;
59
+ case 'social':
60
+ $attributes = [
61
+ 'class' => 'social-navigation',
62
+ 'label' => 'Social Links Menu',
63
+ ];
64
+ break;
65
+ case 'main-1':
66
+ default:
67
+ $attributes = [
68
+ 'class' => 'main-navigation',
69
+ 'label' => 'Top Menu',
70
+ ];
71
+ break;
72
+ }
73
+ return $attributes;
74
+ }
75
+
76
+ /**
77
+ * Renders post content.
78
+ *
79
+ * @param array $attributes Block attributes.
80
+ * @return string
81
+ */
82
+ function render_navigation_menu_block( $attributes ) {
83
+ $location = ! empty( $attributes['themeLocation'] ) ? $attributes['themeLocation'] : null;
84
+ $wrapper_attr = get_wrapper_attributes_by_theme_location( $location );
85
+ ob_start();
86
+ // phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralText
87
+ ?>
88
+ <nav class="<?php echo esc_attr( $wrapper_attr['class'] ); ?>" aria-label="<?php esc_attr_e( $wrapper_attr['label'], 'twentynineteen' ); ?>">
89
+ <?php
90
+ wp_nav_menu( get_menu_params_by_theme_location( $location ) );
91
+ ?>
92
+ </nav><!-- #site-navigation -->
93
+ <?php
94
+ return ob_get_clean();
95
+ }
full-site-editing/blocks/navigation-menu/style.scss ADDED
@@ -0,0 +1,140 @@
1
+ .wp-block-a8c-navigation-menu .main-navigation {
2
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
3
+ font-size: 1.125em;
4
+ font-weight: 700;
5
+ letter-spacing: -0.02em;
6
+ line-height: 1.2;
7
+ pointer-events: none;
8
+ -webkit-font-smoothing: antialiased;
9
+ }
10
+
11
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu {
12
+ display: inline-block;
13
+ margin: 0;
14
+ padding: 0;
15
+ }
16
+
17
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li {
18
+ color: #0073aa;
19
+ display: inline;
20
+ position: relative;
21
+ }
22
+
23
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li > a {
24
+ font-weight: 700;
25
+ color: #0073aa;
26
+ margin-right: 0.5rem;
27
+ }
28
+
29
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li:last-child > a, .main-navigation .main-menu > li:last-child.menu-item-has-children .submenu-expand {
30
+ margin-right: 0;
31
+ }
32
+
33
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li.menu-item-has-children > a {
34
+ margin-right: 0.125rem;
35
+ }
36
+
37
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li.menu-item-has-children {
38
+ display: inline-block;
39
+ position: inherit;
40
+ }
41
+
42
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li.menu-item-has-children .submenu-expand {
43
+ display: inline-block;
44
+ margin-right: 0.25rem;
45
+ }
46
+
47
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li.menu-item-has-children .submenu-expand svg {
48
+ position: relative;
49
+ top: 0.3rem;
50
+ }
51
+
52
+ .wp-block-a8c-navigation-menu .main-navigation .main-menu > li > a:hover, .main-navigation .main-menu > li > a:hover + svg {
53
+ color: #005177;
54
+ }
55
+
56
+ .wp-block-a8c-navigation-menu .main-navigation svg {
57
+ transition: fill 120ms ease-in-out;
58
+ fill: currentColor;
59
+ }
60
+
61
+ .wp-block-a8c-navigation-menu .main-navigation a {
62
+ text-decoration: none;
63
+ }
64
+
65
+ .wp-block-a8c-navigation-menu .main-navigation button {
66
+ display: inline-block;
67
+ border: none;
68
+ padding: 0;
69
+ margin: 0;
70
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
71
+ font-size: 0.88889em;
72
+ font-weight: 700;
73
+ line-height: 1.2;
74
+ text-decoration: none;
75
+ vertical-align: bottom;
76
+ background: transparent;
77
+ color: inherit;
78
+ cursor: pointer;
79
+ transition: background 250ms ease-in-out, transform 150ms ease;
80
+ -webkit-appearance: none;
81
+ -moz-appearance: none;
82
+ }
83
+
84
+ .wp-block-a8c-navigation-menu .main-menu-more {
85
+ display: none;
86
+ }
87
+
88
+ .wp-block-a8c-navigation-menu .social-navigation {
89
+ line-height: 1.25;
90
+ margin-top: calc( 1rem / 2 );
91
+ text-align: left;
92
+ }
93
+
94
+ .wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu {
95
+ content: '';
96
+ display: inline-block;
97
+ margin: 0;
98
+ padding: 0;
99
+ }
100
+
101
+ .wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu li {
102
+ display: inline-block;
103
+ vertical-align: bottom;
104
+ vertical-align: -webkit-baseline-middle;
105
+ list-style: none;
106
+ }
107
+
108
+ .wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu li a svg {
109
+ display: block;
110
+ width: 32px;
111
+ height: 32px;
112
+ transform: translateZ( 0 );
113
+ }
114
+
115
+ .wp-block-a8c-navigation-menu .footer-navigation .footer-menu {
116
+ display: inline;
117
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
118
+ font-size: 0.71111em;
119
+ padding-left: 0;
120
+ }
121
+
122
+ .wp-block-a8c-navigation-menu .footer-navigation .footer-menu li {
123
+ display: inline;
124
+ margin-right: 1rem;
125
+ }
126
+
127
+ .wp-block-a8c-navigation-menu .footer-navigation .footer-menu a {
128
+ text-decoration: none;
129
+ color: #767676;
130
+ }
131
+
132
+ .wp-block-a8c-navigation-menu .footer-navigation .footer-menu a:hover {
133
+ text-decoration: none;
134
+ color: #0073aa;
135
+ }
136
+
137
+ .editor-styles-wrapper .wp-block-a8c-navigation-menu-toolbar a,
138
+ .editor-styles-wrapper .wp-block-a8c-navigation-menu-toolbar a:hover {
139
+ color: #555d66;
140
+ }
full-site-editing/blocks/post-content/index.js CHANGED
@@ -3,6 +3,7 @@
3
* WordPress dependencies
4
*/
5
import { registerBlockType } from '@wordpress/blocks';
6
import { __ } from '@wordpress/i18n';
7
8
/**
@@ -11,20 +12,20 @@ import { __ } from '@wordpress/i18n';
11
import edit from './edit';
12
import './style.scss';
13
14
- if ( 'wp_template' === fullSiteEditing.editorPostType ) {
15
- registerBlockType( 'a8c/post-content', {
16
- title: __( 'Content Slot' ),
17
- description: __( 'Placeholder for a post or a page.' ),
18
- icon: 'layout',
19
- category: 'layout',
20
- supports: {
21
- align: [ 'wide', 'full' ],
22
- anchor: true,
23
- html: false,
24
- multiple: false,
25
- reusable: false,
26
- },
27
- edit,
28
- save: () => null,
29
- } );
30
- }
3
* WordPress dependencies
4
*/
5
import { registerBlockType } from '@wordpress/blocks';
6
+ import { InnerBlocks } from '@wordpress/block-editor';
7
import { __ } from '@wordpress/i18n';
8
9
/**
12
import edit from './edit';
13
import './style.scss';
14
15
+ const isTemplatePostType = 'wp_template' === fullSiteEditing.editorPostType;
16
+
17
+ registerBlockType( 'a8c/post-content', {
18
+ title: __( 'Content Slot' ),
19
+ description: __( 'Placeholder for a post or a page.' ),
20
+ icon: 'layout',
21
+ category: 'layout',
22
+ supports: {
23
+ align: [ 'wide', 'full' ],
24
+ anchor: true,
25
+ html: false,
26
+ multiple: false,
27
+ reusable: false,
28
+ },
29
+ edit: isTemplatePostType ? edit : () => <InnerBlocks />,
30
+ save: isTemplatePostType ? () => null : () => <InnerBlocks.Content />,
31
+ } );
full-site-editing/blocks/post-content/index.php CHANGED
@@ -13,13 +13,13 @@
13
* @return string
14
*/
15
function render_post_content_block( $attributes, $content ) {
16
- // Early return to avoid infinite loops in the REST API
17
if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
18
return $content;
19
}
20
21
- $post_id = get_the_ID();
22
- $post_type = get_post_type();
23
$template_id = get_post_meta( $post_id, '_wp_template_id', true );
24
25
// Early return to avoid the infinite loop of a template rendering itself.
@@ -32,8 +32,11 @@ function render_post_content_block( $attributes, $content ) {
32
ob_start();
33
?>
34
35
- <div class="post-content<?php echo $align; ?>">
36
- <?php echo apply_filters( 'the_content', get_the_content() ); ?>
37
</div><!-- .post-content -->
38
39
<?php
13
* @return string
14
*/
15
function render_post_content_block( $attributes, $content ) {
16
+ // Early return to avoid infinite loops in the REST API.
17
if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
18
return $content;
19
}
20
21
+ $post_id = get_the_ID();
22
+ $post_type = get_post_type();
23
$template_id = get_post_meta( $post_id, '_wp_template_id', true );
24
25
// Early return to avoid the infinite loop of a template rendering itself.
32
ob_start();
33
?>
34
35
+ <div class="post-content<?php echo esc_attr( $align ); ?>">
36
+ <?php
37
+ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
38
+ echo apply_filters( 'the_content', get_the_content() );
39
+ ?>
40
</div><!-- .post-content -->
41
42
<?php
full-site-editing/blocks/site-description/edit.js ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import apiFetch from '@wordpress/api-fetch';
5
+ import { PlainText } from '@wordpress/block-editor';
6
+ import { withNotices } from '@wordpress/components';
7
+ import { compose } from '@wordpress/compose';
8
+ import { withSelect } from '@wordpress/data';
9
+ import { Component, Fragment } from '@wordpress/element';
10
+ import { __ } from '@wordpress/i18n';
11
+
12
+ class SiteDescriptionEdit extends Component {
13
+ state = {
14
+ description: __( 'Site description loading…' ),
15
+ initialDescription: '',
16
+ };
17
+
18
+ componentDidMount() {
19
+ const { noticeOperations } = this.props;
20
+
21
+ return apiFetch( { path: '/wp/v2/settings' } )
22
+ .then( ( { description } ) =>
23
+ this.setState( { initialDescription: description, description } )
24
+ )
25
+ .catch( ( { message } ) => {
26
+ noticeOperations.createErrorNotice( message );
27
+ } );
28
+ }
29
+
30
+ componentDidUpdate( prevProps ) {
31
+ const { description, initialDescription } = this.state;
32
+ const { shouldUpdateSiteOption, noticeOperations, isSelected } = this.props;
33
+
34
+ const descriptionUnchanged = description && description.trim() === initialDescription.trim();
35
+ const descriptionIsEmpty = ! description || description.trim().length === 0;
36
+
37
+ // Reset to initial value if user de-selects the block with an empty value.
38
+ if ( ! isSelected && prevProps.isSelected && descriptionIsEmpty ) {
39
+ this.revertDescription();
40
+ }
41
+
42
+ // Don't do anything further if we shouldn't update the site option or the value is unchanged.
43
+ if ( ! shouldUpdateSiteOption || descriptionUnchanged ) {
44
+ return;
45
+ }
46
+
47
+ if ( ! prevProps.shouldUpdateSiteOption && shouldUpdateSiteOption ) {
48
+ apiFetch( { path: '/wp/v2/settings', method: 'POST', data: { description } } )
49
+ .then( () => this.updateInitialDescription() )
50
+ .catch( ( { message } ) => {
51
+ noticeOperations.createErrorNotice( message );
52
+ this.revertDescription();
53
+ } );
54
+ }
55
+ }
56
+
57
+ revertDescription = () => this.setState( { description: this.state.initialDescription } );
58
+
59
+ updateInitialDescription = () => this.setState( { initialDescription: this.state.description } );
60
+
61
+ render() {
62
+ const { className, noticeUI } = this.props;
63
+ const { description } = this.state;
64
+
65
+ return (
66
+ <Fragment>
67
+ { noticeUI }
68
+ <PlainText
69
+ className={ className }
70
+ value={ description }
71
+ onChange={ value => this.setState( { description: value } ) }
72
+ placeholder={ __( 'Site Description' ) }
73
+ aria-label={ __( 'Site Description' ) }
74
+ />
75
+ </Fragment>
76
+ );
77
+ }
78
+ }
79
+
80
+ export default compose( [
81
+ withSelect( select => {
82
+ const { isSavingPost, isPublishingPost, isAutosavingPost, isCurrentPostPublished } = select(
83
+ 'core/editor'
84
+ );
85
+ return {
86
+ shouldUpdateSiteOption:
87
+ ( ( isSavingPost() && isCurrentPostPublished() ) || isPublishingPost() ) &&
88
+ ! isAutosavingPost(),
89
+ };
90
+ } ),
91
+ withNotices,
92
+ ] )( SiteDescriptionEdit );
full-site-editing/blocks/site-description/index.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { registerBlockType } from '@wordpress/blocks';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import edit from './edit';
11
+ import './style.scss';
12
+
13
+ registerBlockType( 'a8c/site-description', {
14
+ title: __( 'Site Description2' ),
15
+ description: __( 'Site description, also known as the tagline.' ),
16
+ icon: 'layout',
17
+ category: 'layout',
18
+ supports: {
19
+ html: false,
20
+ multiple: false,
21
+ reusable: false,
22
+ },
23
+ edit,
24
+ save: () => null,
25
+ } );
full-site-editing/blocks/site-description/index.php ADDED
@@ -0,0 +1,27 @@
1
+ <?php
2
+ /**
3
+ * Render site description file.
4
+ *
5
+ * @package full-site-editing
6
+ */
7
+
8
+ /**
9
+ * Renders the site description (tagline) block.
10
+ *
11
+ * @return string
12
+ */
13
+ function render_site_description_block( $attributes ) {
14
+ ob_start();
15
+
16
+ $class = 'site-description wp-block-a8c-site-description';
17
+ if ( isset( $attributes['className'] ) ) {
18
+ $class .= ' ' . $attributes['className'];
19
+ }
20
+
21
+ ?>
22
+ <p class="<?php echo esc_attr( $class ); ?>">
23
+ <?php bloginfo( 'description' ); ?>
24
+ </p>
25
+ <?php
26
+ return ob_get_clean();
27
+ }
full-site-editing/blocks/site-description/style.scss ADDED
@@ -0,0 +1,10 @@
1
+ .block-editor .wp-block-a8c-site-description {
2
+ &, &:focus {
3
+ display: inline;
4
+ color: #767676;
5
+ font-size: 1.125em;
6
+ font-weight: normal;
7
+ letter-spacing: -0.01em;
8
+ margin: 0;
9
+ }
10
+ }
full-site-editing/blocks/site-logo/edit.js ADDED
@@ -0,0 +1,41 @@
1
+ /* eslint-disable wpcalypso/jsx-classname-namespace */
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { IconButton, ServerSideRender, Toolbar } from '@wordpress/components';
6
+ import { Fragment } from '@wordpress/element';
7
+ import { BlockControls } from '@wordpress/editor';
8
+ import { __ } from '@wordpress/i18n';
9
+ import { addQueryArgs } from '@wordpress/url';
10
+
11
+ function SiteLogoEdit( { className } ) {
12
+ const navigateToCustomerSiteIdentity = () => {
13
+ const siteIdentityLink = addQueryArgs( 'customize.php', {
14
+ 'autofocus[section]': 'title_tagline',
15
+ return: window.location.href,
16
+ } );
17
+ window.location.href = siteIdentityLink;
18
+ };
19
+
20
+ return (
21
+ <Fragment>
22
+ <BlockControls>
23
+ <Toolbar>
24
+ <IconButton
25
+ className={ 'components-toolbar__control' }
26
+ icon="edit"
27
+ label={ __( 'Edit Site Logo' ) }
28
+ onClick={ navigateToCustomerSiteIdentity }
29
+ />
30
+ </Toolbar>
31
+ </BlockControls>
32
+ <ServerSideRender
33
+ className={ className }
34
+ block="a8c/site-logo"
35
+ attributes={ { editorPreview: true } }
36
+ />
37
+ </Fragment>
38
+ );
39
+ }
40
+
41
+ export default SiteLogoEdit;
full-site-editing/blocks/site-logo/index.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { registerBlockType } from '@wordpress/blocks';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import edit from './edit';
11
+ import './style.scss';
12
+
13
+ registerBlockType( 'a8c/site-logo', {
14
+ title: __( 'Site Logo' ),
15
+ description: __( 'Site Logo' ),
16
+ icon: 'format-image',
17
+ category: 'layout',
18
+ keywords: [ __( 'logo' ), __( 'icon' ), __( 'site' ) ],
19
+ edit,
20
+ save: () => null,
21
+ } );
full-site-editing/blocks/site-logo/index.php ADDED
@@ -0,0 +1,44 @@
1
+ <?php
2
+ /**
3
+ * Render site-logo block file.
4
+ *
5
+ * @package full-site-editing
6
+ */
7
+
8
+ /**
9
+ * Renders a site-logo.
10
+ *
11
+ * @param array $attributes Block attributes.
12
+ * @param string $content Block content.
13
+ * @return string
14
+ */
15
+ function render_site_logo( $attributes, $content ) {
16
+ if ( $attributes[ 'editorPreview' ] === true ) {
17
+ return render_site_logo_editor_preview( $attributes, $content );
18
+ }
19
+ return render_site_logo_publish( $attributes, $content );
20
+ }
21
+
22
+ function render_site_logo_publish( $attributes, $content ) {
23
+ if ( ! function_exists( 'get_custom_logo' ) || ! function_exists( 'has_custom_logo' ) ) {
24
+ return '';
25
+ }
26
+
27
+ if ( ! has_custom_logo() ) {
28
+ return '';
29
+ }
30
+
31
+ return get_custom_logo();
32
+ }
33
+
34
+ function render_site_logo_editor_preview( $attributes, $content ) {
35
+ if ( ! function_exists( 'get_custom_logo' ) || ! function_exists( 'has_custom_logo' ) ) {
36
+ return sprintf( '<div class="components-placeholder"><div class="components-placeholder__label">%1$s</div></components-placeholder__label><div class="components-placeholder__instructions">%2$s</div></div>', __( 'Site Logo', 'full-site-editing' ), __( 'No Logo Support!', 'full-site-editing' ) );
37
+ }
38
+
39
+ if ( ! has_custom_logo() ) {
40
+ return sprintf( '<div class="components-placeholder has-no-logo"><div class="components-placeholder__label">%1$s</div></components-placeholder__label><div class="components-placeholder__instructions">%2$s</div></div>', __( 'Site Logo', 'full-site-editing' ), __( 'Click on the Edit button to select a Site Logo.', 'full-site-editing' ) );
41
+ }
42
+
43
+ return get_custom_logo();
44
+ }
full-site-editing/blocks/site-logo/style.scss ADDED
@@ -0,0 +1,3 @@
1
+ .wp-block-a8c-site-logo {
2
+ pointer-events: none;
3
+ }
full-site-editing/blocks/template/edit.js CHANGED
@@ -1,4 +1,5 @@
1
/* eslint-disable wpcalypso/jsx-classname-namespace */
2
/**
3
* External dependencies
4
*/
@@ -8,7 +9,7 @@ import { get } from 'lodash';
8
/**
9
* WordPress dependencies
10
*/
11
- import { IconButton, Placeholder, Toolbar } from '@wordpress/components';
12
import { compose, withState } from '@wordpress/compose';
13
import { withSelect } from '@wordpress/data';
14
import { BlockControls } from '@wordpress/editor';
@@ -24,13 +25,16 @@ import './style.scss';
24
const TemplateEdit = compose(
25
withSelect( ( select, { attributes } ) => {
26
const { getEntityRecord } = select( 'core' );
27
const { templateId } = attributes;
28
return {
29
template: templateId && getEntityRecord( 'postType', 'wp_template_part', templateId ),
30
};
31
} ),
32
withState( { isEditing: false } )
33
- )( ( { attributes, isEditing, template, setAttributes, setState } ) => {
34
const { align, templateId } = attributes;
35
36
const toggleEditing = () => setState( { isEditing: ! isEditing } );
@@ -43,10 +47,11 @@ const TemplateEdit = compose(
43
const showToggleButton = ! isEditing || !! templateId;
44
const showPlaceholder = isEditing || ! templateId;
45
const showContent = ! isEditing && !! templateId;
46
47
return (
48
<Fragment>
49
- { showToggleButton && (
50
<BlockControls>
51
<Toolbar>
52
<IconButton
@@ -78,7 +83,7 @@ const TemplateEdit = compose(
78
postType="wp_template_part"
79
/>
80
{ !! template && (
81
- <a href={ `?post=${ templateId }&action=edit` }>
82
{ sprintf( __( 'Edit "%s"' ), get( template, [ 'title', 'rendered' ], '' ) ) }
83
</a>
84
) }
@@ -86,9 +91,26 @@ const TemplateEdit = compose(
86
</Placeholder>
87
) }
88
{ showContent && (
89
- <RawHTML className="template-block__content">
90
- { get( template, [ 'content', 'rendered' ] ) }
91
- </RawHTML>
92
) }
93
</div>
94
</Fragment>
1
/* eslint-disable wpcalypso/jsx-classname-namespace */
2
+ /* global fullSiteEditing */
3
/**
4
* External dependencies
5
*/
9
/**
10
* WordPress dependencies
11
*/
12
+ import { Button, IconButton, Placeholder, Toolbar } from '@wordpress/components';
13
import { compose, withState } from '@wordpress/compose';
14
import { withSelect } from '@wordpress/data';
15
import { BlockControls } from '@wordpress/editor';
25
const TemplateEdit = compose(
26
withSelect( ( select, { attributes } ) => {
27
const { getEntityRecord } = select( 'core' );
28
+ const { getCurrentPostId } = select( 'core/editor' );
29
+
30
const { templateId } = attributes;
31
return {
32
+ currentPostId: getCurrentPostId(),
33
template: templateId && getEntityRecord( 'postType', 'wp_template_part', templateId ),
34
};
35
} ),
36
withState( { isEditing: false } )
37
+ )( ( { attributes, currentPostId, isEditing, template, setAttributes, setState } ) => {
38
const { align, templateId } = attributes;
39
40
const toggleEditing = () => setState( { isEditing: ! isEditing } );
47
const showToggleButton = ! isEditing || !! templateId;
48
const showPlaceholder = isEditing || ! templateId;
49
const showContent = ! isEditing && !! templateId;
50
+ const isTemplate = 'wp_template' === fullSiteEditing.editorPostType;
51
52
return (
53
<Fragment>
54
+ { showToggleButton && isTemplate && (
55
<BlockControls>
56
<Toolbar>
57
<IconButton
83
postType="wp_template_part"
84
/>
85
{ !! template && (
86
+ <a href={ `?post=${ templateId }&action=edit&fse_parent_post=${ currentPostId }` }>
87
{ sprintf( __( 'Edit "%s"' ), get( template, [ 'title', 'rendered' ], '' ) ) }
88
</a>
89
) }
91
</Placeholder>
92
) }
93
{ showContent && (
94
+ <Fragment>
95
+ <RawHTML className="template-block__content">
96
+ { get( template, [ 'content', 'rendered' ] ) }
97
+ </RawHTML>
98
+ { ! isTemplate && (
99
+ <Placeholder
100
+ className="template-block__overlay"
101
+ instructions={ __(
102
+ 'This block is part of your site template and may appear on multiple pages.'
103
+ ) }
104
+ >
105
+ <Button
106
+ href={ `?post=${ templateId }&action=edit&fse_parent_post=${ currentPostId }` }
107
+ isDefault
108
+ >
109
+ { sprintf( __( 'Edit %s' ), get( template, [ 'title', 'rendered' ], '' ) ) }
110
+ </Button>
111
+ </Placeholder>
112
+ ) }
113
+ </Fragment>
114
) }
115
</div>
116
</Fragment>
full-site-editing/blocks/template/index.js CHANGED
@@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n';
11
import edit from './edit';
12
import './style.scss';
13
14
- if ( 'wp_template' === fullSiteEditing.editorPostType ) {
15
registerBlockType( 'a8c/template', {
16
title: __( 'Template Part' ),
17
description: __( 'Display a template part.' ),
11
import edit from './edit';
12
import './style.scss';
13
14
+ if ( 'wp_template_part' !== fullSiteEditing.editorPostType ) {
15
registerBlockType( 'a8c/template', {
16
title: __( 'Template Part' ),
17
description: __( 'Display a template part.' ),
full-site-editing/blocks/template/index.php CHANGED
@@ -16,7 +16,6 @@ function render_template_block( $attributes ) {
16
return;
17
}
18
19
- $parent_post_id = get_the_ID();
20
$template = get_post( $attributes['templateId'] );
21
22
$align = isset( $attributes['align'] ) ? ' align' . $attributes['align'] : '';
@@ -25,8 +24,11 @@ function render_template_block( $attributes ) {
25
ob_start();
26
?>
27
28
- <div class="template-part<?php echo $align; ?>">
29
- <?php echo apply_filters( 'the_content', get_the_content() ); ?>
30
</div><!-- .template-part -->
31
32
<?php
16
return;
17
}
18
19
$template = get_post( $attributes['templateId'] );
20
21
$align = isset( $attributes['align'] ) ? ' align' . $attributes['align'] : '';
24
ob_start();
25
?>
26
27
+ <div class="template-part<?php echo esc_attr( $align ); ?>">
28
+ <?php
29
+ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
30
+ echo apply_filters( 'the_content', get_the_content() );
31
+ ?>
32
</div><!-- .template-part -->
33
34
<?php
full-site-editing/blocks/template/style.scss CHANGED
@@ -1,3 +1,11 @@
1
.template-block.alignfull {
2
padding: 0 12px;
3
}
@@ -19,3 +27,12 @@
19
display: table;
20
}
21
}
1
+ .template-block {
2
+ min-height: 200px;
3
+
4
+ &:hover .template-block__overlay {
5
+ display: flex;
6
+ }
7
+ }
8
+
9
.template-block.alignfull {
10
padding: 0 12px;
11
}
27
display: table;
28
}
29
}
30
+
31
+ .template-block__overlay {
32
+ display: none;
33
+ position: absolute;
34
+ top: 0;
35
+ left: 0;
36
+ width: 100%;
37
+ height: 100%;
38
+ }
full-site-editing/class-full-site-editing.php CHANGED
@@ -16,6 +16,8 @@ class Full_Site_Editing {
16
*/
17
private static $instance = null;
18
19
/**
20
* Full_Site_Editing constructor.
21
*/
@@ -25,6 +27,23 @@ class Full_Site_Editing {
25
add_action( 'init', array( $this, 'register_meta_template_id' ) );
26
add_action( 'rest_api_init', array( $this, 'allow_searching_for_templates' ) );
27
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_script_and_style' ), 100 );
28
}
29
30
/**
@@ -156,6 +175,46 @@ class Full_Site_Editing {
156
)
157
);
158
159
register_taxonomy(
160
'wp_template_part_type',
161
'wp_template_part',
@@ -247,7 +306,8 @@ class Full_Site_Editing {
247
'fullSiteEditing',
248
array(
249
'editorPostType' => get_current_screen()->post_type,
250
- 'featureFlags' => $feature_flags->get_flags(),
251
)
252
);
253
@@ -257,7 +317,7 @@ class Full_Site_Editing {
257
wp_enqueue_style(
258
'a8c-full-site-editing-style',
259
plugins_url( 'dist/' . $style_file, __FILE__ ),
260
- array(),
261
filemtime( plugin_dir_path( __FILE__ ) . 'dist/' . $style_file )
262
);
263
}
@@ -266,6 +326,19 @@ class Full_Site_Editing {
266
* Register blocks.
267
*/
268
public function register_blocks() {
269
register_block_type(
270
'a8c/post-content',
271
array(
@@ -273,12 +346,32 @@ class Full_Site_Editing {
273
)
274
);
275
276
register_block_type(
277
'a8c/template',
278
array(
279
'render_callback' => 'render_template_block',
280
)
281
);
282
}
283
284
/**
@@ -302,4 +395,163 @@ class Full_Site_Editing {
302
// Setting this to `public` will allow it to be found in the search endpoint.
303
$post_type->public = true;
304
}
305
}
16
*/
17
private static $instance = null;
18
19
+ private $template_post_types = array( 'wp_template', 'wp_template_part' );
20
+
21
/**
22
* Full_Site_Editing constructor.
23
*/
27
add_action( 'init', array( $this, 'register_meta_template_id' ) );
28
add_action( 'rest_api_init', array( $this, 'allow_searching_for_templates' ) );
29
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_script_and_style' ), 100 );
30
+
31
+ add_action(
32
+ 'wp_head',
33
+ function() {
34
+ ob_start( 'a8c_fse_replace_template_parts' );
35
+ }
36
+ );
37
+
38
+ add_action(
39
+ 'wp_footer',
40
+ function() {
41
+ ob_end_flush();
42
+ }
43
+ );
44
+
45
+ add_action( 'the_post', array( $this, 'merge_template_and_post' ) );
46
+ add_filter( 'wp_insert_post_data', array( $this, 'remove_template_components' ), 10, 2 );
47
}
48
49
/**
175
)
176
);
177
178
+ register_taxonomy(
179
+ 'wp_template_type',
180
+ 'wp_template',
181
+ array(
182
+ 'labels' => array(
183
+ 'name' => _x( 'Template Types', 'taxonomy general name', 'full-site-editing' ),
184
+ 'singular_name' => _x( 'Template Type', 'taxonomy singular name', 'full-site-editing' ),
185
+ 'menu_name' => _x( 'Template Types', 'admin menu', 'full-site-editing' ),
186
+ 'all_items' => __( 'All Template Types', 'full-site-editing' ),
187
+ 'edit_item' => __( 'Edit Template Type', 'full-site-editing' ),
188
+ 'view_item' => __( 'View Template Type', 'full-site-editing' ),
189
+ 'update_item' => __( 'Update Template Type', 'full-site-editing' ),
190
+ 'add_new_item' => __( 'Add New Template Type', 'full-site-editing' ),
191
+ 'new_item_name' => __( 'New Template Type', 'full-site-editing' ),
192
+ 'parent_item' => __( 'Parent Template Type', 'full-site-editing' ),
193
+ 'parent_item_colon' => __( 'Parent Template Type:', 'full-site-editing' ),
194
+ 'search_items' => __( 'Search Template Types', 'full-site-editing' ),
195
+ 'not_found' => __( 'No template types found.', 'full-site-editing' ),
196
+ 'back_to_items' => __( 'Back to template types', 'full-site-editing' ),
197
+ ),
198
+ 'public' => false,
199
+ 'publicly_queryable' => true,
200
+ 'show_ui' => true,
201
+ 'show_in_menu' => false,
202
+ 'show_in_nav_menu' => false,
203
+ 'show_in_rest' => true,
204
+ 'rest_base' => 'template_types',
205
+ 'show_tagcloud' => false,
206
+ 'show_admin_column' => true,
207
+ 'hierarchical' => true,
208
+ 'rewrite' => false,
209
+ 'capabilities' => array(
210
+ 'manage_terms' => 'edit_theme_options',
211
+ 'edit_terms' => 'edit_theme_options',
212
+ 'delete_terms' => 'edit_theme_options',
213
+ 'assign_terms' => 'edit_theme_options',
214
+ ),
215
+ )
216
+ );
217
+
218
register_taxonomy(
219
'wp_template_part_type',
220
'wp_template_part',
306
'fullSiteEditing',
307
array(
308
'editorPostType' => get_current_screen()->post_type,
309
+ 'featureFlags' => $feature_flags->get_flags(),
310
+ 'closeButtonUrl' => $this->get_close_button_url(),
311
)
312
);
313
317
wp_enqueue_style(
318
'a8c-full-site-editing-style',
319
plugins_url( 'dist/' . $style_file, __FILE__ ),
320
+ 'wp-edit-post',
321
filemtime( plugin_dir_path( __FILE__ ) . 'dist/' . $style_file )
322
);
323
}
326
* Register blocks.
327
*/
328
public function register_blocks() {
329
+ register_block_type(
330
+ 'a8c/navigation-menu',
331
+ array(
332
+ 'attributes' => [
333
+ 'themeLocation' => [
334
+ 'default' => 'main-1',
335
+ 'type' => 'string',
336
+ ],
337
+ ],
338
+ 'render_callback' => 'render_navigation_menu_block',
339
+ )
340
+ );
341
+
342
register_block_type(
343
'a8c/post-content',
344
array(
346
)
347
);
348
349
+ register_block_type(
350
+ 'a8c/site-description',
351
+ array(
352
+ 'render_callback' => 'render_site_description_block',
353
+ )
354
+ );
355
+
356
register_block_type(
357
'a8c/template',
358
array(
359
'render_callback' => 'render_template_block',
360
)
361
);
362
+
363
+ register_block_type(
364
+ 'a8c/site-logo',
365
+ array(
366
+ 'attributes' => array(
367
+ 'editorPreview' => array(
368
+ 'type' => 'boolean',
369
+ 'default' => false,
370
+ ),
371
+ ),
372
+ 'render_callback' => 'render_site_logo',
373
+ )
374
+ );
375
}
376
377
/**
395
// Setting this to `public` will allow it to be found in the search endpoint.
396
$post_type->public = true;
397
}
398
+
399
+ /**
400
+ * Returns the URL for the Gutenberg close button.
401
+ *
402
+ * In some cases we want to override the default value which would take us to post listing
403
+ * for a given post type. For example, when navigating back from Header, we want to show the
404
+ * parent page editing view, and not the Template Part CPT list.
405
+ *
406
+ * @return null|string Override URL string if it should be inserted, or null otherwise.
407
+ */
408
+ public function get_close_button_url() {
409
+ // phpcs:disable WordPress.Security.NonceVerification.Recommended
410
+ if ( ! isset( $_GET['fse_parent_post'] ) ) {
411
+ return null;
412
+ }
413
+
414
+ $parent_post_id = absint( $_GET['fse_parent_post'] );
415
+ // phpcs:enable WordPress.Security.NonceVerification.Recommended
416
+
417
+ if ( empty( $parent_post_id ) ) {
418
+ return null;
419
+ }
420
+
421
+ $close_button_url = get_edit_post_link( $parent_post_id );
422
+
423
+ /**
424
+ * Filter the Gutenberg's close button URL when editing Template Part CPTs.
425
+ *
426
+ * @since 0.1
427
+ *
428
+ * @param string Current close button URL.
429
+ */
430
+ $close_button_url = apply_filters( 'a8c_fse_close_button_link', $close_button_url );
431
+
432
+ return $close_button_url;
433
+ }
434
+
435
+ /** This will merge the post content with the post template, modifiying the
436
+ * $post parameter.
437
+ *
438
+ * @param WP_Post $post
439
+ */
440
+ public function merge_template_and_post( $post ) {
441
+ //bail if not a REST API Request
442
+ if ( defined( 'REST_REQUEST' ) && ! REST_REQUEST ) {
443
+ return;
444
+ }
445
+
446
+ // bail if the post type is one of the template post types
447
+ if ( in_array( get_post_type( $post->ID ), $this->template_post_types ) ) {
448
+ return;
449
+ }
450
+
451
+ $template_id = get_post_meta( $post->ID, '_wp_template_id', true );
452
+ //bail if the post has no tempalte id assigned
453
+ if ( ! $template_id ) {
454
+ return;
455
+ }
456
+
457
+ $template = get_post( $template_id );
458
+ $wrapped_post_content = sprintf( '<!-- wp:a8c/post-content -->%s<!-- /wp:a8c/post-content -->', $post->post_content );
459
+ $post->post_content = str_replace( '<!-- wp:a8c/post-content /-->', $wrapped_post_content, $template->post_content );
460
+ }
461
+
462
+ /**
463
+ * This will extract the inner blocks of the post content and
464
+ * serialize them back to HTML for saving.
465
+ *
466
+ * @param array $data An array of slashed post data.
467
+ * @param array $postarr An array of sanitized, but otherwise unmodified post data.
468
+ */
469
+ public function remove_template_components( $data, $postarr ) {
470
+ // bail if the post type is one of the template post types
471
+ if ( in_array( $postarr['post_type'], $this->template_post_types ) ) {
472
+ return $data;
473
+ }
474
+
475
+ $post_content = wp_unslash( $data['post_content'] );
476
+
477
+ //bail if post content has no blocks
478
+ if( ! has_blocks( $post_content ) ) {
479
+ return $data;
480
+ }
481
+
482
+ $post_content_blocks = parse_blocks( $post_content );
483
+ $post_content_key = array_search( 'a8c/post-content', array_column( $post_content_blocks, 'blockName' ) );
484
+
485
+ // bail if no post content block found
486
+ if( ! $post_content_key ) {
487
+ return $data;
488
+ }
489
+
490
+ $data['post_content'] = wp_slash( serialize_blocks( $post_content_blocks[ $post_content_key ]['innerBlocks'] ) );
491
+ return $data;
492
+ }
493
+ }
494
+
495
+ if ( ! function_exists( 'serialize_block' ) ) {
496
+ /**
497
+ * Renders an HTML-serialized form of a block object
498
+ * from https://core.trac.wordpress.org/ticket/47375
499
+ *
500
+ * should be available since WordPress 5.3.0
501
+ *
502
+ * @param array $block The block being rendered.
503
+ * @return string The HTML-serialized form of the block
504
+ */
505
+ function serialize_block( $block ) {
506
+ // Non-block content has no block name.
507
+ if ( null === $block['blockName'] ) {
508
+ return $block['innerHTML'];
509
+ }
510
+
511
+ $unwanted = array( '--', '<', '>', '&', '\"' );
512
+ $wanted = array( '\u002d\u002d', '\u003c', '\u003e', '\u0026', '\u0022' );
513
+
514
+ $name = 0 === strpos( $block['blockName'], 'core/' ) ? substr( $block['blockName'], 5 ) : $block['blockName'];
515
+ $has_attrs = ! empty( $block['attrs'] );
516
+ $attrs = $has_attrs ? str_replace( $unwanted, $wanted, wp_json_encode( $block['attrs'] ) ) : '';
517
+
518
+ // Early abort for void blocks holding no content.
519
+ if ( empty( $block['innerContent'] ) ) {
520
+ return $has_attrs
521
+ ? "<!-- wp:{$name} {$attrs} /-->"
522
+ : "<!-- wp:{$name} /-->";
523
+ }
524
+
525
+ $output = $has_attrs
526
+ ? "<!-- wp:{$name} {$attrs} -->\n"
527
+ : "<!-- wp:{$name} -->\n";
528
+
529
+ $inner_block_index = 0;
530
+ foreach ( $block['innerContent'] as $chunk ) {
531
+ $output .= null === $chunk
532
+ ? serialize_block( $block['innerBlocks'][ $inner_block_index++ ] )
533
+ : $chunk;
534
+
535
+ $output .= "\n";
536
+ }
537
+
538
+ $output .= "<!-- /wp:{$name} -->";
539
+
540
+ return $output;
541
+ }
542
+ }
543
+
544
+ if ( ! function_exists( 'serialize_blocks' ) ) {
545
+ /**
546
+ * Renders an HTML-serialized form of a list of block objects
547
+ * from https://core.trac.wordpress.org/ticket/47375
548
+ *
549
+ * should be available since WordPress 5.3.0
550
+ *
551
+ * @param array $blocks The list of parsed block objects
552
+ * @return string The HTML-serialized form of the list of blocks
553
+ */
554
+ function serialize_blocks( $blocks ) {
555
+ return implode( "\n\n", array_map( 'serialize_block', $blocks ) );
556
+ }
557
}
full-site-editing/dist/full-site-editing.css CHANGED
@@ -1 +1 @@
1
- .a8c-post-autocomplete{position:relative}.a8c-post-autocomplete .components-spinner{bottom:7px;position:absolute;right:-5px}.a8c-post-autocomplete__suggestions{max-height:200px;overflow-y:auto;width:302px}.a8c-post-autocomplete__suggestions .components-button{display:block;height:auto;min-height:30px;white-space:normal;width:100%;word-wrap:break-word}.post-content-block.alignfull{padding:0 12px}.post-content-block__selector{width:300px}.post-content-block__selector a{font-family:sans-serif;font-size:13px;padding-left:8px}.post-content-block__preview{pointer-events:none}.post-content-block__preview:after{content:"";clear:both;display:table}.template-block.alignfull{padding:0 12px}.template-block__selector{width:300px}.template-block__selector a{font-family:sans-serif;font-size:13px;padding-left:8px}.template-block__content{pointer-events:none}.template-block__content:after{content:"";clear:both;display:table}
1
+ .wp-block-a8c-navigation-menu .main-navigation{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:1.125em;font-weight:700;letter-spacing:-.02em;line-height:1.2;pointer-events:none;-webkit-font-smoothing:antialiased}.wp-block-a8c-navigation-menu .main-navigation .main-menu{display:inline-block;margin:0;padding:0}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li{color:#0073aa;display:inline;position:relative}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li>a{font-weight:700;color:#0073aa;margin-right:.5rem}.main-navigation .main-menu>li:last-child.menu-item-has-children .submenu-expand,.wp-block-a8c-navigation-menu .main-navigation .main-menu>li:last-child>a{margin-right:0}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children>a{margin-right:.125rem}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children{display:inline-block;position:inherit}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children .submenu-expand{display:inline-block;margin-right:.25rem}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children .submenu-expand svg{position:relative;top:.3rem}.main-navigation .main-menu>li>a:hover+svg,.wp-block-a8c-navigation-menu .main-navigation .main-menu>li>a:hover{color:#005177}.wp-block-a8c-navigation-menu .main-navigation svg{transition:fill .12s ease-in-out;fill:currentColor}.wp-block-a8c-navigation-menu .main-navigation a{text-decoration:none}.wp-block-a8c-navigation-menu .main-navigation button{display:inline-block;border:none;padding:0;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:.88889em;font-weight:700;line-height:1.2;text-decoration:none;vertical-align:bottom;background:transparent;color:inherit;cursor:pointer;transition:background .25s ease-in-out,transform .15s ease;-webkit-appearance:none;-moz-appearance:none}.wp-block-a8c-navigation-menu .main-menu-more{display:none}.wp-block-a8c-navigation-menu .social-navigation{line-height:1.25;margin-top:.5rem;text-align:left}.wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu{content:"";display:inline-block;margin:0;padding:0}.wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu li{display:inline-block;vertical-align:bottom;vertical-align:-webkit-baseline-middle;list-style:none}.wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu li a svg{display:block;width:32px;height:32px;transform:translateZ(0)}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu{display:inline;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:.71111em;padding-left:0}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu li{display:inline;margin-right:1rem}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu a{text-decoration:none;color:#767676}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu a:hover{text-decoration:none;color:#0073aa}.editor-styles-wrapper .wp-block-a8c-navigation-menu-toolbar a,.editor-styles-wrapper .wp-block-a8c-navigation-menu-toolbar a:hover{color:#555d66}.a8c-post-autocomplete{position:relative}.a8c-post-autocomplete .components-spinner{bottom:7px;position:absolute;right:-5px}.a8c-post-autocomplete__suggestions{max-height:200px;overflow-y:auto;width:302px}.a8c-post-autocomplete__suggestions .components-button{display:block;height:auto;min-height:30px;white-space:normal;width:100%;word-wrap:break-word}.post-content-block.alignfull{padding:0 12px}.post-content-block__selector{width:300px}.post-content-block__selector a{font-family:sans-serif;font-size:13px;padding-left:8px}.post-content-block__preview{pointer-events:none}.post-content-block__preview:after{content:"";clear:both;display:table}.block-editor .wp-block-a8c-site-description,.block-editor .wp-block-a8c-site-description:focus{display:inline;color:#767676;font-size:1.125em;font-weight:400;letter-spacing:-.01em;margin:0}.template-block{min-height:200px}.template-block:hover .template-block__overlay{display:flex}.template-block.alignfull{padding:0 12px}.template-block__selector{width:300px}.template-block__selector a{font-family:sans-serif;font-size:13px;padding-left:8px}.template-block__content{pointer-events:none}.template-block__content:after{content:"";clear:both;display:table}.template-block__overlay{display:none;position:absolute;top:0;left:0;width:100%;height:100%}.wp-block-a8c-site-logo{pointer-events:none}
full-site-editing/dist/full-site-editing.deps.json CHANGED
@@ -1 +1 @@
1
- ["lodash","wp-api-fetch","wp-blocks","wp-components","wp-compose","wp-data","wp-edit-post","wp-editor","wp-element","wp-i18n","wp-plugins","wp-url"]
1
+ ["lodash","wp-api-fetch","wp-block-editor","wp-blocks","wp-components","wp-compose","wp-data","wp-dom-ready","wp-edit-post","wp-editor","wp-element","wp-i18n","wp-plugins","wp-url"]
full-site-editing/dist/full-site-editing.js CHANGED
@@ -1,4 +1,4 @@
1
- !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=26)}([function(e,t){e.exports=wp.element},function(e,t){e.exports=wp.i18n},function(e,t){e.exports=wp.components},function(e,t){e.exports=lodash},function(e,t){e.exports=wp.compose},function(e,t){e.exports=wp.data},function(e,t,n){var o;
2
/*!
3
Copyright (c) 2017 Jed Watson.
4
Licensed under the MIT License (MIT), see
@@ -9,4 +9,4 @@
9
Licensed under the MIT License (MIT), see
10
http://jedwatson.github.io/classnames
11
*/
12
- !function(){"use strict";var n={}.hasOwnProperty;function r(){for(var e=[],t=0;t<arguments.length;t++){var o=arguments[t];if(o){var c=typeof o;if("string"===c||"number"===c)e.push(o);else if(Array.isArray(o)&&o.length){var i=r.apply(null,o);i&&e.push(i)}else if("object"===c)for(var a in o)n.call(o,a)&&o[a]&&e.push(a)}}return e.join(" ")}e.exports?(r.default=r,e.exports=r):void 0===(o=function(){return r}.apply(t,[]))||(e.exports=o)}()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){e.exports=wp.blocks},function(e,t){e.exports=wp.editor},function(e,t){e.exports=wp.editPost},function(e,t,n){},function(e,t,n){var o=n(18),r=n(19),c=n(20);e.exports=function(e,t){return o(e)||r(e,t)||c()}},function(e,t,n){var o=n(7);e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){o(e,t,n[t])})}return e}},function(e,t){function n(e,t,n,o,r,c,i){try{var a=e[c](i),l=a.value}catch(s){return void n(s)}a.done?t(l):Promise.resolve(l).then(o,r)}e.exports=function(e){return function(){var t=this,o=arguments;return new Promise(function(r,c){var i=e.apply(t,o);function a(e){n(i,r,c,a,l,"next",e)}function l(e){n(i,r,c,a,l,"throw",e)}a(void 0)})}}},function(e,t){e.exports=wp.apiFetch},function(e,t){e.exports=wp.url},function(e,t){e.exports=wp.plugins},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){var n=[],o=!0,r=!1,c=void 0;try{for(var i,a=e[Symbol.iterator]();!(o=(i=a.next()).done)&&(n.push(i.value),!t||n.length!==t);o=!0);}catch(l){r=!0,c=l}finally{try{o||null==a.return||a.return()}finally{if(r)throw c}}return n}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t,n){},,function(e,t,n){},,,function(e,t,n){"use strict";n.r(t);var o=n(8),r=n(1),c=n(7),i=n.n(c),a=n(0),l=n(6),s=n.n(l),u=n(3),p=n(2),d=n(4),b=n(5),f=n(9),m=n(12),g=n.n(m),O=n(13),j=n.n(O),y=n(14),v=n.n(y),_=n(15),h=n.n(_),w=n(16),E=(n(21),Object(u.debounce)(function(){var e=v()(regeneratorRuntime.mark(function e(t,n,o){var r;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return o({loading:!0,showSuggestions:!0,suggestions:[]}),e.next=3,h()({path:Object(w.addQueryArgs)("/wp/v2/search",j()({context:"embed",per_page:20,search:t},!!n&&{subtype:n}))});case 3:r=e.sent,o({loading:!1,showSuggestions:!0,suggestions:r});case 5:case"end":return e.stop()}},e)}));return function(t,n,o){return e.apply(this,arguments)}}(),200)),P=Object(d.withState)({loading:!1,showSuggestions:!1,suggestions:[]})(function(e){var t=e.initialValue,n=e.loading,o=e.onSelectPost,c=e.postType,i=e.setState,l=e.showSuggestions,s=e.suggestions,d=Object(a.useState)(t),b=g()(d,2),f=b[0],m=b[1],O=function(e){return function(){var t=function(e,t,n){var o=e.id,r=e.title,c=e.subtype;return t({loading:!1,showSuggestions:!1,suggestions:[]}),n(r),{id:o,type:c}}(e,i,m);o(t)}};return Object(a.createElement)("div",{className:"a8c-post-autocomplete"},Object(a.createElement)(p.TextControl,{autoComplete:"off",onChange:function(e){m(e),e.length<2?i({loading:!1,showSuggestions:!1}):E(e,c,i)},placeholder:Object(r.__)("Type to search"),type:"search",value:f}),n&&Object(a.createElement)(p.Spinner,null),l&&!!s.length&&Object(a.createElement)(p.Popover,{focusOnMount:!1,noArrow:!0,position:"bottom"},Object(a.createElement)("div",{className:"a8c-post-autocomplete__suggestions"},Object(u.map)(s,function(e){return Object(a.createElement)(p.Button,{isLarge:!0,isLink:!0,key:e.id,onClick:O(e)},e.title)}))))}),S=Object(d.compose)(Object(d.withState)({isEditing:!1,selectedPostId:void 0,selectedPostType:void 0}),Object(b.withSelect)(function(e,t){var n=t.selectedPostId,o=t.selectedPostType;return{selectedPost:(0,e("core").getEntityRecord)("postType",o,n)}}))(function(e){var t=e.attributes,n=e.isEditing,o=e.selectedPost,c=e.setState,l=t.align,d=!n||!!o,b=n||!o,m=!n&&!!o;return Object(a.createElement)(a.Fragment,null,d&&Object(a.createElement)(f.BlockControls,null,Object(a.createElement)(p.Toolbar,null,Object(a.createElement)(p.IconButton,{className:s()("components-icon-button components-toolbar__control",{"is-active":n}),label:Object(r.__)("Change Preview"),onClick:function(){return c({isEditing:!n})},icon:"edit"}))),Object(a.createElement)("div",{className:s()("post-content-block",i()({},"align".concat(l),l))},b&&Object(a.createElement)(p.Placeholder,{icon:"layout",label:Object(r.__)("Content Slot"),instructions:Object(r.__)("Placeholder for a post or a page.")},Object(a.createElement)("div",{className:"post-content-block__selector"},Object(a.createElement)("div",null,Object(r.__)("Select something to preview:")),Object(a.createElement)(P,{initialValue:Object(u.get)(o,["title","rendered"]),onSelectPost:function(e){var t=e.id,n=e.type;c({isEditing:!1,selectedPostId:t,selectedPostType:n})},postType:["page","post"]}),!!o&&Object(a.createElement)("a",{href:"?post=".concat(o.id,"&action=edit")},Object(r.sprintf)(Object(r.__)('Edit "%s"'),Object(u.get)(o,["title","rendered"],""))))),m&&Object(a.createElement)(a.RawHTML,{className:"post-content-block__preview"},Object(u.get)(o,["content","rendered"]))))});n(23);"wp_template"===fullSiteEditing.editorPostType&&Object(o.registerBlockType)("a8c/post-content",{title:Object(r.__)("Content Slot"),description:Object(r.__)("Placeholder for a post or a page."),icon:"layout",category:"layout",supports:{align:["wide","full"],anchor:!0,html:!1,multiple:!1,reusable:!1},edit:S,save:function(){return null}});n(11);var x=Object(d.compose)(Object(b.withSelect)(function(e,t){var n=t.attributes,o=e("core").getEntityRecord,r=n.templateId;return{template:r&&o("postType","wp_template_part",r)}}),Object(d.withState)({isEditing:!1}))(function(e){var t=e.attributes,n=e.isEditing,o=e.template,c=e.setAttributes,l=e.setState,d=t.align,b=t.templateId,m=!n||!!b,g=n||!b,O=!n&&!!b;return Object(a.createElement)(a.Fragment,null,m&&Object(a.createElement)(f.BlockControls,null,Object(a.createElement)(p.Toolbar,null,Object(a.createElement)(p.IconButton,{className:s()("components-icon-button components-toolbar__control",{"is-active":n}),label:Object(r.__)("Change Template Part"),onClick:function(){return l({isEditing:!n})},icon:"edit"}))),Object(a.createElement)("div",{className:s()("template-block",i()({},"align".concat(d),d))},g&&Object(a.createElement)(p.Placeholder,{icon:"layout",label:Object(r.__)("Template Part"),instructions:Object(r.__)("Select a template part to display")},Object(a.createElement)("div",{className:"template-block__selector"},Object(a.createElement)(P,{initialValue:Object(u.get)(o,["title","rendered"]),onSelectPost:function(e){var t=e.id;l({isEditing:!1}),c({templateId:t})},postType:"wp_template_part"}),!!o&&Object(a.createElement)("a",{href:"?post=".concat(b,"&action=edit")},Object(r.sprintf)(Object(r.__)('Edit "%s"'),Object(u.get)(o,["title","rendered"],""))))),O&&Object(a.createElement)(a.RawHTML,{className:"template-block__content"},Object(u.get)(o,["content","rendered"]))))});"wp_template"===fullSiteEditing.editorPostType&&Object(o.registerBlockType)("a8c/template",{title:Object(r.__)("Template Part"),description:Object(r.__)("Display a template part."),icon:"layout",category:"layout",attributes:{templateId:{type:"number"}},supports:{align:["wide","full"],anchor:!0,html:!1,reusable:!1},edit:x,save:function(){return null}});var T=n(10),k=n(17),I=Object(d.compose)(Object(b.withDispatch)(function(e){return{setTemplateId:function(t){return e("core/editor").editPost({meta:{_wp_template_id:t}})}}}),Object(b.withSelect)(function(e){var t=e("core"),n=t.canUser,o=t.getEntityRecord,r=Object(u.get)(e("core/editor").getEditedPostAttribute("meta"),"_wp_template_id");return{canUserUpdateSettings:n("update","settings"),selectedTemplate:r&&o("postType","wp_template",r)}}))(function(e){var t=e.canUserUpdateSettings,n=e.setTemplateId,o=e.selectedTemplate;if(!t)return null;return Object(a.createElement)(a.Fragment,null,Object(a.createElement)(T.PluginSidebarMoreMenuItem,{target:"fse-template-sidebar",icon:"layout"},Object(r.__)("Template")),Object(a.createElement)(T.PluginSidebar,{icon:"layout",name:"fse-template-sidebar",title:Object(r.__)("Template")},Object(a.createElement)(p.PanelBody,null,Object(r.__)("Select a template"),Object(a.createElement)(P,{initialValue:Object(u.get)(o,["title","rendered"]),onSelectPost:function(e){var t=e.id;n(parseInt(t,10))},postType:"wp_template"}))))});"page"===fullSiteEditing.editorPostType&&Object(k.registerPlugin)("fse-template-selector-sidebar",{render:I})}]));
1
+ !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(o){if(t[o])return t[o].exports;var i=t[o]={i:o,l:!1,exports:{}};return e[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(o,i,function(t){return e[t]}.bind(null,i));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=42)}([function(e,t){e.exports=wp.element},function(e,t){e.exports=wp.i18n},function(e,t){e.exports=wp.components},function(e,t){e.exports=lodash},function(e,t){e.exports=wp.compose},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){e.exports=wp.data},function(e,t){e.exports=wp.blocks},function(e,t){e.exports=wp.editor},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t){e.exports=wp.url},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}e.exports=function(e,t,o){return t&&n(e.prototype,t),o&&n(e,o),e}},function(e,t,n){var o=n(35),i=n(9);e.exports=function(e,t){return!t||"object"!==o(t)&&"function"!=typeof t?i(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var o=n(36);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&o(e,t)}},function(e,t,n){var o;
2
/*!
3
Copyright (c) 2017 Jed Watson.
4
Licensed under the MIT License (MIT), see
9
Licensed under the MIT License (MIT), see
10
http://jedwatson.github.io/classnames
11
*/
12
+ !function(){"use strict";var n={}.hasOwnProperty;function i(){for(var e=[],t=0;t<arguments.length;t++){var o=arguments[t];if(o){var r=typeof o;if("string"===r||"number"===r)e.push(o);else if(Array.isArray(o)&&o.length){var c=i.apply(null,o);c&&e.push(c)}else if("object"===r)for(var a in o)n.call(o,a)&&o[a]&&e.push(a)}}return e.join(" ")}e.exports?(i.default=i,e.exports=i):void 0===(o=function(){return i}.apply(t,[]))||(e.exports=o)}()},function(e,t){e.exports=wp.blockEditor},function(e,t){e.exports=wp.apiFetch},function(e,t){e.exports=wp.domReady},function(e,t){e.exports=wp.editPost},function(e,t,n){},function(e,t,n){var o=n(28),i=n(29),r=n(30);e.exports=function(e,t){return o(e)||i(e,t)||r()}},function(e,t,n){var o=n(5);e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),i.forEach(function(t){o(e,t,n[t])})}return e}},function(e,t){function n(e,t,n,o,i,r,c){try{var a=e[r](c),l=a.value}catch(s){return void n(s)}a.done?t(l):Promise.resolve(l).then(o,i)}e.exports=function(e){return function(){var t=this,o=arguments;return new Promise(function(i,r){var c=e.apply(t,o);function a(e){n(c,i,r,a,l,"next",e)}function l(e){n(c,i,r,a,l,"throw",e)}a(void 0)})}}},function(e,t){e.exports=wp.plugins},function(e,t,n){},,function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){var n=[],o=!0,i=!1,r=void 0;try{for(var c,a=e[Symbol.iterator]();!(o=(c=a.next()).done)&&(n.push(c.value),!t||n.length!==t);o=!0);}catch(l){i=!0,r=l}finally{try{o||null==a.return||a.return()}finally{if(i)throw r}}return n}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t,n){},,function(e,t,n){},,function(e,t){function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(t){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?e.exports=o=function(e){return n(e)}:e.exports=o=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":n(e)},o(t)}e.exports=o},function(e,t){function n(t,o){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,o)}e.exports=n},function(e,t,n){},,,function(e,t,n){},,function(e,t,n){"use strict";n.r(t);var o=n(0),i=n(7),r=n(1),c=n(2),a=n(8),l=n(10),s=function(e){var t=e.attributes,n=Object(l.addQueryArgs)("customize.php",{"autofocus[panel]":"nav_menus",return:window.location.href});return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(a.BlockControls,null,Object(o.createElement)(c.Toolbar,{className:"wp-block-a8c-navigation-menu-toolbar"},Object(o.createElement)(c.IconButton,{icon:"edit",label:Object(r.__)("Edit Menu"),href:n,className:"components-toolbar__control"}))),Object(o.createElement)(c.ServerSideRender,{attributes:t,block:"a8c/navigation-menu",className:"wp-block-a8c-navigation-menu"}))},u=(n(26),Object(o.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(o.createElement)("path",{fill:"none",d:"M0 0h24v24H0V0z"}),Object(o.createElement)("path",{d:"M12 7.27l4.28 10.43-3.47-1.53-.81-.36-.81.36-3.47 1.53L12 7.27M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z"})));Object(i.registerBlockType)("a8c/navigation-menu",{title:Object(r.__)("Navigation Menu"),description:Object(r.__)("Visual placeholder for site-wide navigation and menus."),icon:u,category:"layout",supports:{html:!1,multiple:!1,reusable:!1},attributes:{themeLocation:{type:"string",default:"main-1"}},edit:s,save:function(){return null}});var p=n(17),b=n(5),d=n.n(b),f=n(16),m=n.n(f),g=n(3),O=n(4),h=n(6),j=n(22),y=n.n(j),v=n(23),_=n.n(v),S=n(24),E=n.n(S),w=n(18),P=n.n(w),x=(n(31),Object(g.debounce)(function(){var e=E()(regeneratorRuntime.mark(function e(t,n,o){var i;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return o({loading:!0,showSuggestions:!0,suggestions:[]}),e.next=3,P()({path:Object(l.addQueryArgs)("/wp/v2/search",_()({context:"embed",per_page:20,search:t},!!n&&{subtype:n}))});case 3:i=e.sent,o({loading:!1,showSuggestions:!0,suggestions:i});case 5:case"end":return e.stop()}},e)}));return function(t,n,o){return e.apply(this,arguments)}}(),200)),k=Object(O.withState)({loading:!1,showSuggestions:!1,suggestions:[]})(function(e){var t=e.initialValue,n=e.loading,i=e.onSelectPost,a=e.postType,l=e.setState,s=e.showSuggestions,u=e.suggestions,p=Object(o.useState)(t),b=y()(p,2),d=b[0],f=b[1],m=function(e){return function(){var t=function(e,t,n){var o=e.id,i=e.title,r=e.subtype;return t({loading:!1,showSuggestions:!1,suggestions:[]}),n(i),{id:o,type:r}}(e,l,f);i(t)}};return Object(o.createElement)("div",{className:"a8c-post-autocomplete"},Object(o.createElement)(c.TextControl,{autoComplete:"off",onChange:function(e){f(e),e.length<2?l({loading:!1,showSuggestions:!1}):x(e,a,l)},placeholder:Object(r.__)("Type to search"),type:"search",value:d}),n&&Object(o.createElement)(c.Spinner,null),s&&!!u.length&&Object(o.createElement)(c.Popover,{focusOnMount:!1,noArrow:!0,position:"bottom"},Object(o.createElement)("div",{className:"a8c-post-autocomplete__suggestions"},Object(g.map)(u,function(e){return Object(o.createElement)(c.Button,{isLarge:!0,isLink:!0,key:e.id,onClick:m(e)},e.title)}))))}),T=Object(O.compose)(Object(O.withState)({isEditing:!1,selectedPostId:void 0,selectedPostType:void 0}),Object(h.withSelect)(function(e,t){var n=t.selectedPostId,o=t.selectedPostType;return{selectedPost:(0,e("core").getEntityRecord)("postType",o,n)}}))(function(e){var t=e.attributes,n=e.isEditing,i=e.selectedPost,l=e.setState,s=t.align,u=!n||!!i,p=n||!i,b=!n&&!!i;return Object(o.createElement)(o.Fragment,null,u&&Object(o.createElement)(a.BlockControls,null,Object(o.createElement)(c.Toolbar,null,Object(o.createElement)(c.IconButton,{className:m()("components-icon-button components-toolbar__control",{"is-active":n}),label:Object(r.__)("Change Preview"),onClick:function(){return l({isEditing:!n})},icon:"edit"}))),Object(o.createElement)("div",{className:m()("post-content-block",d()({},"align".concat(s),s))},p&&Object(o.createElement)(c.Placeholder,{icon:"layout",label:Object(r.__)("Content Slot"),instructions:Object(r.__)("Placeholder for a post or a page.")},Object(o.createElement)("div",{className:"post-content-block__selector"},Object(o.createElement)("div",null,Object(r.__)("Select something to preview:")),Object(o.createElement)(k,{initialValue:Object(g.get)(i,["title","rendered"]),onSelectPost:function(e){var t=e.id,n=e.type;l({isEditing:!1,selectedPostId:t,selectedPostType:n})},postType:["page","post"]}),!!i&&Object(o.createElement)("a",{href:"?post=".concat(i.id,"&action=edit")},Object(r.sprintf)(Object(r.__)('Edit "%s"'),Object(g.get)(i,["title","rendered"],""))))),b&&Object(o.createElement)(o.RawHTML,{className:"post-content-block__preview"},Object(g.get)(i,["content","rendered"]))))}),C=(n(33),"wp_template"===fullSiteEditing.editorPostType);Object(i.registerBlockType)("a8c/post-content",{title:Object(r.__)("Content Slot"),description:Object(r.__)("Placeholder for a post or a page."),icon:"layout",category:"layout",supports:{align:["wide","full"],anchor:!0,html:!1,multiple:!1,reusable:!1},edit:C?T:function(){return Object(o.createElement)(p.InnerBlocks,null)},save:C?function(){return null}:function(){return Object(o.createElement)(p.InnerBlocks.Content,null)}});var B=n(11),N=n.n(B),I=n(12),R=n.n(I),D=n(13),L=n.n(D),M=n(14),A=n.n(M),U=n(9),F=n.n(U),z=n(15),V=n.n(z),H=function(e){function t(){var e,n;N()(this,t);for(var o=arguments.length,i=new Array(o),c=0;c<o;c++)i[c]=arguments[c];return n=L()(this,(e=A()(t)).call.apply(e,[this].concat(i))),d()(F()(n),"state",{description:Object(r.__)("Site description loading…"),initialDescription:""}),d()(F()(n),"revertDescription",function(){return n.setState({description:n.state.initialDescription})}),d()(F()(n),"updateInitialDescription",function(){return n.setState({initialDescription:n.state.description})}),n}return V()(t,e),R()(t,[{key:"componentDidMount",value:function(){var e=this,t=this.props.noticeOperations;return P()({path:"/wp/v2/settings"}).then(function(t){var n=t.description;return e.setState({initialDescription:n,description:n})}).catch(function(e){var n=e.message;t.createErrorNotice(n)})}},{key:"componentDidUpdate",value:function(e){var t=this,n=this.state,o=n.description,i=n.initialDescription,r=this.props,c=r.shouldUpdateSiteOption,a=r.noticeOperations,l=r.isSelected,s=o&&o.trim()===i.trim(),u=!o||0===o.trim().length;!l&&e.isSelected&&u&&this.revertDescription(),c&&!s&&!e.shouldUpdateSiteOption&&c&&P()({path:"/wp/v2/settings",method:"POST",data:{description:o}}).then(function(){return t.updateInitialDescription()}).catch(function(e){var n=e.message;a.createErrorNotice(n),t.revertDescription()})}},{key:"render",value:function(){var e=this,t=this.props,n=t.className,i=t.noticeUI,c=this.state.description;return Object(o.createElement)(o.Fragment,null,i,Object(o.createElement)(p.PlainText,{className:n,value:c,onChange:function(t){return e.setState({description:t})},placeholder:Object(r.__)("Site Description"),"aria-label":Object(r.__)("Site Description")}))}}]),t}(o.Component),Q=Object(O.compose)([Object(h.withSelect)(function(e){var t=e("core/editor"),n=t.isSavingPost,o=t.isPublishingPost,i=t.isAutosavingPost,r=t.isCurrentPostPublished;return{shouldUpdateSiteOption:(n()&&r()||o())&&!i()}}),c.withNotices])(H);n(37);Object(i.registerBlockType)("a8c/site-description",{title:Object(r.__)("Site Description2"),description:Object(r.__)("Site description, also known as the tagline."),icon:"layout",category:"layout",supports:{html:!1,multiple:!1,reusable:!1},edit:Q,save:function(){return null}});n(21);var q=Object(O.compose)(Object(h.withSelect)(function(e,t){var n=t.attributes,o=e("core").getEntityRecord,i=e("core/editor").getCurrentPostId,r=n.templateId;return{currentPostId:i(),template:r&&o("postType","wp_template_part",r)}}),Object(O.withState)({isEditing:!1}))(function(e){var t=e.attributes,n=e.currentPostId,i=e.isEditing,l=e.template,s=e.setAttributes,u=e.setState,p=t.align,b=t.templateId,f=!i||!!b,O=i||!b,h=!i&&!!b,j="wp_template"===fullSiteEditing.editorPostType;return Object(o.createElement)(o.Fragment,null,f&&j&&Object(o.createElement)(a.BlockControls,null,Object(o.createElement)(c.Toolbar,null,Object(o.createElement)(c.IconButton,{className:m()("components-icon-button components-toolbar__control",{"is-active":i}),label:Object(r.__)("Change Template Part"),onClick:function(){return u({isEditing:!i})},icon:"edit"}))),Object(o.createElement)("div",{className:m()("template-block",d()({},"align".concat(p),p))},O&&Object(o.createElement)(c.Placeholder,{icon:"layout",label:Object(r.__)("Template Part"),instructions:Object(r.__)("Select a template part to display")},Object(o.createElement)("div",{className:"template-block__selector"},Object(o.createElement)(k,{initialValue:Object(g.get)(l,["title","rendered"]),onSelectPost:function(e){var t=e.id;u({isEditing:!1}),s({templateId:t})},postType:"wp_template_part"}),!!l&&Object(o.createElement)("a",{href:"?post=".concat(b,"&action=edit&fse_parent_post=").concat(n)},Object(r.sprintf)(Object(r.__)('Edit "%s"'),Object(g.get)(l,["title","rendered"],""))))),h&&Object(o.createElement)(o.Fragment,null,Object(o.createElement)(o.RawHTML,{className:"template-block__content"},Object(g.get)(l,["content","rendered"])),!j&&Object(o.createElement)(c.Placeholder,{className:"template-block__overlay",instructions:Object(r.__)("This block is part of your site template and may appear on multiple pages.")},Object(o.createElement)(c.Button,{href:"?post=".concat(b,"&action=edit&fse_parent_post=").concat(n),isDefault:!0},Object(r.sprintf)(Object(r.__)("Edit %s"),Object(g.get)(l,["title","rendered"],"")))))))});"wp_template_part"!==fullSiteEditing.editorPostType&&Object(i.registerBlockType)("a8c/template",{title:Object(r.__)("Template Part"),description:Object(r.__)("Display a template part."),icon:"layout",category:"layout",attributes:{templateId:{type:"number"}},supports:{align:["wide","full"],anchor:!0,html:!1,reusable:!1},edit:q,save:function(){return null}});var G=function(e){var t=e.className;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(a.BlockControls,null,Object(o.createElement)(c.Toolbar,null,Object(o.createElement)(c.IconButton,{className:"components-toolbar__control",icon:"edit",label:Object(r.__)("Edit Site Logo"),onClick:function(){var e=Object(l.addQueryArgs)("customize.php",{"autofocus[section]":"title_tagline",return:window.location.href});window.location.href=e}}))),Object(o.createElement)(c.ServerSideRender,{className:t,block:"a8c/site-logo",attributes:{editorPreview:!0}}))};n(40);Object(i.registerBlockType)("a8c/site-logo",{title:Object(r.__)("Site Logo"),description:Object(r.__)("Site Logo"),icon:"format-image",category:"layout",keywords:[Object(r.__)("logo"),Object(r.__)("icon"),Object(r.__)("site")],edit:G,save:function(){return null}});var J=n(20),K=n(25),W=Object(O.compose)(Object(h.withDispatch)(function(e){return{setTemplateId:function(t){return e("core/editor").editPost({meta:{_wp_template_id:t}})}}}),Object(h.withSelect)(function(e){var t=e("core"),n=t.canUser,o=t.getEntityRecord,i=Object(g.get)(e("core/editor").getEditedPostAttribute("meta"),"_wp_template_id");return{canUserUpdateSettings:n("update","settings"),selectedTemplate:i&&o("postType","wp_template",i)}}))(function(e){var t=e.canUserUpdateSettings,n=e.setTemplateId,i=e.selectedTemplate;if(!t)return null;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(J.PluginSidebarMoreMenuItem,{target:"fse-template-sidebar",icon:"layout"},Object(r.__)("Template")),Object(o.createElement)(J.PluginSidebar,{icon:"layout",name:"fse-template-sidebar",title:Object(r.__)("Template")},Object(o.createElement)(c.PanelBody,null,Object(r.__)("Select a template"),Object(o.createElement)(k,{initialValue:Object(g.get)(i,["title","rendered"]),onSelectPost:function(e){var t=e.id;n(parseInt(t,10))},postType:"wp_template"}))))});"page"===fullSiteEditing.editorPostType&&Object(K.registerPlugin)("fse-template-selector-sidebar",{render:W});var X=n(19),Y=n.n(X);Y()(function(){if("wp_template_part"===fullSiteEditing.editorPostType&&fullSiteEditing.closeButtonUrl){var e=document.querySelector(".edit-post-fullscreen-mode-close__toolbar a");e&&(e.href=fullSiteEditing.closeButtonUrl)}});var Z=function(e){function t(){return N()(this,t),L()(this,A()(t).apply(this,arguments))}return V()(t,e),R()(t,[{key:"render",value:function(){var e=this.props,t=e.onSave,n=e.onClose,i=e.isBusy,a=e.disabled;return Object(o.createElement)("div",{className:"edit-post-layout"},Object(o.createElement)("div",{className:"editor-post-publish-panel"},Object(o.createElement)("div",{className:"editor-post-publish-panel__header"},Object(o.createElement)("div",{className:"editor-post-publish-panel__header-publish-button"},Object(o.createElement)(c.Button,{isPrimary:!0,isLarge:!0,isBusy:i,onClick:t,disabled:a},Object(r.__)("Publish")),Object(o.createElement)("span",{className:"editor-post-publish-panel__spacer"})),Object(o.createElement)(c.IconButton,{"aria-expanded":!0,onClick:n,icon:"no-alt",label:Object(r.__)("Close panel")})),Object(o.createElement)("div",{className:"editor-post-publish-panel__prepublish"},Object(o.createElement)("p",null,Object(o.createElement)("strong",null,Object(r.__)("Are you ready to publish?"))),Object(o.createElement)("p",null,Object(r.__)("Changes you publish will update all pages with this template part.")))))}}]),t}(o.Component),$={buttonStyle:{visibility:"hidden"},isPanelOpen:!1},ee=function(e){function t(e){var n;return N()(this,t),n=L()(this,A()(t).call(this,e)),d()(F()(n),"onPublish",function(){n.togglePanel(),n.getOriginalButton().click()}),d()(F()(n),"togglePanel",function(){n.setState({isPanelOpen:!n.state.isPanelOpen})}),n.onResize=Object(g.debounce)(n.onResize,100),n.state=$,n.onResize(),n}return V()(t,e),R()(t,[{key:"componentDidUpdate",value:function(e,t){var n=this;e.isFullScreen!==t.isFullScreen&&setTimeout(function(){return n.onResize()},1)}},{key:"getOriginalButton",value:function(){return document.querySelector(".edit-post-header .editor-post-publish-button")}},{key:"onResize",value:function(){var e=this.getOriginalButton(),t=$.buttonStyle;if(Object(g.isNil)(e)||!("getBoundingClientRect"in e))return this.setState({buttonStyle:t});var n=e.getBoundingClientRect();t={height:"33px",position:"fixed",zIndex:"10001",top:n.top,left:n.x},window.matchMedia("(min-width: 600px)").matches||(t.paddingLeft="5px",t.paddingRight="5px"),this.setState({buttonStyle:t})}},{key:"getHidingCss",value:function(){return".edit-post-header .editor-post-publish-button {\n\t\t\tvisibility: hidden !important;\n\t\t}"}},{key:"render",value:function(){if(!this.shouldRender())return null;var e=this.props,t=e.isSaving,n=e.isSaveable,i=e.isPostSavingLocked,a=e.isPublishable,l=t||!n||i||!a;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(c.Button,{onClick:this.togglePanel,isPrimary:!0,isLarge:!0,style:this.state.buttonStyle,disabled:l,isBusy:this.isSaving},Object(r.__)("Update")),this.state.isPanelOpen&&Object(o.createElement)(Z,{isBusy:this.isSaving,onClose:this.togglePanel,onSave:this.onPublish,disabled:l}),Object(o.createElement)("style",null,this.getHidingCss()))}},{key:"shouldRender",value:function(){var e=this.props,t=e.isPublished,n=e.isPublishable,o=e.isSaveable;return!!(t&&n&&o)}}]),t}(o.Component),te=Object(O.compose)([Object(h.withSelect)(function(e){var t=e("core/editor"),n=t.isSavingPost,o=t.isCurrentPostPublished,i=t.isEditedPostSaveable,r=t.isEditedPostPublishable,c=t.isPostSavingLocked,a=t.getCurrentPost;return{isSaving:n(),isSaveable:i(),isPostSavingLocked:c(),isPublishable:r(),isPublished:o(),hasPublishAction:Object(g.get)(a(),["_links","wp:action-publish"],!1),isFullScreen:e("core/edit-post").isFeatureActive("fullscreenMode")}}),Object(O.withGlobalEvents)({resize:"onResize"})])(ee);Y()(function(){if("wp_template_part"===fullSiteEditing.editorPostType){var e=document.createElement("div");e.id="template-update-confirmation",document.getElementById("wpcontent").appendChild(e),Object(o.render)(Object(o.createElement)(te,null),e)}})}]));
full-site-editing/dist/full-site-editing.rtl.css CHANGED
@@ -1 +1 @@
1
- .a8c-post-autocomplete{position:relative}.a8c-post-autocomplete .components-spinner{bottom:7px;position:absolute;left:-5px}.a8c-post-autocomplete__suggestions{max-height:200px;overflow-y:auto;width:302px}.a8c-post-autocomplete__suggestions .components-button{display:block;height:auto;min-height:30px;white-space:normal;width:100%;word-wrap:break-word}.post-content-block.alignfull{padding:0 12px}.post-content-block__selector{width:300px}.post-content-block__selector a{font-family:sans-serif;font-size:13px;padding-right:8px}.post-content-block__preview{pointer-events:none}.post-content-block__preview:after{content:"";clear:both;display:table}.template-block.alignfull{padding:0 12px}.template-block__selector{width:300px}.template-block__selector a{font-family:sans-serif;font-size:13px;padding-right:8px}.template-block__content{pointer-events:none}.template-block__content:after{content:"";clear:both;display:table}
1
+ .wp-block-a8c-navigation-menu .main-navigation{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:1.125em;font-weight:700;letter-spacing:-.02em;line-height:1.2;pointer-events:none;-webkit-font-smoothing:antialiased}.wp-block-a8c-navigation-menu .main-navigation .main-menu{display:inline-block;margin:0;padding:0}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li{color:#0073aa;display:inline;position:relative}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li>a{font-weight:700;color:#0073aa;margin-left:.5rem}.main-navigation .main-menu>li:last-child.menu-item-has-children .submenu-expand,.wp-block-a8c-navigation-menu .main-navigation .main-menu>li:last-child>a{margin-left:0}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children>a{margin-left:.125rem}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children{display:inline-block;position:inherit}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children .submenu-expand{display:inline-block;margin-left:.25rem}.wp-block-a8c-navigation-menu .main-navigation .main-menu>li.menu-item-has-children .submenu-expand svg{position:relative;top:.3rem}.main-navigation .main-menu>li>a:hover+svg,.wp-block-a8c-navigation-menu .main-navigation .main-menu>li>a:hover{color:#005177}.wp-block-a8c-navigation-menu .main-navigation svg{transition:fill .12s ease-in-out;fill:currentColor}.wp-block-a8c-navigation-menu .main-navigation a{text-decoration:none}.wp-block-a8c-navigation-menu .main-navigation button{display:inline-block;border:none;padding:0;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:.88889em;font-weight:700;line-height:1.2;text-decoration:none;vertical-align:bottom;background:transparent;color:inherit;cursor:pointer;transition:background .25s ease-in-out,transform .15s ease;-webkit-appearance:none;-moz-appearance:none}.wp-block-a8c-navigation-menu .main-menu-more{display:none}.wp-block-a8c-navigation-menu .social-navigation{line-height:1.25;margin-top:.5rem;text-align:right}.wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu{content:"";display:inline-block;margin:0;padding:0}.wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu li{display:inline-block;vertical-align:bottom;vertical-align:-webkit-baseline-middle;list-style:none}.wp-block-a8c-navigation-menu .social-navigation ul.social-links-menu li a svg{display:block;width:32px;height:32px;transform:translateZ(0)}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu{display:inline;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:.71111em;padding-right:0}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu li{display:inline;margin-left:1rem}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu a{text-decoration:none;color:#767676}.wp-block-a8c-navigation-menu .footer-navigation .footer-menu a:hover{text-decoration:none;color:#0073aa}.editor-styles-wrapper .wp-block-a8c-navigation-menu-toolbar a,.editor-styles-wrapper .wp-block-a8c-navigation-menu-toolbar a:hover{color:#555d66}.a8c-post-autocomplete{position:relative}.a8c-post-autocomplete .components-spinner{bottom:7px;position:absolute;left:-5px}.a8c-post-autocomplete__suggestions{max-height:200px;overflow-y:auto;width:302px}.a8c-post-autocomplete__suggestions .components-button{display:block;height:auto;min-height:30px;white-space:normal;width:100%;word-wrap:break-word}.post-content-block.alignfull{padding:0 12px}.post-content-block__selector{width:300px}.post-content-block__selector a{font-family:sans-serif;font-size:13px;padding-right:8px}.post-content-block__preview{pointer-events:none}.post-content-block__preview:after{content:"";clear:both;display:table}.block-editor .wp-block-a8c-site-description,.block-editor .wp-block-a8c-site-description:focus{display:inline;color:#767676;font-size:1.125em;font-weight:400;letter-spacing:-.01em;margin:0}.template-block{min-height:200px}.template-block:hover .template-block__overlay{display:flex}.template-block.alignfull{padding:0 12px}.template-block__selector{width:300px}.template-block__selector a{font-family:sans-serif;font-size:13px;padding-right:8px}.template-block__content{pointer-events:none}.template-block__content:after{content:"";clear:both;display:table}.template-block__overlay{display:none;position:absolute;top:0;right:0;width:100%;height:100%}.wp-block-a8c-site-logo{pointer-events:none}
full-site-editing/index.js CHANGED
@@ -1,6 +1,11 @@
1
/**
2
* Internal dependencies
3
*/
4
import './blocks/post-content';
5
import './blocks/template';
6
import './plugins/template-selector-sidebar';
1
/**
2
* Internal dependencies
3
*/
4
+ import './blocks/navigation-menu';
5
import './blocks/post-content';
6
+ import './blocks/site-description';
7
import './blocks/template';
8
+ import './blocks/site-logo';
9
import './plugins/template-selector-sidebar';
10
+ import './plugins/close-button-override';
11
+ import './plugins/template-update-confirmation';
full-site-editing/plugins/close-button-override/index.js ADDED
@@ -0,0 +1,24 @@
1
+ /* global fullSiteEditing */
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import domReady from '@wordpress/dom-ready';
7
+
8
+ domReady( () => {
9
+ // We only want this override when closing Template Part CPT (e.g. header) to navigate back to parent page.
10
+ if ( 'wp_template_part' !== fullSiteEditing.editorPostType ) {
11
+ return;
12
+ }
13
+
14
+ // Keep the default URL if the override hasn't been provided by the plugin.
15
+ if ( ! fullSiteEditing.closeButtonUrl ) {
16
+ return;
17
+ }
18
+
19
+ const closeButton = document.querySelector( '.edit-post-fullscreen-mode-close__toolbar a' );
20
+
21
+ if ( closeButton ) {
22
+ closeButton.href = fullSiteEditing.closeButtonUrl;
23
+ }
24
+ } );
full-site-editing/plugins/template-update-confirmation/button.js ADDED
@@ -0,0 +1,143 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { Button } from '@wordpress/components';
5
+ import { Component, Fragment } from '@wordpress/element';
6
+ import { withGlobalEvents, compose } from '@wordpress/compose';
7
+ import { withSelect } from '@wordpress/data';
8
+ import { debounce, get, isNil } from 'lodash';
9
+ import { __ } from '@wordpress/i18n';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import Panel from './panel';
15
+
16
+ const initialState = {
17
+ buttonStyle: {
18
+ visibility: 'hidden',
19
+ },
20
+ isPanelOpen: false,
21
+ };
22
+
23
+ class TemplateUpdateConfirmationButton extends Component {
24
+ constructor( props ) {
25
+ super( props );
26
+ this.onResize = debounce( this.onResize, 100 );
27
+ this.state = initialState;
28
+ this.onResize();
29
+ }
30
+
31
+ componentDidUpdate( props, prevProps ) {
32
+ if ( props.isFullScreen !== prevProps.isFullScreen ) {
33
+ // this ensures the button is repositioned properly when toggling fullscreen mode
34
+ setTimeout( () => this.onResize(), 1 );
35
+ }
36
+ }
37
+
38
+ getOriginalButton() {
39
+ return document.querySelector( '.edit-post-header .editor-post-publish-button' );
40
+ }
41
+
42
+ onResize() {
43
+ const originalButton = this.getOriginalButton();
44
+ let { buttonStyle } = initialState;
45
+ if ( isNil( originalButton ) || ! ( 'getBoundingClientRect' in originalButton ) ) {
46
+ // if it's not there, might need a timeout to await it?
47
+ return this.setState( { buttonStyle } );
48
+ }
49
+ const rect = originalButton.getBoundingClientRect();
50
+ buttonStyle = {
51
+ // height doesn't line up perfectly with default styles
52
+ height: '33px',
53
+ position: 'fixed',
54
+ zIndex: '10001',
55
+ top: rect.top,
56
+ left: rect.x,
57
+ };
58
+ if ( ! window.matchMedia( '(min-width: 600px)' ).matches ) {
59
+ buttonStyle.paddingLeft = '5px';
60
+ buttonStyle.paddingRight = '5px';
61
+ }
62
+ this.setState( { buttonStyle } );
63
+ }
64
+
65
+ getHidingCss() {
66
+ return `.edit-post-header .editor-post-publish-button {
67
+ visibility: hidden !important;
68
+ }`;
69
+ }
70
+
71
+ render() {
72
+ if ( ! this.shouldRender() ) {
73
+ return null;
74
+ }
75
+ const { isSaving, isSaveable, isPostSavingLocked, isPublishable } = this.props;
76
+ const isButtonDisabled = isSaving || ! isSaveable || isPostSavingLocked || ! isPublishable;
77
+ return (
78
+ <Fragment>
79
+ <Button
80
+ onClick={ this.togglePanel }
81
+ isPrimary
82
+ isLarge
83
+ style={ this.state.buttonStyle }
84
+ disabled={ isButtonDisabled }
85
+ isBusy={ this.isSaving }
86
+ >
87
+ { __( 'Update' ) }
88
+ </Button>
89
+ { this.state.isPanelOpen && (
90
+ <Panel
91
+ isBusy={ this.isSaving }
92
+ onClose={ this.togglePanel }
93
+ onSave={ this.onPublish }
94
+ disabled={ isButtonDisabled }
95
+ />
96
+ ) }
97
+ <style>{ this.getHidingCss() }</style>
98
+ </Fragment>
99
+ );
100
+ }
101
+
102
+ shouldRender() {
103
+ const { isPublished, isPublishable, isSaveable } = this.props;
104
+ if ( ! isPublished || ! isPublishable || ! isSaveable ) {
105
+ return false;
106
+ }
107
+ return true;
108
+ }
109
+
110
+ onPublish = () => {
111
+ this.togglePanel();
112
+ this.getOriginalButton().click();
113
+ };
114
+
115
+ togglePanel = () => {
116
+ this.setState( { isPanelOpen: ! this.state.isPanelOpen } );
117
+ };
118
+ }
119
+
120
+ export default compose( [
121
+ withSelect( select => {
122
+ const {
123
+ isSavingPost,
124
+ isCurrentPostPublished,
125
+ isEditedPostSaveable,
126
+ isEditedPostPublishable,
127
+ isPostSavingLocked,
128
+ getCurrentPost,
129
+ } = select( 'core/editor' );
130
+ return {
131
+ isSaving: isSavingPost(),
132
+ isSaveable: isEditedPostSaveable(),
133
+ isPostSavingLocked: isPostSavingLocked(),
134
+ isPublishable: isEditedPostPublishable(),
135
+ isPublished: isCurrentPostPublished(),
136
+ hasPublishAction: get( getCurrentPost(), [ '_links', 'wp:action-publish' ], false ),
137
+ isFullScreen: select( 'core/edit-post' ).isFeatureActive( 'fullscreenMode' ),
138
+ };
139
+ } ),
140
+ withGlobalEvents( {
141
+ resize: 'onResize',
142
+ } ),
143
+ ] )( TemplateUpdateConfirmationButton );
full-site-editing/plugins/template-update-confirmation/index.js ADDED
@@ -0,0 +1,21 @@
1
+ /* global fullSiteEditing */
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import domReady from '@wordpress/dom-ready';
6
+ import { render } from '@wordpress/element';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import TemplateUpdateConfirmationButton from './button';
12
+
13
+ domReady( () => {
14
+ if ( 'wp_template_part' !== fullSiteEditing.editorPostType ) {
15
+ return;
16
+ }
17
+ const element = document.createElement( 'div' );
18
+ element.id = 'template-update-confirmation';
19
+ document.getElementById( 'wpcontent' ).appendChild( element );
20
+ render( <TemplateUpdateConfirmationButton />, element );
21
+ } );
full-site-editing/plugins/template-update-confirmation/panel.js ADDED
@@ -0,0 +1,40 @@
1
+ /* eslint-disable wpcalypso/jsx-classname-namespace */
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { Component } from '@wordpress/element';
6
+ import { Button, IconButton } from '@wordpress/components';
7
+ import { __ } from '@wordpress/i18n';
8
+
9
+ export default class Panel extends Component {
10
+ render() {
11
+ const { onSave, onClose, isBusy, disabled } = this.props;
12
+ return (
13
+ <div className="edit-post-layout">
14
+ <div className="editor-post-publish-panel">
15
+ <div className="editor-post-publish-panel__header">
16
+ <div className="editor-post-publish-panel__header-publish-button">
17
+ <Button isPrimary isLarge isBusy={ isBusy } onClick={ onSave } disabled={ disabled }>
18
+ { __( 'Publish' ) }
19
+ </Button>
20
+ <span className="editor-post-publish-panel__spacer" />
21
+ </div>
22
+
23
+ <IconButton
24
+ aria-expanded={ true }
25
+ onClick={ onClose }
26
+ icon="no-alt"
27
+ label={ __( 'Close panel' ) }
28
+ />
29
+ </div>
30
+ <div className="editor-post-publish-panel__prepublish">
31
+ <p>
32
+ <strong>{ __( 'Are you ready to publish?' ) }</strong>
33
+ </p>
34
+ <p>{ __( 'Changes you publish will update all pages with this template part.' ) }</p>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ );
39
+ }
40
+ }
full-site-editing/utils/class-a8c-wp-template-data-inserter.php ADDED
@@ -0,0 +1,105 @@
1
+ <?php
2
+ /**
3
+ * Template data inserter file.
4
+ *
5
+ * @package full-site-editing
6
+ */
7
+
8
+ /**
9
+ * Class A8C_WP_Template_Data_Inserter
10
+ */
11
+ class A8C_WP_Template_Data_Inserter {
12
+ /**
13
+ * This function will be called on plugin activation hook.
14
+ */
15
+ public function insert_default_template_data() {
16
+ $header_id = wp_insert_post(
17
+ [
18
+ 'post_title' => 'Header',
19
+ 'post_content' => $this->get_header_content(),
20
+ 'post_status' => 'publish',
21
+ 'post_type' => 'wp_template_part',
22
+ 'comment_status' => 'closed',
23
+ 'ping_status' => 'closed',
24
+ ]
25
+ );
26
+
27
+ if ( ! term_exists( 'header', 'wp_template_part_type' ) ) {
28
+ wp_insert_term( 'header', 'wp_template_part_type' );
29
+ }
30
+
31
+ wp_set_object_terms( $header_id, 'header', 'wp_template_part_type' );
32
+
33
+ $footer_id = wp_insert_post(
34
+ [
35
+ 'post_title' => 'Footer',
36
+ 'post_content' => $this->get_footer_content(),
37
+ 'post_status' => 'publish',
38
+ 'post_type' => 'wp_template_part',
39
+ 'comment_status' => 'closed',
40
+ 'ping_status' => 'closed',
41
+ ]
42
+ );
43
+
44
+ if ( ! term_exists( 'footer', 'wp_template_part_type' ) ) {
45
+ wp_insert_term( 'footer', 'wp_template_part_type' );
46
+ }
47
+
48
+ wp_set_object_terms( $footer_id, 'footer', 'wp_template_part_type' );
49
+
50
+ $page_template_id = wp_insert_post(
51
+ [
52
+ 'post_title' => 'Page Template',
53
+ 'post_content' => $this->get_template_content( $header_id, $footer_id ),
54
+ 'post_status' => 'publish',
55
+ 'post_type' => 'wp_template',
56
+ 'comment_status' => 'closed',
57
+ 'ping_status' => 'closed',
58
+ ]
59
+ );
60
+
61
+ if ( ! term_exists( 'footer', 'wp_template_part_type' ) ) {
62
+ wp_insert_term( 'footer', 'wp_template_part_type' );
63
+ }
64
+
65
+ wp_set_object_terms( $page_template_id, 'page_template', 'wp_template_type' );
66
+ }
67
+
68
+ /**
69
+ * Returns default header template part content.
70
+ *
71
+ * @return string
72
+ */
73
+ public function get_header_content() {
74
+ // TODO: replace with header blocks once they are ready.
75
+ return '<!-- wp:heading -->' .
76
+ '<h2>Test Header Content</h2>' .
77
+ '<!-- /wp:heading -->';
78
+ }
79
+
80
+ /**
81
+ * Returns default footer template part content.
82
+ *
83
+ * @return string
84
+ */
85
+ public function get_footer_content() {
86
+ // TODO: replace with footer blocks once they are ready.
87
+ return '<!-- wp:heading -->' .
88
+ '<h2>Test Footer Content</h2>' .
89
+ '<!-- /wp:heading -->';
90
+ }
91
+
92
+ /**
93
+ * Returns default page template content.
94
+ *
95
+ * @param int $header_id ID of referenced header template part CPT.
96
+ * @param int $footer_id ID of referenced footer template part CPT.
97
+ *
98
+ * @return string
99
+ */
100
+ public function get_template_content( $header_id, $footer_id ) {
101
+ return "<!-- wp:a8c/template {\"templateId\":$header_id,\"align\":\"full\"} /-->" .
102
+ '<!-- wp:a8c/post-content {"align":"full"} /-->' .
103
+ "<!-- wp:a8c/template {\"templateId\":$footer_id,\"align\":\"full\"} /-->";
104
+ }
105
+ }
full-site-editing/utils/class-a8c-wp-template.php ADDED
@@ -0,0 +1,200 @@
1
+ <?php
2
+ /**
3
+ * A8C WP Template file.
4
+ *
5
+ * @package full-site-editing
6
+ */
7
+
8
+ /**
9
+ * Class A8C_WP_Template
10
+ */
11
+ class A8C_WP_Template {
12
+ const TEMPLATE_META_KEY = '_wp_template_id';
13
+
14
+ /**
15
+ * ID of the current post that's being rendered.
16
+ *
17
+ * @var int $current_post_id ID of the current post.
18
+ */
19
+ private $current_post_id;
20
+
21
+ /**
22
+ * ID of the template associated with the current post.
23
+ *
24
+ * @var int $template_id ID of the template associated with the current post.
25
+ */
26
+ private $template_id;
27
+
28
+
29
+ /**
30
+ * A8C_WP_Template constructor.
31
+ *
32
+ * @param int|null $post_id Defaults to current post id if not passed.
33
+ */
34
+ public function __construct( $post_id = null ) {
35
+ if ( null === $post_id ) {
36
+ $post_id = get_post()->ID;
37
+ }
38
+
39
+ $this->current_post_id = $post_id;
40
+ $this->template_id = $this->get_template_id();
41
+ }
42
+
43
+ /**
44
+ * Returns template ID for current page if it exists.
45
+ *
46
+ * If template id is set in current post's meta (_wp_template_id) it will be returned.
47
+ * Otherwise it falls back to global page template that is marked with page_template term
48
+ * in wp_template_type taxonomy. Note that having only one term of this kind is not
49
+ * currently enforced, so we'll just pick the latest page template that was created
50
+ * (based on its post ID).
51
+ *
52
+ * @return null|int template ID for current page, or null if it doesn't exist.
53
+ */
54
+ public function get_template_id() {
55
+ // If the specific template is referenced in post meta, use it.
56
+ $template_id = get_post_meta( $this->current_post_id, self::TEMPLATE_META_KEY, true );
57
+
58
+ if ( ! empty( $template_id ) ) {
59
+ return $template_id;
60
+ }
61
+
62
+ // Otherwise, fall back to latest global page template.
63
+ $term = get_term_by( 'name', 'page_template', 'wp_template_type', ARRAY_A );
64
+
65
+ if ( ! isset( $term['term_id'] ) ) {
66
+ return null;
67
+ }
68
+
69
+ $template_ids = get_objects_in_term( $term['term_id'], $term['taxonomy'], [ 'order' => 'DESC' ] );
70
+
71
+ if ( empty( $template_ids ) ) {
72
+ return null;
73
+ }
74
+
75
+ return $template_ids[0];
76
+ }
77
+
78
+ /**
79
+ * Returns template's post content.
80
+ *
81
+ * @return null|string
82
+ */
83
+ public function get_template_content() {
84
+ if ( empty( $this->template_id ) ) {
85
+ return null;
86
+ }
87
+
88
+ $template_post = get_post( $this->template_id );
89
+
90
+ return null === $template_post ? null : $template_post->post_content;
91
+ }
92
+
93
+ /**
94
+ * Returns array of blocks that represent the template.
95
+ *
96
+ * @return array
97
+ */
98
+ public function get_template_blocks() {
99
+ $template_content = $this->get_template_content();
100
+
101
+ $template_blocks = parse_blocks( $template_content );
102
+
103
+ return is_array( $template_blocks ) ? $template_blocks : [];
104
+ }
105
+
106
+ /**
107
+ * Returns the post ID of the template part CPT that represents the Header in this template.
108
+ *
109
+ * This is simplified for now and we are just assuming that the first template part in every
110
+ * template will represent the Header.
111
+ *
112
+ * @return null|int Header template part ID if it exists or null otherwise.
113
+ */
114
+ public function get_header_id() {
115
+ $template_blocks = $this->get_template_blocks();
116
+
117
+ if ( empty( $template_blocks ) ) {
118
+ return null;
119
+ }
120
+
121
+ // TODO: Incorporate wp_template_part taxonomy checks.
122
+ if ( ! isset( $template_blocks[0]['attrs']['templateId'] ) ) {
123
+ return null;
124
+ }
125
+
126
+ $header_id = $template_blocks[0]['attrs']['templateId'];
127
+
128
+ if ( ! has_term( 'header', 'wp_template_part_type', $header_id ) ) {
129
+ return null;
130
+ }
131
+
132
+ return $header_id;
133
+ }
134
+
135
+ /**
136
+ * Returns the post ID of the template part CPT that represents the Footer in this template.
137
+ *
138
+ * This is simplified for now and we are just assuming that the last template part in every
139
+ * template will represent the Footer.
140
+ *
141
+ * @return null|int Footer template part ID if it exists or null otherwise.
142
+ */
143
+ public function get_footer_id() {
144
+ $template_blocks = $this->get_template_blocks();
145
+
146
+ if ( ! isset( end( $template_blocks )['attrs']['templateId'] ) ) {
147
+ return null;
148
+ }
149
+
150
+ $footer_id = end( $template_blocks )['attrs']['templateId'];
151
+
152
+ if ( ! has_term( 'footer', 'wp_template_part_type', $footer_id ) ) {
153
+ return null;
154
+ }
155
+
156
+ return $footer_id;
157
+ }
158
+
159
+ /**
160
+ * Returns header template part content of current template.
161
+ *
162
+ * @return null|string
163
+ */
164
+ public function get_header_content() {
165
+ $header_id = $this->get_header_id();
166
+
167
+ if ( null === $header_id ) {
168
+ return null;
169
+ }
170
+
171
+ $header = get_post( $header_id );
172
+
173
+ if ( null === $header ) {
174
+ return null;
175
+ }
176
+
177
+ return $header->post_content;
178
+ }
179
+
180
+ /**
181
+ * Returns footer template part content of current template.
182
+ *
183
+ * @return null|string
184
+ */
185
+ public function get_footer_content() {
186
+ $footer_id = $this->get_footer_id();
187
+
188
+ if ( null === $footer_id ) {
189
+ return null;
190
+ }
191
+
192
+ $footer = get_post( $footer_id );
193
+
194
+ if ( null === $footer ) {
195
+ return null;
196
+ }
197
+
198