Make WordPress Core


Ignore:
Timestamp:
12/02/2016 12:25:47 AM (8 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.

Merges [39411] to 4.7 branch.
See #38114.
Fixes #38928 for 4.7.

Location:
branches/4.7
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/4.7

  • branches/4.7/src/wp-includes/class-wp-customize-manager.php

    r39410 r39412  
    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.