PluginProbe
Gutenberg / 9.6.1
Gutenberg v9.6.1
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / templates-sync.php

templates-sync.php in Gutenberg 9.6.1, at lib/templates-sync.php

189 lines 6.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Block templates and template parts auto-draft synchronization utils.
4 *
5 * @package gutenberg
6 */
7
8 /**
9 * Creates a template (or template part depending on the post type)
10 * auto-draft if it doesn't exist yet.
11 *
12 * @access private
13 * @internal
14 *
15 * @param string $post_type Template post type.
16 * @param string $slug Template slug.
17 * @param string $theme Template theme.
18 * @param string $content Template content.
19 */
20 function _gutenberg_create_auto_draft_for_template( $post_type, $slug, $theme, $content ) {
21 // We check if an auto-draft was already created,
22 // before running the REST API calls
23 // because the site editor needs an existing auto-draft
24 // for each theme template part to work properly.
25 $template_query = new WP_Query(
26 array(
27 'post_type' => $post_type,
28 'post_status' => array( 'publish', 'auto-draft' ),
29 'post_name__in' => array( $slug ),
30 'tax_query' => array(
31 array(
32 'taxonomy' => 'wp_theme',
33 'field' => 'slug',
34 'terms' => $theme,
35 ),
36 ),
37 'posts_per_page' => 1,
38 'no_found_rows' => true,
39 )
40 );
41 $post = $template_query->have_posts() ? $template_query->next_post() : null;
42 if ( ! $post ) {
43 $template_post = array(
44 'post_content' => $content,
45 'post_title' => $slug,
46 'post_status' => 'auto-draft',
47 'post_type' => $post_type,
48 'post_name' => $slug,
49 'tax_input' => array( 'wp_theme' => array( $theme, '_wp_file_based' ) ),
50 );
51
52 if ( 'wp_template' === $post_type ) {
53 $default_template_types = gutenberg_get_default_template_types();
54 if ( isset( $default_template_types[ $slug ] ) ) {
55 $template_post['post_title'] = $default_template_types[ $slug ]['title'];
56 $template_post['post_excerpt'] = $default_template_types[ $slug ]['description'];
57 }
58 }
59
60 wp_insert_post( $template_post );
61 } elseif ( 'auto-draft' === $post->post_status && $content !== $post->post_content ) {
62 // If the template already exists, but it was never changed by the user
63 // and the template file content changed then update the content of auto-draft.
64 $post->post_content = $content;
65 wp_insert_post( $post );
66 }
67 }
68
69 /**
70 * Finds all nested template part file paths in a theme's directory.
71 *
72 * @access private
73 *
74 * @param string $base_directory The theme's file path.
75 * @return array $path_list A list of paths to all template part files.
76 */
77 function _gutenberg_get_template_paths( $base_directory ) {
78 $path_list = array();
79 if ( file_exists( $base_directory ) ) {
80 $nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_directory ) );
81 $nested_html_files = new RegexIterator( $nested_files, '/^.+\.html$/i', RecursiveRegexIterator::GET_MATCH );
82 foreach ( $nested_html_files as $path => $file ) {
83 $path_list[] = $path;
84 }
85 }
86 return $path_list;
87 }
88
89 /**
90 * Create the template parts auto-drafts for the current theme.
91 *
92 * @access private
93 * @internal
94 *
95 * @param string $template_type The template type (template or template-part).
96 */
97 function _gutenberg_synchronize_theme_templates( $template_type ) {
98 $template_post_types = array(
99 'template' => 'wp_template',
100 'template-part' => 'wp_template_part',
101 );
102 $template_base_paths = array(
103 'template' => 'block-templates',
104 'template-part' => 'block-template-parts',
105 );
106 $themes = array(
107 get_stylesheet() => get_stylesheet_directory(),
108 get_template() => get_template_directory(),
109 );
110
111 // Get file paths for all theme supplied template that changed since last check.
112 $template_files = array();
113 $option_name = 'gutenberg_last_synchronize_theme_' . $template_type . '_checks';
114 $last_checks = get_option( $option_name, array() );
115 $current_time = time();
116 foreach ( $themes as $theme_slug => $theme_dir ) {
117 $last_check = isset( $last_checks[ $theme_slug ] ) ? $last_checks[ $theme_slug ] : 0;
118
119 $theme_template_files = _gutenberg_get_template_paths( $theme_dir . '/' . $template_base_paths[ $template_type ] );
120 foreach ( $theme_template_files as $template_file ) {
121 if ( filemtime( $template_file ) > $last_check ) {
122 $template_files[] = array(
123 'path' => $template_file,
124 'theme' => $theme_slug,
125 );
126 }
127 }
128
129 $last_checks[ $theme_slug ] = $current_time;
130 }
131
132 // Build and save each template part.
133 foreach ( $template_files as $template_file ) {
134 $path = $template_file['path'];
135 $theme = $template_file['theme'];
136 $template_base_path = $template_base_paths[ $template_type ];
137
138 $content = file_get_contents( $path );
139 $slug = substr(
140 $path,
141 // Starting position of slug.
142 strpos( $path, $template_base_path . DIRECTORY_SEPARATOR ) + 1 + strlen( $template_base_path ),
143 // Subtract ending '.html'.
144 -5
145 );
146 _gutenberg_create_auto_draft_for_template( $template_post_types[ $template_type ], $slug, $theme, $content );
147 }
148
149 update_option( $option_name, $last_checks );
150 }
151
152 /**
153 * Synchronize changed template and template part files after WordPress is loaded
154 */
155 function gutenberg_synchronize_theme_templates_on_load() {
156 if ( ! gutenberg_is_fse_theme() ) {
157 return;
158 }
159
160 _gutenberg_synchronize_theme_templates( 'template-part' );
161 _gutenberg_synchronize_theme_templates( 'template' );
162 }
163 add_action( 'wp_loaded', 'gutenberg_synchronize_theme_templates_on_load' );
164
165 /**
166 * Clears synchronization last check timestamps.
167 */
168 function gutenberg_clear_synchronize_last_checks() {
169 update_option( 'gutenberg_last_synchronize_theme_template_checks', array() );
170 update_option( 'gutenberg_last_synchronize_theme_template-part_checks', array() );
171 }
172
173 // Clear synchronization last check timestamps after trashing a template or template part.
174 add_action( 'trash_wp_template', 'gutenberg_clear_synchronize_last_checks' );
175 add_action( 'trash_wp_template_part', 'gutenberg_clear_synchronize_last_checks' );
176
177 /**
178 * Clear synchronization last check timestamps after deleting a template or template part.
179 *
180 * @param int $post_id ID of the deleted post.
181 * @param WP_Post $post WP_Post instance of the deleted post.
182 */
183 function gutenberg_clear_synchronize_last_checks_after_delete( $post_id, $post ) {
184 if ( 'wp_template' === $post->post_type || 'wp_template_part' === $post->post_type ) {
185 gutenberg_clear_synchronize_last_checks();
186 }
187 }
188 add_action( 'after_delete_post', 'gutenberg_clear_synchronize_last_checks_after_delete', 10, 2 );
189