Make WordPress Core


Ignore:
Timestamp:
12/02/2016 12:24:19 AM (10 years ago)
Author:
westonruter
Message:

Customize: Reuse existing non-auto-draft posts and existing auto-draft posts in the customized state with matching slugs when applying starter content.

  • Updates wp_unique_post_slug() to ignore auto-draft posts. Prevents publishing multiple posts that have the same slugs from starter content.
  • Fixes fatal error when attempting to save an header_image setting from a non-admin context.
  • Fixes substituting attachment symbols in options and theme mods.
  • Fixes applying starter content for header images and background images.

See #38114.
Fixes #38928.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r39409 r39411  
    972972                }
    973973
     974                // Make an index of all the posts needed and what their slugs are.
     975                $needed_posts = array();
     976                $attachments = $this->prepare_starter_content_attachments( $attachments );
     977                foreach ( $attachments as $attachment ) {
     978                        $key = 'attachment:' . $attachment['post_name'];
     979                        $needed_posts[ $key ] = true;
     980                }
     981                foreach ( array_keys( $posts ) as $post_symbol ) {
     982                        if ( empty( $posts[ $post_symbol ]['post_name'] ) && empty( $posts[ $post_symbol ]['post_title'] ) ) {
     983                                unset( $posts[ $post_symbol ] );
     984                                continue;
     985                        }
     986                        if ( empty( $posts[ $post_symbol ]['post_name'] ) ) {
     987                                $posts[ $post_symbol ]['post_name'] = sanitize_title( $posts[ $post_symbol ]['post_title'] );
     988                        }
     989                        if ( empty( $posts[ $post_symbol ]['post_type'] ) ) {
     990                                $posts[ $post_symbol ]['post_type'] = 'post';
     991                        }
     992                        $needed_posts[ $posts[ $post_symbol ]['post_type'] . ':' . $posts[ $post_symbol ]['post_name'] ] = true;
     993                }
     994                $all_post_slugs = array_merge(
     995                        wp_list_pluck( $attachments, 'post_name' ),
     996                        wp_list_pluck( $posts, 'post_name' )
     997                );
     998
     999                // Re-use auto-draft starter content posts referenced in the current customized state.
    9741000                $existing_starter_content_posts = array();
    9751001                if ( ! empty( $starter_content_auto_draft_post_ids ) ) {
     
    9851011                }
    9861012
     1013                // Re-use non-auto-draft posts.
     1014                if ( ! empty( $all_post_slugs ) ) {
     1015                        $existing_posts_query = new WP_Query( array(
     1016                                'post_name__in' => $all_post_slugs,
     1017                                'post_status' => array_diff( get_post_stati(), array( 'auto-draft' ) ),
     1018                                'post_type' => 'any',
     1019                                'number' => -1,
     1020                        ) );
     1021                        foreach ( $existing_posts_query->posts as $existing_post ) {
     1022                                $key = $existing_post->post_type . ':' . $existing_post->post_name;
     1023                                if ( isset( $needed_posts[ $key ] ) && ! isset( $existing_starter_content_posts[ $key ] ) ) {
     1024                                        $existing_starter_content_posts[ $key ] = $existing_post;
     1025                                }
     1026                        }
     1027                }
     1028
    9871029                // Attachments are technically posts but handled differently.
    9881030                if ( ! empty( $attachments ) ) {
    989                         // Such is The WordPress Way.
    990                         require_once( ABSPATH . 'wp-admin/includes/file.php' );
    991                         require_once( ABSPATH . 'wp-admin/includes/media.php' );
    992                         require_once( ABSPATH . 'wp-admin/includes/image.php' );
    9931031
    9941032                        $attachment_ids = array();
    9951033
    9961034                        foreach ( $attachments as $symbol => $attachment ) {
    997 
    998                                 // A file is required and URLs to files are not currently allowed.
    999                                 if ( empty( $attachment['file'] ) || preg_match( '#^https?://$#', $attachment['file'] ) ) {
    1000                                         continue;
    1001                                 }
    1002 
    1003                                 $file_array = array();
    1004                                 $file_path = null;
    1005                                 if ( file_exists( $attachment['file'] ) ) {
    1006                                         $file_path = $attachment['file']; // Could be absolute path to file in plugin.
    1007                                 } elseif ( is_child_theme() && file_exists( get_stylesheet_directory() . '/' . $attachment['file'] ) ) {
    1008                                         $file_path = get_stylesheet_directory() . '/' . $attachment['file'];
    1009                                 } elseif ( file_exists( get_template_directory() . '/' . $attachment['file'] ) ) {
    1010                                         $file_path = get_template_directory() . '/' . $attachment['file'];
    1011                                 } else {
    1012                                         continue;
    1013                                 }
    1014                                 $file_array['name'] = basename( $attachment['file'] );
    1015 
    1016                                 // Skip file types that are not recognized.
    1017                                 $checked_filetype = wp_check_filetype( $file_array['name'] );
    1018                                 if ( empty( $checked_filetype['type'] ) ) {
    1019                                         continue;
    1020                                 }
    1021 
    1022                                 // Ensure post_name is set since not automatically derived from post_title for new auto-draft posts.
    1023                                 if ( empty( $attachment['post_name'] ) ) {
    1024                                         if ( ! empty( $attachment['post_title'] ) ) {
    1025                                                 $attachment['post_name'] = sanitize_title( $attachment['post_title'] );
    1026                                         } else {
    1027                                                 $attachment['post_name'] = sanitize_title( preg_replace( '/\.\w+$/', '', $file_array['name'] ) );
    1028                                         }
    1029                                 }
    1030 
     1035                                $file_array = array(
     1036                                        'name' => $attachment['file_name'],
     1037                                );
     1038                                $file_path = $attachment['file_path'];
    10311039                                $attachment_id = null;
    10321040                                $attached_file = null;
     
    10811089
    10821090                                $attachment_ids[ $symbol ] = $attachment_id;
    1083                                 $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, array_values( $attachment_ids ) );
    1084                         }
     1091                        }
     1092                        $starter_content_auto_draft_post_ids = array_merge( $starter_content_auto_draft_post_ids, array_values( $attachment_ids ) );
    10851093                }
    10861094
     
    10881096                if ( ! empty( $posts ) ) {
    10891097                        foreach ( array_keys( $posts ) as $post_symbol ) {
    1090                                 if ( empty( $posts[ $post_symbol ]['post_type'] ) ) {
     1098                                if ( empty( $posts[ $post_symbol ]['post_type'] ) || empty( $posts[ $post_symbol ]['post_name'] ) ) {
    10911099                                        continue;
    10921100                                }
     
    12101218                // Options.
    12111219                foreach ( $options as $name => $value ) {
    1212                         if ( preg_match( '/^{{(?P<symbol>.+)}}$/', $value, $matches ) && isset( $posts[ $matches['symbol'] ] ) ) {
    1213                                 $value = $posts[ $matches['symbol'] ]['ID'];
     1220                        if ( preg_match( '/^{{(?P<symbol>.+)}}$/', $value, $matches ) ) {
     1221                                if ( isset( $posts[ $matches['symbol'] ] ) ) {
     1222                                        $value = $posts[ $matches['symbol'] ]['ID'];
     1223                                } elseif ( isset( $attachment_ids[ $matches['symbol'] ] ) ) {
     1224                                        $value = $attachment_ids[ $matches['symbol'] ];
     1225                                } else {
     1226                                        continue;
     1227                                }
    12141228                        }
    12151229
     
    12221236                // Theme mods.
    12231237                foreach ( $theme_mods as $name => $value ) {
    1224                         if ( preg_match( '/^{{(?P<symbol>.+)}}$/', $value, $matches ) && isset( $posts[ $matches['symbol'] ] ) ) {
    1225                                 $value = $posts[ $matches['symbol'] ]['ID'];
     1238                        if ( preg_match( '/^{{(?P<symbol>.+)}}$/', $value, $matches ) ) {
     1239                                if ( isset( $posts[ $matches['symbol'] ] ) ) {
     1240                                        $value = $posts[ $matches['symbol'] ]['ID'];
     1241                                } elseif ( isset( $attachment_ids[ $matches['symbol'] ] ) ) {
     1242                                        $value = $attachment_ids[ $matches['symbol'] ];
     1243                                } else {
     1244                                        continue;
     1245                                }
     1246                        }
     1247
     1248                        // Handle header image as special case since setting has a legacy format.
     1249                        if ( 'header_image' === $name ) {
     1250                                $name = 'header_image_data';
     1251                                $metadata = wp_get_attachment_metadata( $value );
     1252                                if ( empty( $metadata ) ) {
     1253                                        continue;
     1254                                }
     1255                                $value = array(
     1256                                        'attachment_id' => $value,
     1257                                        'url' => wp_get_attachment_url( $value ),
     1258                                        'height' => $metadata['height'],
     1259                                        'width' => $metadata['width'],
     1260                                );
     1261                        } elseif ( 'background_image' === $name ) {
     1262                                $value = wp_get_attachment_url( $value );
    12261263                        }
    12271264
     
    12391276                        }
    12401277                }
     1278        }
     1279
     1280        /**
     1281         * Prepare starter content attachments.
     1282         *
     1283         * Ensure that the attachments are valid and that they have slugs and file name/path.
     1284         *
     1285         * @since 4.7.0
     1286         * @access private
     1287         *
     1288         * @param array $attachments Attachments.
     1289         * @return array Prepared attachments.
     1290         */
     1291        protected function prepare_starter_content_attachments( $attachments ) {
     1292                $prepared_attachments = array();
     1293                if ( empty( $attachments ) ) {
     1294                        return $prepared_attachments;
     1295                }
     1296
     1297                // Such is The WordPress Way.
     1298                require_once( ABSPATH . 'wp-admin/includes/file.php' );
     1299                require_once( ABSPATH . 'wp-admin/includes/media.php' );
     1300                require_once( ABSPATH . 'wp-admin/includes/image.php' );
     1301
     1302                foreach ( $attachments as $symbol => $attachment ) {
     1303
     1304                        // A file is required and URLs to files are not currently allowed.
     1305                        if ( empty( $attachment['file'] ) || preg_match( '#^https?://$#', $attachment['file'] ) ) {
     1306                                continue;
     1307                        }
     1308
     1309                        $file_path = null;
     1310                        if ( file_exists( $attachment['file'] ) ) {
     1311                                $file_path = $attachment['file']; // Could be absolute path to file in plugin.
     1312                        } elseif ( is_child_theme() && file_exists( get_stylesheet_directory() . '/' . $attachment['file'] ) ) {
     1313                                $file_path = get_stylesheet_directory() . '/' . $attachment['file'];
     1314                        } elseif ( file_exists( get_template_directory() . '/' . $attachment['file'] ) ) {
     1315                                $file_path = get_template_directory() . '/' . $attachment['file'];
     1316                        } else {
     1317                                continue;
     1318                        }
     1319                        $file_name = basename( $attachment['file'] );
     1320
     1321                        // Skip file types that are not recognized.
     1322                        $checked_filetype = wp_check_filetype( $file_name );
     1323                        if ( empty( $checked_filetype['type'] ) ) {
     1324                                continue;
     1325                        }
     1326
     1327                        // Ensure post_name is set since not automatically derived from post_title for new auto-draft posts.
     1328                        if ( empty( $attachment['post_name'] ) ) {
     1329                                if ( ! empty( $attachment['post_title'] ) ) {
     1330                                        $attachment['post_name'] = sanitize_title( $attachment['post_title'] );
     1331                                } else {
     1332                                        $attachment['post_name'] = sanitize_title( preg_replace( '/\.\w+$/', '', $file_name ) );
     1333                                }
     1334                        }
     1335
     1336                        $attachment['file_name'] = $file_name;
     1337                        $attachment['file_path'] = $file_path;
     1338                        $prepared_attachments[ $symbol ] = $attachment;
     1339                }
     1340                return $prepared_attachments;
    12411341        }
    12421342
Note: See TracChangeset for help on using the changeset viewer.