267 * |
267 * |
268 * @param WP_REST_Request $request The request instance. |
268 * @param WP_REST_Request $request The request instance. |
269 * @return WP_REST_Response |
269 * @return WP_REST_Response |
270 */ |
270 */ |
271 public function get_items( $request ) { |
271 public function get_items( $request ) { |
|
272 if ( $request->is_method( 'HEAD' ) ) { |
|
273 // Return early as this handler doesn't add any response headers. |
|
274 return new WP_REST_Response( array() ); |
|
275 } |
|
276 |
272 $query = array(); |
277 $query = array(); |
273 if ( isset( $request['wp_id'] ) ) { |
278 if ( isset( $request['wp_id'] ) ) { |
274 $query['wp_id'] = $request['wp_id']; |
279 $query['wp_id'] = $request['wp_id']; |
275 } |
280 } |
276 if ( isset( $request['area'] ) ) { |
281 if ( isset( $request['area'] ) ) { |
324 * |
329 * |
325 * @param WP_REST_Request $request The request instance. |
330 * @param WP_REST_Request $request The request instance. |
326 * @return WP_REST_Response|WP_Error |
331 * @return WP_REST_Response|WP_Error |
327 */ |
332 */ |
328 public function get_item( $request ) { |
333 public function get_item( $request ) { |
329 if ( isset( $request['source'] ) && 'theme' === $request['source'] ) { |
334 if ( isset( $request['source'] ) && ( 'theme' === $request['source'] || 'plugin' === $request['source'] ) ) { |
330 $template = get_block_file_template( $request['id'], $this->post_type ); |
335 $template = get_block_file_template( $request['id'], $this->post_type ); |
331 } else { |
336 } else { |
332 $template = get_block_template( $request['id'], $this->post_type ); |
337 $template = get_block_template( $request['id'], $this->post_type ); |
333 } |
338 } |
334 |
339 |
666 * @param WP_Block_Template $item Template instance. |
671 * @param WP_Block_Template $item Template instance. |
667 * @param WP_REST_Request $request Request object. |
672 * @param WP_REST_Request $request Request object. |
668 * @return WP_REST_Response Response object. |
673 * @return WP_REST_Response Response object. |
669 */ |
674 */ |
670 public function prepare_item_for_response( $item, $request ) { |
675 public function prepare_item_for_response( $item, $request ) { |
671 // Resolve pattern blocks so they don't need to be resolved client-side |
676 // Don't prepare the response body for HEAD requests. |
672 // in the editor, improving performance. |
677 if ( $request->is_method( 'HEAD' ) ) { |
|
678 return new WP_REST_Response( array() ); |
|
679 } |
|
680 |
|
681 /* |
|
682 * Resolve pattern blocks so they don't need to be resolved client-side |
|
683 * in the editor, improving performance. |
|
684 */ |
673 $blocks = parse_blocks( $item->content ); |
685 $blocks = parse_blocks( $item->content ); |
674 $blocks = resolve_pattern_blocks( $blocks ); |
686 $blocks = resolve_pattern_blocks( $blocks ); |
675 $item->content = serialize_blocks( $blocks ); |
687 $item->content = serialize_blocks( $blocks ); |
676 |
688 |
677 // Restores the more descriptive, specific name for use within this method. |
689 // Restores the more descriptive, specific name for use within this method. |
770 $data['author_text'] = self::get_wp_templates_author_text_field( $template ); |
782 $data['author_text'] = self::get_wp_templates_author_text_field( $template ); |
771 } |
783 } |
772 |
784 |
773 if ( rest_is_field_included( 'original_source', $fields ) ) { |
785 if ( rest_is_field_included( 'original_source', $fields ) ) { |
774 $data['original_source'] = self::get_wp_templates_original_source_field( $template ); |
786 $data['original_source'] = self::get_wp_templates_original_source_field( $template ); |
|
787 } |
|
788 |
|
789 if ( rest_is_field_included( 'plugin', $fields ) ) { |
|
790 $registered_template = WP_Block_Templates_Registry::get_instance()->get_by_slug( $template->slug ); |
|
791 if ( $registered_template ) { |
|
792 $data['plugin'] = $registered_template->plugin; |
|
793 } |
775 } |
794 } |
776 |
795 |
777 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; |
796 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; |
778 $data = $this->add_additional_fields_to_object( $data, $request ); |
797 $data = $this->add_additional_fields_to_object( $data, $request ); |
779 $data = $this->filter_response_by_context( $data, $context ); |
798 $data = $this->filter_response_by_context( $data, $context ); |
804 * @param WP_Block_Template $template_object Template instance. |
823 * @param WP_Block_Template $template_object Template instance. |
805 * @return string Original source of the template one of theme, plugin, site, or user. |
824 * @return string Original source of the template one of theme, plugin, site, or user. |
806 */ |
825 */ |
807 private static function get_wp_templates_original_source_field( $template_object ) { |
826 private static function get_wp_templates_original_source_field( $template_object ) { |
808 if ( 'wp_template' === $template_object->type || 'wp_template_part' === $template_object->type ) { |
827 if ( 'wp_template' === $template_object->type || 'wp_template_part' === $template_object->type ) { |
809 // Added by theme. |
828 /* |
810 // Template originally provided by a theme, but customized by a user. |
829 * Added by theme. |
811 // Templates originally didn't have the 'origin' field so identify |
830 * Template originally provided by a theme, but customized by a user. |
812 // older customized templates by checking for no origin and a 'theme' |
831 * Templates originally didn't have the 'origin' field so identify |
813 // or 'custom' source. |
832 * older customized templates by checking for no origin and a 'theme' |
|
833 * or 'custom' source. |
|
834 */ |
814 if ( $template_object->has_theme_file && |
835 if ( $template_object->has_theme_file && |
815 ( 'theme' === $template_object->origin || ( |
836 ( 'theme' === $template_object->origin || ( |
816 empty( $template_object->origin ) && in_array( |
837 empty( $template_object->origin ) && in_array( |
817 $template_object->source, |
838 $template_object->source, |
818 array( |
839 array( |
825 ) { |
846 ) { |
826 return 'theme'; |
847 return 'theme'; |
827 } |
848 } |
828 |
849 |
829 // Added by plugin. |
850 // Added by plugin. |
830 if ( $template_object->has_theme_file && 'plugin' === $template_object->origin ) { |
851 if ( 'plugin' === $template_object->origin ) { |
831 return 'plugin'; |
852 return 'plugin'; |
832 } |
853 } |
833 |
854 |
834 // Added by site. |
855 /* |
835 // Template was created from scratch, but has no author. Author support |
856 * Added by site. |
836 // was only added to templates in WordPress 5.9. Fallback to showing the |
857 * Template was created from scratch, but has no author. Author support |
837 // site logo and title. |
858 * was only added to templates in WordPress 5.9. Fallback to showing the |
|
859 * site logo and title. |
|
860 */ |
838 if ( empty( $template_object->has_theme_file ) && 'custom' === $template_object->source && empty( $template_object->author ) ) { |
861 if ( empty( $template_object->has_theme_file ) && 'custom' === $template_object->source && empty( $template_object->author ) ) { |
839 return 'site'; |
862 return 'site'; |
840 } |
863 } |
841 } |
864 } |
842 |
865 |
857 switch ( $original_source ) { |
880 switch ( $original_source ) { |
858 case 'theme': |
881 case 'theme': |
859 $theme_name = wp_get_theme( $template_object->theme )->get( 'Name' ); |
882 $theme_name = wp_get_theme( $template_object->theme )->get( 'Name' ); |
860 return empty( $theme_name ) ? $template_object->theme : $theme_name; |
883 return empty( $theme_name ) ? $template_object->theme : $theme_name; |
861 case 'plugin': |
884 case 'plugin': |
862 $plugins = get_plugins(); |
885 if ( ! function_exists( 'get_plugins' ) ) { |
863 $plugin = $plugins[ plugin_basename( sanitize_text_field( $template_object->theme . '.php' ) ) ]; |
886 require_once ABSPATH . 'wp-admin/includes/plugin.php'; |
864 return empty( $plugin['Name'] ) ? $template_object->theme : $plugin['Name']; |
887 } |
|
888 if ( isset( $template_object->plugin ) ) { |
|
889 $plugins = wp_get_active_and_valid_plugins(); |
|
890 |
|
891 foreach ( $plugins as $plugin_file ) { |
|
892 $plugin_basename = plugin_basename( $plugin_file ); |
|
893 // Split basename by '/' to get the plugin slug. |
|
894 list( $plugin_slug, ) = explode( '/', $plugin_basename ); |
|
895 |
|
896 if ( $plugin_slug === $template_object->plugin ) { |
|
897 $plugin_data = get_plugin_data( $plugin_file ); |
|
898 |
|
899 if ( ! empty( $plugin_data['Name'] ) ) { |
|
900 return $plugin_data['Name']; |
|
901 } |
|
902 |
|
903 break; |
|
904 } |
|
905 } |
|
906 } |
|
907 |
|
908 /* |
|
909 * Fall back to the theme name if the plugin is not defined. That's needed to keep backwards |
|
910 * compatibility with templates that were registered before the plugin attribute was added. |
|
911 */ |
|
912 $plugins = get_plugins(); |
|
913 $plugin_basename = plugin_basename( sanitize_text_field( $template_object->theme . '.php' ) ); |
|
914 if ( isset( $plugins[ $plugin_basename ] ) && isset( $plugins[ $plugin_basename ]['Name'] ) ) { |
|
915 return $plugins[ $plugin_basename ]['Name']; |
|
916 } |
|
917 return isset( $template_object->plugin ) ? |
|
918 $template_object->plugin : |
|
919 $template_object->theme; |
865 case 'site': |
920 case 'site': |
866 return get_bloginfo( 'name' ); |
921 return get_bloginfo( 'name' ); |
867 case 'user': |
922 case 'user': |
868 $author = get_user_by( 'id', $template_object->author ); |
923 $author = get_user_by( 'id', $template_object->author ); |
869 if ( ! $author ) { |
924 if ( ! $author ) { |
870 return __( 'Unknown author' ); |
925 return __( 'Unknown author' ); |
871 } |
926 } |
872 return $author->get( 'display_name' ); |
927 return $author->get( 'display_name' ); |
873 } |
928 } |
|
929 |
|
930 // Fail-safe to return a string should the original source ever fall through. |
|
931 return ''; |
874 } |
932 } |
875 |
933 |
876 |
934 |
877 /** |
935 /** |
878 * Prepares links for the request. |
936 * Prepares links for the request. |
1123 'description' => __( 'Whether a template is a custom template.' ), |
1181 'description' => __( 'Whether a template is a custom template.' ), |
1124 'type' => 'bool', |
1182 'type' => 'bool', |
1125 'context' => array( 'embed', 'view', 'edit' ), |
1183 'context' => array( 'embed', 'view', 'edit' ), |
1126 'readonly' => true, |
1184 'readonly' => true, |
1127 ); |
1185 ); |
|
1186 $schema['properties']['plugin'] = array( |
|
1187 'type' => 'string', |
|
1188 'description' => __( 'Plugin that registered the template.' ), |
|
1189 'readonly' => true, |
|
1190 'context' => array( 'view', 'edit', 'embed' ), |
|
1191 ); |
1128 } |
1192 } |
1129 |
1193 |
1130 if ( 'wp_template_part' === $this->post_type ) { |
1194 if ( 'wp_template_part' === $this->post_type ) { |
1131 $schema['properties']['area'] = array( |
1195 $schema['properties']['area'] = array( |
1132 'description' => __( 'Where the template part is intended for use (header, footer, etc.)' ), |
1196 'description' => __( 'Where the template part is intended for use (header, footer, etc.)' ), |