WordPress.org

Make WordPress Core

Changeset 38951


Ignore:
Timestamp:
10/26/16 08:06:43 (15 months ago)
Author:
swissspidy
Message:

Posts, Post Types: Add support for post type templates.

WordPress has supported custom page templates for over 12 years, allowing developers to create various layouts for specific pages.
While this feature is very helpful, it has always been limited to the 'page' post type and not was not available to other post types.

By opening up the page template functionality to all post types, we continue to improve the template hierarchy's flexibility.

In addition to the Template Name file header, the post types supported by a template can be specified using Template Post Type: post, foo, bar.
When at least one template exists for a post type, the 'Post Attributes' meta box will be displayed in the back end, without the need to add post type support for 'page-attributes'. 'Post Attributes' can be customized per post type using the 'attributes' label when registering a post type.

Props johnbillion, Mte90, dipesh.kakadiya, swissspidy.
Fixes #18375.

Location:
trunk
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/edit-form-advanced.php

    r38725 r38951  
    260260} 
    261261 
    262 if ( post_type_supports($post_type, 'page-attributes') ) 
    263     add_meta_box('pageparentdiv', 'page' == $post_type ? __('Page Attributes') : __('Attributes'), 'page_attributes_meta_box', null, 'side', 'core'); 
     262if ( post_type_supports( $post_type, 'page-attributes' ) || count( get_page_templates( null, $post_type ) ) > 0 ) { 
     263    add_meta_box( 'pageparentdiv', $post_type_object->labels->attributes, 'page_attributes_meta_box', null, 'side', 'core' ); 
     264} 
    264265 
    265266if ( $thumbnail_support && current_user_can( 'upload_files' ) ) 
  • trunk/src/wp-admin/includes/class-wp-posts-list-table.php

    r38854 r38951  
    15291529            </label> 
    15301530 
    1531     <?php   endif; // !$bulk 
    1532  
    1533             if ( 'page' === $screen->post_type ) : 
    1534     ?> 
    1535  
    1536             <label> 
    1537                 <span class="title"><?php _e( 'Template' ); ?></span> 
    1538                 <select name="page_template"> 
    1539     <?php   if ( $bulk ) : ?> 
    1540                     <option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option> 
    1541     <?php   endif; // $bulk ?> 
    1542                     <?php 
    1543                     /** This filter is documented in wp-admin/includes/meta-boxes.php */ 
    1544                     $default_title = apply_filters( 'default_page_template_title',  __( 'Default Template' ), 'quick-edit' ); 
    1545                     ?> 
    1546                     <option value="default"><?php echo esc_html( $default_title ); ?></option> 
    1547                     <?php page_template_dropdown() ?> 
    1548                 </select> 
    1549             </label> 
    1550  
    15511531    <?php 
    1552             endif; // page post_type 
     1532            endif; // !$bulk 
    15531533        endif; // page-attributes 
    15541534    ?> 
     1535 
     1536    <?php if ( 0 < count( get_page_templates( null, $screen->post_type ) ) ) : ?> 
     1537        <label> 
     1538            <span class="title"><?php _e( 'Template' ); ?></span> 
     1539            <select name="page_template"> 
     1540<?php   if ( $bulk ) : ?> 
     1541                <option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option> 
     1542<?php   endif; // $bulk ?> 
     1543                <?php 
     1544                /** This filter is documented in wp-admin/includes/meta-boxes.php */ 
     1545                $default_title = apply_filters( 'default_page_template_title',  __( 'Default Template' ), 'quick-edit' ); 
     1546                ?> 
     1547                <option value="default"><?php echo esc_html( $default_title ); ?></option> 
     1548                <?php page_template_dropdown( $post->page_template, $screen->post_type ) ?> 
     1549            </select> 
     1550        </label> 
     1551    <?php endif; ?> 
    15551552 
    15561553    <?php if ( count( $flat_taxonomies ) && !$bulk ) : ?> 
  • trunk/src/wp-admin/includes/meta-boxes.php

    r38880 r38951  
    789789 */ 
    790790function page_attributes_meta_box($post) { 
    791     $post_type_object = get_post_type_object($post->post_type); 
    792     if ( $post_type_object->hierarchical ) { 
     791    if ( is_post_type_hierarchical( $post->post_type ) ) : 
    793792        $dropdown_args = array( 
    794793            'post_type'        => $post->post_type, 
     
    813812        $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); 
    814813        $pages = wp_dropdown_pages( $dropdown_args ); 
    815         if ( ! empty($pages) ) { 
     814        if ( ! empty($pages) ) : 
    816815?> 
    817816<p><strong><?php _e('Parent') ?></strong></p> 
     
    819818<?php echo $pages; ?> 
    820819<?php 
    821         } // end empty pages check 
    822     } // end hierarchical check. 
    823     if ( 'page' == $post->post_type && 0 != count( get_page_templates( $post ) ) && get_option( 'page_for_posts' ) != $post->ID ) { 
    824         $template = !empty($post->page_template) ? $post->page_template : false; 
     820        endif; // end empty pages check 
     821    endif;  // end hierarchical check. 
     822 
     823    if ( count( get_page_templates( $post ) ) > 0 && get_option( 'page_for_posts' ) != $post->ID ) : 
     824        $template = ! empty( $post->page_template ) ? $post->page_template : false; 
    825825        ?> 
    826826<p><strong><?php _e('Template') ?></strong><?php 
     
    836836    do_action( 'page_attributes_meta_box_template', $template, $post ); 
    837837?></p> 
    838 <label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template"> 
     838<label class="screen-reader-text" for="page_template"> 
     839    <?php 
     840    $post_type_object = get_post_type_object( $post->post_type ); 
     841    echo esc_html( $post_type_object->labels->attributes ); 
     842    ?> 
     843</label> 
     844<select name="page_template" id="page_template"> 
    839845<?php 
    840846/** 
     
    850856?> 
    851857<option value="default"><?php echo esc_html( $default_title ); ?></option> 
    852 <?php page_template_dropdown($template); ?> 
     858<?php page_template_dropdown( $template, $post->post_type ); ?> 
    853859</select> 
    854 <?php 
    855     } ?> 
     860<?php endif; ?> 
     861<?php if ( post_type_supports( $post->post_type, 'page-attributes' ) ) : ?> 
    856862<p><strong><?php _e('Order') ?></strong></p> 
    857863<p><label class="screen-reader-text" for="menu_order"><?php _e('Order') ?></label><input name="menu_order" type="text" size="4" id="menu_order" value="<?php echo esc_attr($post->menu_order) ?>" /></p> 
    858 <?php if ( 'page' == $post->post_type && get_current_screen()->get_help_tabs() ) { ?> 
     864<?php if ( 'page' == $post->post_type && get_current_screen()->get_help_tabs() ) : ?> 
    859865<p><?php _e( 'Need help? Use the Help tab above the screen title.' ); ?></p> 
    860 <?php 
    861     } 
     866<?php endif; 
     867    endif; 
    862868} 
    863869 
  • trunk/src/wp-admin/includes/template.php

    r38831 r38951  
    294294    <div class="post_password">' . esc_html( $post->post_password ) . '</div>'; 
    295295 
    296     if ( $post_type_object->hierarchical ) 
     296    if ( $post_type_object->hierarchical ) { 
    297297        echo '<div class="post_parent">' . $post->post_parent . '</div>'; 
    298  
    299     if ( $post->post_type == 'page' ) 
    300         echo '<div class="page_template">' . esc_html( get_post_meta( $post->ID, '_wp_page_template', true ) ) . '</div>'; 
    301  
    302     if ( post_type_supports( $post->post_type, 'page-attributes' ) ) 
     298    } 
     299 
     300    echo '<div class="page_template">' . esc_html( $post->page_template ) . '</div>'; 
     301 
     302    if ( post_type_supports( $post->post_type, 'page-attributes' ) ) { 
    303303        echo '<div class="menu_order">' . $post->menu_order . '</div>'; 
     304    } 
    304305 
    305306    $taxonomy_names = get_object_taxonomies( $post->post_type ); 
     
    762763 * 
    763764 * @since 1.5.0 
    764  * 
    765  * @param string $default Optional. The template file name. Default empty. 
    766  */ 
    767 function page_template_dropdown( $default = '' ) { 
    768     $templates = get_page_templates( get_post() ); 
     765 * @since 4.7.0 Added the `$post_type` parameter. 
     766 * 
     767 * @param string $default   Optional. The template file name. Default empty. 
     768 * @param string $post_type Optional. Post type to get templates for. Default 'post'. 
     769 */ 
     770function page_template_dropdown( $default = '', $post_type = 'page' ) { 
     771    $templates = get_page_templates( null, $post_type ); 
    769772    ksort( $templates ); 
    770773    foreach ( array_keys( $templates ) as $template ) { 
  • trunk/src/wp-admin/includes/theme.php

    r38813 r38951  
    103103 * 
    104104 * @since 1.5.0 
    105  * 
    106  * @param WP_Post|null $post Optional. The post being edited, provided for context. 
     105 * @since 4.7.0 Added the `$post_type` parameter. 
     106 * 
     107 * @param WP_Post|null $post      Optional. The post being edited, provided for context. 
     108 * @param string       $post_type Optional. Post type to get the templates for. Default 'page'. 
    107109 * @return array Key is the template name, value is the filename of the template 
    108110 */ 
    109 function get_page_templates( $post = null ) { 
    110     return array_flip( wp_get_theme()->get_page_templates( $post ) ); 
     111function get_page_templates( $post = null, $post_type = 'page' ) { 
     112    return array_flip( wp_get_theme()->get_page_templates( $post, $post_type ) ); 
    111113} 
    112114 
  • trunk/src/wp-includes/class-wp-post.php

    r38381 r38951  
    255255 
    256256        if ( 'page_template' == $key ) 
    257             return ( 'page' == $this->post_type ); 
     257            return true; 
    258258 
    259259        if ( 'post_category' == $key ) 
  • trunk/src/wp-includes/class-wp-theme.php

    r38839 r38951  
    539539     * @access private 
    540540     * 
    541      * @param string $key Type of data to store (theme, screenshot, headers, page_templates) 
     541     * @param string $key Type of data to store (theme, screenshot, headers, post_templates) 
    542542     * @param string $data Data to store 
    543543     * @return bool Return value from wp_cache_add() 
     
    555555     * @access private 
    556556     * 
    557      * @param string $key Type of data to retrieve (theme, screenshot, headers, page_templates) 
     557     * @param string $key Type of data to retrieve (theme, screenshot, headers, post_templates) 
    558558     * @return mixed Retrieved data 
    559559     */ 
     
    569569     */ 
    570570    public function cache_delete() { 
    571         foreach ( array( 'theme', 'screenshot', 'headers', 'page_templates' ) as $key ) 
     571        foreach ( array( 'theme', 'screenshot', 'headers', 'post_templates' ) as $key ) 
    572572            wp_cache_delete( $key . '-' . $this->cache_hash, 'themes' ); 
    573573        $this->template = $this->textdomain_loaded = $this->theme_root_uri = $this->parent = $this->errors = $this->headers_sanitized = $this->name_translated = null; 
     
    10071007 
    10081008    /** 
    1009      * Returns the theme's page templates. 
    1010      * 
    1011      * @since 3.4.0 
    1012      * @access public 
    1013      * 
    1014      * @param WP_Post|null $post Optional. The post being edited, provided for context. 
     1009     * Returns the theme's post templates. 
     1010     * 
     1011     * @since 4.7.0 
     1012     * @access public 
     1013     * 
     1014     * @return array Array of page templates, keyed by filename and post type, 
     1015     *               with the value of the translated header name. 
     1016     */ 
     1017    public function get_post_templates() { 
     1018        // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide. 
     1019        if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) { 
     1020            return array(); 
     1021        } 
     1022 
     1023        $post_templates = $this->cache_get( 'post_templates' ); 
     1024 
     1025        if ( ! is_array( $post_templates ) ) { 
     1026            $post_templates = array(); 
     1027 
     1028            $files = (array) $this->get_files( 'php', 1 ); 
     1029 
     1030            foreach ( $files as $file => $full_path ) { 
     1031                if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) ) { 
     1032                    continue; 
     1033                } 
     1034 
     1035                $types = array( 'page' ); 
     1036                if ( preg_match( '|Template Post Type:(.*)$|mi', file_get_contents( $full_path ), $type ) ) { 
     1037                    $types = explode( ',', _cleanup_header_comment( $type[1] ) ); 
     1038                } 
     1039 
     1040                foreach ( $types as $type ) { 
     1041                    $type = trim( $type ); 
     1042                    if ( ! isset( $post_templates[ $type ] ) ) { 
     1043                        $post_templates[ $type ] = array(); 
     1044                    } 
     1045 
     1046                    $post_templates[ $type ][ $file ] = _cleanup_header_comment( $header[1] ); 
     1047                } 
     1048            } 
     1049 
     1050            $this->cache_add( 'post_templates', $post_templates ); 
     1051        } 
     1052 
     1053        if ( $this->load_textdomain() ) { 
     1054            foreach ( $post_templates as &$post_type ) { 
     1055                foreach ( $post_type as &$post_template ) { 
     1056                    $post_template = $this->translate_header( 'Template Name', $post_template ); 
     1057                } 
     1058            } 
     1059        } 
     1060 
     1061        return $post_templates; 
     1062    } 
     1063 
     1064    /** 
     1065     * Returns the theme's post templates for a given post type. 
     1066     * 
     1067     * @since 3.4.0 
     1068     * @since 4.7.0 Added the `$post_type` parameter. 
     1069     * @access public 
     1070     * 
     1071     * @param WP_Post|null $post      Optional. The post being edited, provided for context. 
     1072     * @param string       $post_type Optional. Post type to get the templates for. Default 'page'. 
     1073     *                                If a post is provided, its post type is used. 
    10151074     * @return array Array of page templates, keyed by filename, with the value of the translated header name. 
    10161075     */ 
    1017     public function get_page_templates( $post = null ) { 
    1018         // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide. 
    1019         if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) 
    1020             return array(); 
    1021  
    1022         $page_templates = $this->cache_get( 'page_templates' ); 
    1023  
    1024         if ( ! is_array( $page_templates ) ) { 
    1025             $page_templates = array(); 
    1026  
    1027             $files = (array) $this->get_files( 'php', 1 ); 
    1028  
    1029             foreach ( $files as $file => $full_path ) { 
    1030                 if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) ) 
    1031                     continue; 
    1032                 $page_templates[ $file ] = _cleanup_header_comment( $header[1] ); 
    1033             } 
    1034  
    1035             $this->cache_add( 'page_templates', $page_templates ); 
    1036         } 
    1037  
    1038         if ( $this->load_textdomain() ) { 
    1039             foreach ( $page_templates as &$page_template ) { 
    1040                 $page_template = $this->translate_header( 'Template Name', $page_template ); 
    1041             } 
    1042         } 
    1043  
    1044         if ( $this->parent() ) 
    1045             $page_templates += $this->parent()->get_page_templates( $post ); 
     1076    public function get_page_templates( $post = null, $post_type = 'page' ) { 
     1077        if ( $post ) { 
     1078            $post_type = get_post_type( $post ); 
     1079        } 
     1080 
     1081        $post_templates = $this->get_post_templates(); 
     1082        $post_templates = isset( $post_templates[ $post_type ] ) ? $post_templates[ $post_type ] : array(); 
     1083 
     1084        if ( $this->parent() ) { 
     1085            $post_templates += $this->parent()->get_page_templates( $post ); 
     1086        } 
    10461087 
    10471088        /** 
    10481089         * Filters list of page templates for a theme. 
    10491090         * 
     1091         * The dynamic portion of the hook name, `$post_type`, refers to the post type. 
     1092         * 
    10501093         * @since 3.9.0 
    10511094         * @since 4.4.0 Converted to allow complete control over the `$page_templates` array. 
     1095         * @since 4.7.0 Added the `$post_type` parameter. 
    10521096         * 
    1053          * @param array        $page_templates Array of page templates. Keys are filenames, 
     1097         * @param array        $post_templates Array of page templates. Keys are filenames, 
    10541098         *                                     values are translated names. 
    10551099         * @param WP_Theme     $this           The theme object. 
    10561100         * @param WP_Post|null $post           The post being edited, provided for context, or null. 
     1101         * @param string       $post_type      Post type to get the templates for. 
    10571102         */ 
    1058         return (array) apply_filters( 'theme_page_templates', $page_templates, $this, $post ); 
     1103        return (array) apply_filters( "theme_{$post_type}_templates", $post_templates, $this, $post, $post_type ); 
    10591104    } 
    10601105 
  • trunk/src/wp-includes/post-template.php

    r38798 r38951  
    595595        $classes[] = 'error404'; 
    596596 
    597     if ( is_single() ) { 
     597    if ( is_singular() ) { 
    598598        $post_id = $wp_query->get_queried_object_id(); 
    599599        $post = $wp_query->get_queried_object(); 
    600  
    601         $classes[] = 'single'; 
    602         if ( isset( $post->post_type ) ) { 
    603             $classes[] = 'single-' . sanitize_html_class($post->post_type, $post_id); 
    604             $classes[] = 'postid-' . $post_id; 
    605  
    606             // Post Format 
    607             if ( post_type_supports( $post->post_type, 'post-formats' ) ) { 
    608                 $post_format = get_post_format( $post->ID ); 
    609  
    610                 if ( $post_format && !is_wp_error($post_format) ) 
    611                     $classes[] = 'single-format-' . sanitize_html_class( $post_format ); 
    612                 else 
    613                     $classes[] = 'single-format-standard'; 
     600        $post_type = $post->post_type; 
     601 
     602        if ( is_page_template() ) { 
     603            $classes[] = "{$post_type}-template"; 
     604 
     605            $template_slug  = get_page_template_slug( $post_id ); 
     606            $template_parts = explode( '/', $template_slug ); 
     607 
     608            foreach ( $template_parts as $part ) { 
     609                $classes[] = "{$post_type}-template-" . sanitize_html_class( str_replace( array( '.', '/' ), '-', basename( $part, '.php' ) ) ); 
     610            } 
     611            $classes[] = "{$post_type}-template-" . sanitize_html_class( str_replace( '.', '-', $template_slug ) ); 
     612        } else { 
     613            $classes[] = "{$post_type}-template-default"; 
     614        } 
     615 
     616        if ( is_single() ) { 
     617            $classes[] = 'single'; 
     618            if ( isset( $post->post_type ) ) { 
     619                $classes[] = 'single-' . sanitize_html_class( $post->post_type, $post_id ); 
     620                $classes[] = 'postid-' . $post_id; 
     621 
     622                // Post Format 
     623                if ( post_type_supports( $post->post_type, 'post-formats' ) ) { 
     624                    $post_format = get_post_format( $post->ID ); 
     625 
     626                    if ( $post_format && !is_wp_error($post_format) ) 
     627                        $classes[] = 'single-format-' . sanitize_html_class( $post_format ); 
     628                    else 
     629                        $classes[] = 'single-format-standard'; 
     630                } 
    614631            } 
    615632        } 
     
    620637            $classes[] = 'attachmentid-' . $post_id; 
    621638            $classes[] = 'attachment-' . str_replace( $mime_prefix, '', $mime_type ); 
     639        } elseif ( is_page() ) { 
     640            $classes[] = 'page'; 
     641 
     642            $page_id = $wp_query->get_queried_object_id(); 
     643 
     644            $post = get_post($page_id); 
     645 
     646            $classes[] = 'page-id-' . $page_id; 
     647 
     648            if ( get_pages( array( 'parent' => $page_id, 'number' => 1 ) ) ) { 
     649                $classes[] = 'page-parent'; 
     650            } 
     651 
     652            if ( $post->post_parent ) { 
     653                $classes[] = 'page-child'; 
     654                $classes[] = 'parent-pageid-' . $post->post_parent; 
     655            } 
    622656        } 
    623657    } elseif ( is_archive() ) { 
     
    671705                $classes[] = 'term-' . $term->term_id; 
    672706            } 
    673         } 
    674     } elseif ( is_page() ) { 
    675         $classes[] = 'page'; 
    676  
    677         $page_id = $wp_query->get_queried_object_id(); 
    678  
    679         $post = get_post($page_id); 
    680  
    681         $classes[] = 'page-id-' . $page_id; 
    682  
    683         if ( get_pages( array( 'parent' => $page_id, 'number' => 1 ) ) ) { 
    684             $classes[] = 'page-parent'; 
    685         } 
    686  
    687         if ( $post->post_parent ) { 
    688             $classes[] = 'page-child'; 
    689             $classes[] = 'parent-pageid-' . $post->post_parent; 
    690         } 
    691         if ( is_page_template() ) { 
    692             $classes[] = 'page-template'; 
    693  
    694             $template_slug  = get_page_template_slug( $page_id ); 
    695             $template_parts = explode( '/', $template_slug ); 
    696  
    697             foreach ( $template_parts as $part ) { 
    698                 $classes[] = 'page-template-' . sanitize_html_class( str_replace( array( '.', '/' ), '-', basename( $part, '.php' ) ) ); 
    699             } 
    700             $classes[] = 'page-template-' . sanitize_html_class( str_replace( '.', '-', $template_slug ) ); 
    701         } else { 
    702             $classes[] = 'page-template-default'; 
    703707        } 
    704708    } 
     
    16221626 * @since 2.5.0 
    16231627 * @since 4.2.0 The `$template` parameter was changed to also accept an array of page templates. 
     1628 * @since 4.7.0 Now works with any post type, not just pages. 
    16241629 * 
    16251630 * @param string|array $template The specific template name or array of templates to match. 
     
    16271632 */ 
    16281633function is_page_template( $template = '' ) { 
    1629     if ( ! is_page() ) 
    1630         return false; 
    1631  
    16321634    $page_template = get_page_template_slug( get_queried_object_id() ); 
    16331635 
     
    16501652 
    16511653/** 
    1652  * Get the specific template name for a page. 
     1654 * Get the specific template name for a given post. 
    16531655 * 
    16541656 * @since 3.4.0 
    1655  * 
    1656  * @param int $post_id Optional. The page ID to check. Defaults to the current post, when used in the loop. 
     1657 * @since 4.7.0 Now works with any post type, not just pages. 
     1658 * 
     1659 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. 
    16571660 * @return string|false Page template filename. Returns an empty string when the default page template 
    1658  *  is in use. Returns false if the post is not a page. 
    1659  */ 
    1660 function get_page_template_slug( $post_id = null ) { 
    1661     $post = get_post( $post_id ); 
    1662     if ( ! $post || 'page' != $post->post_type ) 
     1661 *  is in use. Returns false if the post does not exist. 
     1662 */ 
     1663function get_page_template_slug( $post = null ) { 
     1664    $post = get_post( $post ); 
     1665 
     1666    if ( ! $post ) { 
    16631667        return false; 
     1668    } 
     1669 
    16641670    $template = get_post_meta( $post->ID, '_wp_page_template', true ); 
    1665     if ( ! $template || 'default' == $template ) 
     1671 
     1672    if ( ! $template || 'default' == $template ) { 
    16661673        return ''; 
     1674    } 
     1675 
    16671676    return $template; 
    16681677} 
  • trunk/src/wp-includes/post.php

    r38925 r38951  
    6767            'edit_item' => __( 'Edit Media' ), 
    6868            'view_item' => __( 'View Attachment Page' ), 
     69            'attributes' => __( 'Attachment Attributes' ), 
    6970        ), 
    7071        'public' => true, 
     
    13271328 * - `all_items` - Label to signify all items in a submenu link. Default is 'All Posts' / 'All Pages'. 
    13281329 * - `archives` - Label for archives in nav menus. Default is 'Post Archives' / 'Page Archives'. 
     1330 * - `attributes` - Label for the attributes meta box. Default is 'Post Attributes' / 'Page Attributes'. 
    13291331 * - `insert_into_item` - Label for the media frame button. Default is 'Insert into post' / 'Insert into page'. 
    13301332 * - `uploaded_to_this_item` - Label for the media frame filter. Default is 'Uploaded to this post' / 
     
    13521354 *              `items_list_navigation`, and `items_list` labels. 
    13531355 * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object. 
    1354  * @since 4.7.0 Added the `view_items` label. 
     1356 * @since 4.7.0 Added the `view_items` and `attributes` labels. 
    13551357 * 
    13561358 * @access private 
     
    13751377        'all_items' => array( __( 'All Posts' ), __( 'All Pages' ) ), 
    13761378        'archives' => array( __( 'Post Archives' ), __( 'Page Archives' ) ), 
     1379        'attributes' => array( __( 'Post Attributes' ), __( 'Page Attributes' ) ), 
    13771380        'insert_into_item' => array( __( 'Insert into post' ), __( 'Insert into page' ) ), 
    13781381        'uploaded_to_this_item' => array( __( 'Uploaded to this post' ), __( 'Uploaded to this page' ) ), 
     
    33943397    $post = get_post( $post_ID ); 
    33953398 
    3396     if ( ! empty( $postarr['page_template'] ) && 'page' == $data['post_type'] ) { 
     3399    if ( ! empty( $postarr['page_template'] ) ) { 
    33973400        $post->page_template = $postarr['page_template']; 
    33983401        $page_templates = wp_get_theme()->get_page_templates( $post ); 
  • trunk/src/wp-includes/template.php

    r38789 r38951  
    450450 * The hierarchy for this template looks like: 
    451451 * 
    452  * 1. single-{post_type}-{post_name}.php 
    453  * 2. single-{post_type}.php 
    454  * 3. single.php 
    455  * 
    456  * An example of this is: 
    457  * 
    458  * 1. single-post-hello-world.php 
    459  * 2. single-post.php 
    460  * 3. single.php 
     452 * 1. {Post Type Template}.php 
     453 * 2. single-{post_type}-{post_name}.php 
     454 * 3. single-{post_type}.php 
     455 * 4. single.php 
     456 * 
     457 * An example of this is: 
     458 * 
     459 * 1. templates/full-width.php 
     460 * 2. single-post-hello-world.php 
     461 * 3. single-post.php 
     462 * 4. single.php 
    461463 * 
    462464 * The template hierarchy is filterable via the {@see 'single_template_hierarchy'} hook. 
     
    467469 * @since 4.7.0 The decoded form of `single-{post_type}-{post_name}.php` was added to the top of the 
    468470 *              template hierarchy when the post name contains multibyte characters. 
     471 * @since 4.7.0 {Post Type Template}.php was added to the top of the template hierarchy. 
    469472 * 
    470473 * @see get_query_template() 
     
    478481 
    479482    if ( ! empty( $object->post_type ) ) { 
     483        $template = get_page_template_slug( $object ); 
     484        if ( $template && 0 === validate_file( $template ) ) { 
     485            $templates[] = $template; 
     486        } 
    480487 
    481488        $name_decoded = urldecode( $object->post_name ); 
  • trunk/tests/phpunit/tests/admin/includesTheme.php

    r25409 r38951  
    4949        switch_theme( $theme['Template'], $theme['Stylesheet'] ); 
    5050 
    51         $templates = get_page_templates(); 
    52         $this->assertCount( 3, $templates ); 
    53         $this->assertEquals( "template-top-level.php", $templates['Top Level'] ); 
    54         $this->assertEquals( "subdir/template-sub-dir.php", $templates['Sub Dir'] ); 
    55         $this->assertEquals( "template-header.php", $templates['This Template Header Is On One Line'] ); 
     51        $this->assertEqualSetsWithIndex( array( 
     52            'Top Level'                           => 'template-top-level.php', 
     53            'Sub Dir'                             => 'subdir/template-sub-dir.php', 
     54            'This Template Header Is On One Line' => 'template-header.php', 
     55        ), get_page_templates() ); 
    5656 
    5757        $theme = wp_get_theme( 'page-templates' ); 
     
    6060        switch_theme( $theme['Template'], $theme['Stylesheet'] ); 
    6161 
    62         $templates = get_page_templates(); 
    63         $this->assertCount( 3, $templates ); 
    64         $this->assertEquals( "template-top-level.php", $templates['Top Level'] ); 
    65         $this->assertEquals( "subdir/template-sub-dir.php", $templates['Sub Dir'] ); 
    66         $this->assertEquals( "template-header.php", $templates['This Template Header Is On One Line'] ); 
     62        $this->assertEqualSetsWithIndex( array( 
     63            'Top Level'                           => 'template-top-level.php', 
     64            'Sub Dir'                             => 'subdir/template-sub-dir.php', 
     65            'This Template Header Is On One Line' => 'template-header.php', 
     66        ), get_page_templates() ); 
     67    } 
     68 
     69    /** 
     70     * @ticket 18375 
     71     */ 
     72    function test_page_templates_different_post_types() { 
     73        $theme = wp_get_theme( 'page-templates' ); 
     74        $this->assertNotEmpty( $theme ); 
     75 
     76        switch_theme( $theme['Template'], $theme['Stylesheet'] ); 
     77 
     78        $this->assertEqualSetsWithIndex( array( 
     79            'Top Level' => 'template-top-level-post-types.php', 
     80            'Sub Dir'   => 'subdir/template-sub-dir-post-types.php', 
     81        ), get_page_templates( null, 'foo' ) ); 
     82        $this->assertEqualSetsWithIndex( array( 
     83            'Top Level' => 'template-top-level-post-types.php', 
     84            'Sub Dir'   => 'subdir/template-sub-dir-post-types.php', 
     85        ), get_page_templates( null, 'post' ) ); 
     86        $this->assertEquals( array(), get_page_templates( null, 'bar' ) ); 
    6787    } 
    6888} 
  • trunk/tests/phpunit/tests/post/getBodyClass.php

    r37249 r38951  
    9393    } 
    9494 
     95    public function test_page_template_body_classes_no_template() { 
     96        $post_id = self::factory()->post->create( array( 
     97            'post_type' => 'page', 
     98        ) ); 
     99        $this->go_to( get_permalink( $post_id ) ); 
     100 
     101        $class = get_body_class(); 
     102 
     103        $this->assertNotContains( 'page-template', $class ); 
     104        $this->assertContains( 'page-template-default', $class ); 
     105    } 
     106 
     107    public function test_page_template_body_classes() { 
     108        $post_id = self::factory()->post->create( array( 
     109            'post_type' => 'page', 
     110        ) ); 
     111 
     112        add_post_meta( $post_id, '_wp_page_template', 'templates/cpt.php' ); 
     113 
     114        $this->go_to( get_permalink( $post_id ) ); 
     115 
     116        $class = get_body_class(); 
     117 
     118        $this->assertContains( 'page-template', $class ); 
     119        $this->assertContains( 'page-template-templates', $class ); 
     120        $this->assertContains( 'page-template-cpt', $class ); 
     121        $this->assertContains( 'page-template-templatescpt-php', $class ); 
     122    } 
     123 
     124    /** 
     125     * @ticket 18375 
     126     */ 
     127    public function test_page_template_body_classes_attachment() { 
     128        $post_id = self::factory()->post->create( array( 
     129            'post_type' => 'attachment', 
     130        ) ); 
     131 
     132        add_post_meta( $post_id, '_wp_page_template', 'templates/cpt.php' ); 
     133 
     134        $this->go_to( get_permalink( $post_id ) ); 
     135 
     136        $class = get_body_class(); 
     137 
     138        $this->assertContains( 'attachment-template', $class ); 
     139        $this->assertContains( 'attachment-template-templates', $class ); 
     140        $this->assertContains( 'attachment-template-cpt', $class ); 
     141        $this->assertContains( 'attachment-template-templatescpt-php', $class ); 
     142    } 
     143 
     144    /** 
     145     * @ticket 18375 
     146     */ 
     147    public function test_page_template_body_classes_post() { 
     148        $post_id = self::factory()->post->create(); 
     149 
     150        add_post_meta( $post_id, '_wp_page_template', 'templates/cpt.php' ); 
     151 
     152        $this->go_to( get_permalink( $post_id ) ); 
     153 
     154        $class = get_body_class(); 
     155 
     156        $this->assertContains( 'post-template', $class ); 
     157        $this->assertContains( 'post-template-templates', $class ); 
     158        $this->assertContains( 'post-template-cpt', $class ); 
     159        $this->assertContains( 'post-template-templatescpt-php', $class ); 
     160    } 
    95161} 
  • trunk/tests/phpunit/tests/post/objects.php

    r35242 r38951  
    146146        $template = get_post_meta( $post->ID, '_wp_page_template', true ); 
    147147        $this->assertEquals( 'foo.php', $template ); 
    148         // The post is not a page so the template is still empty 
    149         $this->assertEquals( '', $post->page_template ); 
    150  
    151         // Now the post is a page and should retrieve the template 
    152         wp_update_post( array( 'ID' => $post->ID, 'post_type' => 'page' ) ); 
    153         $post = get_post( $post_id ); 
    154148        $this->assertEquals( $template, $post->page_template ); 
    155149    } 
  • trunk/tests/phpunit/tests/post/template.php

    r38523 r38951  
    272272    /** 
    273273     * @ticket 31389 
     274     * @ticket 18375 
    274275     */ 
    275276    public function test_get_page_template_slug_non_page() { 
    276         $post_id = self::factory()->post->create( array( 
    277             'post_type' => 'post', 
    278         ) ); 
    279  
    280         $this->assertFalse( get_page_template_slug( $post_id ) ); 
     277        $post_id = self::factory()->post->create(); 
     278 
     279        $this->assertEquals( '', get_page_template_slug( $post_id ) ); 
     280 
     281        update_post_meta( $post_id, '_wp_page_template', 'default' ); 
     282 
     283        $this->assertEquals( '', get_page_template_slug( $post_id ) ); 
     284 
     285        update_post_meta( $post_id, '_wp_page_template', 'example.php' ); 
     286        $this->assertEquals( 'example.php', get_page_template_slug( $post_id ) ); 
     287    } 
     288 
     289    /** 
     290     * @ticket 18375 
     291     */ 
     292    public function test_get_page_template_slug_non_page_from_loop() { 
     293        $post_id = self::factory()->post->create(); 
     294 
     295        update_post_meta( $post_id, '_wp_page_template', 'example.php' ); 
    281296 
    282297        $this->go_to( get_permalink( $post_id ) ); 
    283         $this->assertFalse( get_page_template_slug() ); 
     298 
     299        $this->assertEquals( 'example.php', get_page_template_slug() ); 
    284300    } 
    285301 
  • trunk/tests/phpunit/tests/query/conditionals.php

    r38938 r38951  
    10451045 
    10461046    /** 
     1047     * @ticket 18375 
     1048     */ 
     1049    function test_is_page_template_other_post_type() { 
     1050        $post_id = self::factory()->post->create( array( 'post_type' => 'post' ) ); 
     1051        update_post_meta( $post_id, '_wp_page_template', 'example.php' ); 
     1052        $this->go_to( get_post_permalink( $post_id ) ); 
     1053        $this->assertFalse( is_page_template( array( 'test.php' ) ) ); 
     1054        $this->assertTrue( is_page_template( array( 'test.php', 'example.php' ) ) ); 
     1055    } 
     1056 
     1057    /** 
    10471058     * @ticket 35902 
    10481059     */ 
  • trunk/tests/phpunit/tests/template.php

    r38583 r38951  
    3737        ) ); 
    3838        set_post_format( self::$post, 'quote' ); 
     39        add_post_meta( self::$post->ID, '_wp_page_template', 'templates/post.php' ); 
    3940    } 
    4041 
     
    204205    } 
    205206 
     207    /** 
     208     * @ticket 18375 
     209     */ 
    206210    public function test_single_template_hierarchy_for_post() { 
    207211        $this->assertTemplateHierarchy( get_permalink( self::$post ), array( 
     212            'templates/post.php', 
    208213            'single-post-post-name-😀.php', 
    209214            'single-post-post-name-%f0%9f%98%80.php', 
     
    221226 
    222227        $this->assertTemplateHierarchy( get_permalink( $cpt ), array( 
     228            'single-cpt-cpt-name-😀.php', 
     229            'single-cpt-cpt-name-%f0%9f%98%80.php', 
     230            'single-cpt.php', 
     231            'single.php', 
     232            'singular.php', 
     233        ) ); 
     234    } 
     235 
     236    /** 
     237     * @ticket 18375 
     238     */ 
     239    public function test_single_template_hierarchy_for_custom_post_type_with_template() { 
     240        $cpt = self::factory()->post->create_and_get( array( 
     241            'post_type' => 'cpt', 
     242            'post_name' => 'cpt-name-😀', 
     243        ) ); 
     244        add_post_meta( $cpt->ID, '_wp_page_template', 'templates/cpt.php' ); 
     245 
     246        $this->assertTemplateHierarchy( get_permalink( $cpt ), array( 
     247            'templates/cpt.php', 
    223248            'single-cpt-cpt-name-😀.php', 
    224249            'single-cpt-cpt-name-%f0%9f%98%80.php', 
     
    248273    } 
    249274 
     275    /** 
     276     * @ticket 18375 
     277     */ 
     278    public function test_attachment_template_hierarchy_with_template() { 
     279        $attachment = self::factory()->attachment->create_and_get( array( 
     280            'post_name'      => 'attachment-name-😀', 
     281            'file'           => 'image.jpg', 
     282            'post_mime_type' => 'image/jpeg', 
     283        ) ); 
     284 
     285        add_post_meta( $attachment, '_wp_page_template', 'templates/cpt.php' ); 
     286 
     287        $this->assertTemplateHierarchy( get_permalink( $attachment ), array( 
     288            'image-jpeg.php', 
     289            'jpeg.php', 
     290            'image.php', 
     291            'attachment.php', 
     292            'single-attachment-attachment-name-😀.php', 
     293            'single-attachment-attachment-name-%f0%9f%98%80.php', 
     294            'single-attachment.php', 
     295            'single.php', 
     296            'singular.php', 
     297        ) ); 
     298    } 
     299 
    250300    public function test_embed_template_hierarchy_for_post() { 
    251301        $this->assertTemplateHierarchy( get_post_embed_url( self::$post ), array( 
     
    253303            'embed-post.php', 
    254304            'embed.php', 
     305            'templates/post.php', 
    255306            'single-post-post-name-😀.php', 
    256307            'single-post-post-name-%f0%9f%98%80.php', 
Note: See TracChangeset for help on using the changeset viewer.