WordPress.org

Make WordPress Core

Changeset 38951


Ignore:
Timestamp:
10/26/2016 08:06:43 AM (19 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.