PluginProbe
Gutenberg / 9.4.0
Gutenberg v9.4.0
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.4.0, at lib/templates-sync.php

175 lines 5.7 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 'title' => $slug,
30 'meta_key' => 'theme',
31 'meta_value' => $theme,
32 'posts_per_page' => 1,
33 'no_found_rows' => true,
34 )
35 );
36 $post = $template_query->have_posts() ? $template_query->next_post() : null;
37 if ( ! $post ) {
38 wp_insert_post(
39 array(
40 'post_content' => $content,
41 'post_title' => $slug,
42 'post_status' => 'auto-draft',
43 'post_type' => $post_type,
44 'post_name' => $slug,
45 )
46 );
47 } elseif ( 'auto-draft' === $post->post_status && $content !== $post->post_content ) {
48 // If the template already exists, but it was never changed by the user
49 // and the template file content changed then update the content of auto-draft.
50 $post->post_content = $content;
51 wp_insert_post( $post );
52 }
53 }
54
55 /**
56 * Finds all nested template part file paths in a theme's directory.
57 *
58 * @access private
59 *
60 * @param string $base_directory The theme's file path.
61 * @return array $path_list A list of paths to all template part files.
62 */
63 function _gutenberg_get_template_paths( $base_directory ) {
64 $path_list = array();
65 if ( file_exists( $base_directory ) ) {
66 $nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_directory ) );
67 $nested_html_files = new RegexIterator( $nested_files, '/^.+\.html$/i', RecursiveRegexIterator::GET_MATCH );
68 foreach ( $nested_html_files as $path => $file ) {
69 $path_list[] = $path;
70 }
71 }
72 return $path_list;
73 }
74
75 /**
76 * Create the template parts auto-drafts for the current theme.
77 *
78 * @access private
79 * @internal
80 *
81 * @param string $template_type The template type (template or template-part).
82 */
83 function _gutenberg_synchronize_theme_templates( $template_type ) {
84 $template_post_types = array(
85 'template' => 'wp_template',
86 'template-part' => 'wp_template_part',
87 );
88 $template_base_paths = array(
89 'template' => 'block-templates',
90 'template-part' => 'block-template-parts',
91 );
92 $themes = array(
93 get_stylesheet() => get_stylesheet_directory(),
94 get_template() => get_template_directory(),
95 );
96
97 // Get file paths for all theme supplied template that changed since last check.
98 $template_files = array();
99 $option_name = 'gutenberg_last_synchronize_theme_' . $template_type . '_checks';
100 $last_checks = get_option( $option_name, array() );
101 $current_time = time();
102 foreach ( $themes as $theme_slug => $theme_dir ) {
103 $last_check = isset( $last_checks[ $theme_slug ] ) ? $last_checks[ $theme_slug ] : 0;
104
105 $theme_template_files = _gutenberg_get_template_paths( $theme_dir . '/' . $template_base_paths[ $template_type ] );
106 foreach ( $theme_template_files as $template_file ) {
107 if ( filemtime( $template_file ) > $last_check ) {
108 $template_files[] = array(
109 'path' => $template_file,
110 'theme' => $theme_slug,
111 );
112 }
113 }
114
115 $last_checks[ $theme_slug ] = $current_time;
116 }
117
118 // Build and save each template part.
119 foreach ( $template_files as $template_file ) {
120 $path = $template_file['path'];
121 $theme = $template_file['theme'];
122 $template_base_path = $template_base_paths[ $template_type ];
123
124 $content = file_get_contents( $path );
125 $slug = substr(
126 $path,
127 // Starting position of slug.
128 strpos( $path, $template_base_path . DIRECTORY_SEPARATOR ) + 1 + strlen( $template_base_path ),
129 // Subtract ending '.html'.
130 -5
131 );
132 _gutenberg_create_auto_draft_for_template( $template_post_types[ $template_type ], $slug, $theme, $content );
133 }
134
135 update_option( $option_name, $last_checks );
136 }
137
138 /**
139 * Synchronize changed template and template part files after WordPress is loaded
140 */
141 function gutenberg_synchronize_theme_templates_on_load() {
142 if ( ! gutenberg_is_fse_theme() ) {
143 return;
144 }
145
146 _gutenberg_synchronize_theme_templates( 'template-part' );
147 _gutenberg_synchronize_theme_templates( 'template' );
148 }
149 add_action( 'wp_loaded', 'gutenberg_synchronize_theme_templates_on_load' );
150
151 /**
152 * Clears synchronization last check timestamps.
153 */
154 function gutenberg_clear_synchronize_last_checks() {
155 update_option( 'gutenberg_last_synchronize_theme_template_checks', array() );
156 update_option( 'gutenberg_last_synchronize_theme_template-part_checks', array() );
157 }
158
159 // Clear synchronization last check timestamps after trashing a template or template part.
160 add_action( 'trash_wp_template', 'gutenberg_clear_synchronize_last_checks' );
161 add_action( 'trash_wp_template_part', 'gutenberg_clear_synchronize_last_checks' );
162
163 /**
164 * Clear synchronization last check timestamps after deleting a template or template part.
165 *
166 * @param int $post_id ID of the deleted post.
167 * @param WP_Post $post WP_Post instance of the deleted post.
168 */
169 function gutenberg_clear_synchronize_last_checks_after_delete( $post_id, $post ) {
170 if ( 'wp_template' === $post->post_type || 'wp_template_part' === $post->post_type ) {
171 gutenberg_clear_synchronize_last_checks();
172 }
173 }
174 add_action( 'after_delete_post', 'gutenberg_clear_synchronize_last_checks_after_delete', 10, 2 );
175