Ensure that a user can publish_posts before making a post sticky.
Props: danielbachhuber, whyisjake, peterwilson, xknown. Prevent stored XSS through wp_targeted_link_rel(). Props: vortfu, whyisjake, peterwilsoncc, xknown, SergeyBiryukov, flaviozavan. Update `wp_kses_bad_protocol()` to recognize `:` on uri attributes, `wp_kses_bad_protocol()` makes sure to validate that uri attributes don’t contain invalid/or not allowed protocols. While this works fine in most cases, there’s a risk that by using the colon html5 named entity, one is able to bypass this function. Brings r46895 to the 5.3 branch. Props: xknown, nickdaugherty, peterwilsoncc. Prevent stored XSS in the block editor. Brings r46896 to the 5.3 branch. Prevent escaped unicode characters become unescaped in unsafe HTML during JSON decoding. Props: aduth, epiqueras. Built from https://develop.svn.wordpress.org/branches/5.2@46901 git-svn-id: http://core.svn.wordpress.org/branches/5.2@46701 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
373c82a7c4
commit
da95cca74c
|
@ -74,11 +74,11 @@ function has_blocks( $post = null ) {
|
||||||
* @since 5.0.0
|
* @since 5.0.0
|
||||||
* @see parse_blocks()
|
* @see parse_blocks()
|
||||||
*
|
*
|
||||||
* @param string $block_type Full Block type to look for.
|
* @param string $block_name Full Block type to look for.
|
||||||
* @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
|
* @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
|
||||||
* @return bool Whether the post content contains the specified block.
|
* @return bool Whether the post content contains the specified block.
|
||||||
*/
|
*/
|
||||||
function has_block( $block_type, $post = null ) {
|
function has_block( $block_name, $post = null ) {
|
||||||
if ( ! has_blocks( $post ) ) {
|
if ( ! has_blocks( $post ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,30 @@ function has_block( $block_type, $post = null ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false !== strpos( $post, '<!-- wp:' . $block_type . ' ' );
|
/*
|
||||||
|
* Normalize block name to include namespace, if provided as non-namespaced.
|
||||||
|
* This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
|
||||||
|
* their serialized names.
|
||||||
|
*/
|
||||||
|
if ( false === strpos( $block_name, '/' ) ) {
|
||||||
|
$block_name = 'core/' . $block_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for existence of block by its fully qualified name.
|
||||||
|
$has_block = false !== strpos( $post, '<!-- wp:' . $block_name . ' ' );
|
||||||
|
|
||||||
|
if ( ! $has_block ) {
|
||||||
|
/*
|
||||||
|
* If the given block name would serialize to a different name, test for
|
||||||
|
* existence by the serialized form.
|
||||||
|
*/
|
||||||
|
$serialized_block_name = strip_core_block_namespace( $block_name );
|
||||||
|
if ( $serialized_block_name !== $block_name ) {
|
||||||
|
$has_block = false !== strpos( $post, '<!-- wp:' . $serialized_block_name . ' ' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $has_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,6 +136,207 @@ function get_dynamic_block_names() {
|
||||||
return $dynamic_block_names;
|
return $dynamic_block_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an array of attributes, returns a string in the serialized attributes
|
||||||
|
* format prepared for post content.
|
||||||
|
*
|
||||||
|
* The serialized result is a JSON-encoded string, with unicode escape sequence
|
||||||
|
* substitution for characters which might otherwise interfere with embedding
|
||||||
|
* the result in an HTML comment.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param array $attributes Attributes object.
|
||||||
|
* @return string Serialized attributes.
|
||||||
|
*/
|
||||||
|
function serialize_block_attributes( $block_attributes ) {
|
||||||
|
$encoded_attributes = json_encode( $block_attributes );
|
||||||
|
$encoded_attributes = preg_replace( '/--/', '\\u002d\\u002d', $encoded_attributes );
|
||||||
|
$encoded_attributes = preg_replace( '/</', '\\u003c', $encoded_attributes );
|
||||||
|
$encoded_attributes = preg_replace( '/>/', '\\u003e', $encoded_attributes );
|
||||||
|
$encoded_attributes = preg_replace( '/&/', '\\u0026', $encoded_attributes );
|
||||||
|
// Regex: /\\"/
|
||||||
|
$encoded_attributes = preg_replace( '/\\\\"/', '\\u0022', $encoded_attributes );
|
||||||
|
|
||||||
|
return $encoded_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the block name to use for serialization. This will remove the default
|
||||||
|
* "core/" namespace from a block name.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param string $block_name Original block name.
|
||||||
|
* @return string Block name to use for serialization.
|
||||||
|
*/
|
||||||
|
function strip_core_block_namespace( $block_name = null ) {
|
||||||
|
if ( is_string( $block_name ) && 0 === strpos( $block_name, 'core/' ) ) {
|
||||||
|
return substr( $block_name, 5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content of a block, including comment delimiters.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param string $block_name Block name.
|
||||||
|
* @param array $attributes Block attributes.
|
||||||
|
* @param string $content Block save content.
|
||||||
|
* @return string Comment-delimited block content.
|
||||||
|
*/
|
||||||
|
function get_comment_delimited_block_content( $block_name = null, $block_attributes, $block_content ) {
|
||||||
|
if ( is_null( $block_name ) ) {
|
||||||
|
return $block_content;
|
||||||
|
}
|
||||||
|
|
||||||
|
$serialized_block_name = strip_core_block_namespace( $block_name );
|
||||||
|
$serialized_attributes = empty( $block_attributes ) ? '' : serialize_block_attributes( $block_attributes ) . ' ';
|
||||||
|
|
||||||
|
if ( empty( $block_content ) ) {
|
||||||
|
return sprintf( '<!-- wp:%s %s/-->', $serialized_block_name, $serialized_attributes );
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
'<!-- wp:%s %s-->%s<!-- /wp:%s -->',
|
||||||
|
$serialized_block_name,
|
||||||
|
$serialized_attributes,
|
||||||
|
$block_content,
|
||||||
|
$serialized_block_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content of a block, including comment delimiters, serializing all
|
||||||
|
* attributes from the given parsed block.
|
||||||
|
*
|
||||||
|
* This should be used when preparing a block to be saved to post content.
|
||||||
|
* Prefer `render_block` when preparing a block for display. Unlike
|
||||||
|
* `render_block`, this does not evaluate a block's `render_callback`, and will
|
||||||
|
* instead preserve the markup as parsed.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param WP_Block_Parser_Block $block A single parsed block object.
|
||||||
|
* @return string String of rendered HTML.
|
||||||
|
*/
|
||||||
|
function serialize_block( $block ) {
|
||||||
|
$block_content = '';
|
||||||
|
|
||||||
|
$index = 0;
|
||||||
|
foreach ( $block['innerContent'] as $chunk ) {
|
||||||
|
$block_content .= is_string( $chunk ) ? $chunk : serialize_block( $block['innerBlocks'][ $index++ ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! is_array( $block['attrs'] ) ) {
|
||||||
|
$block['attrs'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_comment_delimited_block_content(
|
||||||
|
$block['blockName'],
|
||||||
|
$block['attrs'],
|
||||||
|
$block_content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a joined string of the aggregate serialization of the given parsed
|
||||||
|
* blocks.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param WP_Block_Parser_Block[] $blocks Parsed block objects.
|
||||||
|
* @return string String of rendered HTML.
|
||||||
|
*/
|
||||||
|
function serialize_blocks( $blocks ) {
|
||||||
|
return implode( '', array_map( 'serialize_block', $blocks ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters and sanitizes block content to remove non-allowable HTML from
|
||||||
|
* parsed block attribute values.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param string $text Text that may contain block content.
|
||||||
|
* @param array[]|string $allowed_html An array of allowed HTML elements
|
||||||
|
* and attributes, or a context name
|
||||||
|
* such as 'post'.
|
||||||
|
* @param string[] $allowed_protocols Array of allowed URL protocols.
|
||||||
|
* @return string The filtered and sanitized content result.
|
||||||
|
*/
|
||||||
|
function filter_block_content( $text, $allowed_html = 'post', $allowed_protocols = array() ) {
|
||||||
|
$result = '';
|
||||||
|
|
||||||
|
$blocks = parse_blocks( $text );
|
||||||
|
foreach ( $blocks as $block ) {
|
||||||
|
$block = filter_block_kses( $block, $allowed_html, $allowed_protocols );
|
||||||
|
$result .= serialize_block( $block );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters and sanitizes a parsed block to remove non-allowable HTML from block
|
||||||
|
* attribute values.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param WP_Block_Parser_Block $block The parsed block object.
|
||||||
|
* @param array[]|string $allowed_html An array of allowed HTML
|
||||||
|
* elements and attributes, or a
|
||||||
|
* context name such as 'post'.
|
||||||
|
* @param string[] $allowed_protocols Allowed URL protocols.
|
||||||
|
* @return array The filtered and sanitized block object result.
|
||||||
|
*/
|
||||||
|
function filter_block_kses( $block, $allowed_html, $allowed_protocols = array() ) {
|
||||||
|
$block['attrs'] = filter_block_kses_value( $block['attrs'], $allowed_html, $allowed_protocols );
|
||||||
|
|
||||||
|
if ( is_array( $block['innerBlocks'] ) ) {
|
||||||
|
foreach ( $block['innerBlocks'] as $i => $inner_block ) {
|
||||||
|
$block['innerBlocks'][ $i ] = filter_block_kses( $inner_block, $allowed_html, $allowed_protocols );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters and sanitizes a parsed block attribute value to remove non-allowable
|
||||||
|
* HTML.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param mixed $value The attribute value to filter.
|
||||||
|
* @param array[]|string $allowed_html An array of allowed HTML elements
|
||||||
|
* and attributes, or a context name
|
||||||
|
* such as 'post'.
|
||||||
|
* @param string[] $allowed_protocols Array of allowed URL protocols.
|
||||||
|
* @return array The filtered and sanitized result.
|
||||||
|
*/
|
||||||
|
function filter_block_kses_value( $value, $allowed_html, $allowed_protocols = array() ) {
|
||||||
|
if ( is_array( $value ) ) {
|
||||||
|
foreach ( $value as $key => $inner_value ) {
|
||||||
|
$filtered_key = filter_block_kses_value( $key, $allowed_html, $allowed_protocols );
|
||||||
|
$filtered_value = filter_block_kses_value( $inner_value, $allowed_html, $allowed_protocols );
|
||||||
|
|
||||||
|
if ( $filtered_key !== $key ) {
|
||||||
|
unset( $value[ $key ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
$value[ $filtered_key ] = $filtered_value;
|
||||||
|
}
|
||||||
|
} elseif ( is_string( $value ) ) {
|
||||||
|
return wp_kses( $value, $allowed_html, $allowed_protocols );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses blocks out of a content string, and renders those appropriate for the excerpt.
|
* Parses blocks out of a content string, and renders those appropriate for the excerpt.
|
||||||
*
|
*
|
||||||
|
|
|
@ -245,6 +245,7 @@ add_filter( 'option_siteurl', '_config_wp_siteurl' );
|
||||||
add_filter( 'tiny_mce_before_init', '_mce_set_direction' );
|
add_filter( 'tiny_mce_before_init', '_mce_set_direction' );
|
||||||
add_filter( 'teeny_mce_before_init', '_mce_set_direction' );
|
add_filter( 'teeny_mce_before_init', '_mce_set_direction' );
|
||||||
add_filter( 'pre_kses', 'wp_pre_kses_less_than' );
|
add_filter( 'pre_kses', 'wp_pre_kses_less_than' );
|
||||||
|
add_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10, 3 );
|
||||||
add_filter( 'sanitize_title', 'sanitize_title_with_dashes', 10, 3 );
|
add_filter( 'sanitize_title', 'sanitize_title_with_dashes', 10, 3 );
|
||||||
add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 );
|
add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 );
|
||||||
add_filter( 'comment_flood_filter', 'wp_throttle_comment_flood', 10, 3 );
|
add_filter( 'comment_flood_filter', 'wp_throttle_comment_flood', 10, 3 );
|
||||||
|
|
|
@ -3043,8 +3043,26 @@ function wp_rel_nofollow_callback( $matches ) {
|
||||||
*/
|
*/
|
||||||
function wp_targeted_link_rel( $text ) {
|
function wp_targeted_link_rel( $text ) {
|
||||||
// Don't run (more expensive) regex if no links with targets.
|
// Don't run (more expensive) regex if no links with targets.
|
||||||
if ( stripos( $text, 'target' ) !== false && stripos( $text, '<a ' ) !== false ) {
|
if ( stripos( $text, 'target' ) === false || stripos( $text, '<a ' ) === false || is_serialized( $text ) ) {
|
||||||
$text = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $text );
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
$script_and_style_regex = '/<(script|style).*?<\/\\1>/si';
|
||||||
|
|
||||||
|
preg_match_all( $script_and_style_regex, $text, $matches );
|
||||||
|
$extra_parts = $matches[0];
|
||||||
|
$html_parts = preg_split( $script_and_style_regex, $text );
|
||||||
|
|
||||||
|
foreach ( $html_parts as &$part ) {
|
||||||
|
$part = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $part );
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = '';
|
||||||
|
for ( $i = 0; $i < count( $html_parts ); $i++ ) {
|
||||||
|
$text .= $html_parts[ $i ];
|
||||||
|
if ( isset( $extra_parts[ $i ] ) ) {
|
||||||
|
$text .= $extra_parts[ $i ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
|
@ -3063,7 +3081,16 @@ function wp_targeted_link_rel( $text ) {
|
||||||
*/
|
*/
|
||||||
function wp_targeted_link_rel_callback( $matches ) {
|
function wp_targeted_link_rel_callback( $matches ) {
|
||||||
$link_html = $matches[1];
|
$link_html = $matches[1];
|
||||||
$rel_match = array();
|
$original_link_html = $link_html;
|
||||||
|
|
||||||
|
// Consider the html escaped if there are no unescaped quotes
|
||||||
|
$is_escaped = ! preg_match( '/(^|[^\\\\])[\'"]/', $link_html );
|
||||||
|
if ( $is_escaped ) {
|
||||||
|
// Replace only the quotes so that they are parsable by wp_kses_hair, leave the rest as is
|
||||||
|
$link_html = preg_replace( '/\\\\([\'"])/', '$1', $link_html );
|
||||||
|
}
|
||||||
|
|
||||||
|
$atts = wp_kses_hair( $link_html, wp_allowed_protocols() );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the rel values that are added to links with `target` attribute.
|
* Filters the rel values that are added to links with `target` attribute.
|
||||||
|
@ -3075,35 +3102,21 @@ function wp_targeted_link_rel_callback( $matches ) {
|
||||||
*/
|
*/
|
||||||
$rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html );
|
$rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html );
|
||||||
|
|
||||||
// Avoid additional regex if the filter removes rel values.
|
// Return early if no rel values to be added or if no actual target attribute
|
||||||
if ( ! $rel ) {
|
if ( ! $rel || ! isset( $atts['target'] ) ) {
|
||||||
return "<a $link_html>";
|
return "<a $original_link_html>";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value with delimiters, spaces around are optional.
|
if ( isset( $atts['rel'] ) ) {
|
||||||
$attr_regex = '|rel\s*=\s*?(\\\\{0,1}["\'])(.*?)\\1|i';
|
$all_parts = preg_split( '/\s/', "{$atts['rel']['value']} $rel", -1, PREG_SPLIT_NO_EMPTY );
|
||||||
preg_match( $attr_regex, $link_html, $rel_match );
|
$rel = implode( ' ', array_unique( $all_parts ) );
|
||||||
|
|
||||||
if ( empty( $rel_match[0] ) ) {
|
|
||||||
// No delimiters, try with a single value and spaces, because `rel = va"lue` is totally fine...
|
|
||||||
$attr_regex = '|rel\s*=(\s*)([^\s]*)|i';
|
|
||||||
preg_match( $attr_regex, $link_html, $rel_match );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $rel_match[0] ) ) {
|
$atts['rel']['whole'] = 'rel="' . esc_attr( $rel ) . '"';
|
||||||
$parts = preg_split( '|\s+|', strtolower( $rel_match[2] ) );
|
$link_html = join( ' ', array_column( $atts, 'whole' ) );
|
||||||
$parts = array_map( 'esc_attr', $parts );
|
|
||||||
$needed = explode( ' ', $rel );
|
if ( $is_escaped ) {
|
||||||
$parts = array_unique( array_merge( $parts, $needed ) );
|
$link_html = preg_replace( '/[\'"]/', '\\\\$0', $link_html );
|
||||||
$delimiter = trim( $rel_match[1] ) ? $rel_match[1] : '"';
|
|
||||||
$rel = 'rel=' . $delimiter . trim( implode( ' ', $parts ) ) . $delimiter;
|
|
||||||
$link_html = str_replace( $rel_match[0], $rel, $link_html );
|
|
||||||
} elseif ( preg_match( '|target\s*=\s*?\\\\"|', $link_html ) ) {
|
|
||||||
$link_html .= " rel=\\\"$rel\\\"";
|
|
||||||
} elseif ( preg_match( '#(target|href)\s*=\s*?\'#', $link_html ) ) {
|
|
||||||
$link_html .= " rel='$rel'";
|
|
||||||
} else {
|
|
||||||
$link_html .= " rel=\"$rel\"";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "<a $link_html>";
|
return "<a $link_html>";
|
||||||
|
@ -4807,6 +4820,31 @@ function wp_pre_kses_less_than_callback( $matches ) {
|
||||||
return $matches[0];
|
return $matches[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove non-allowable HTML from parsed block attribute values when filtering
|
||||||
|
* in the post context.
|
||||||
|
*
|
||||||
|
* @since 5.3.1
|
||||||
|
*
|
||||||
|
* @param string $string Content to be run through KSES.
|
||||||
|
* @param array[]|string $allowed_html An array of allowed HTML elements
|
||||||
|
* and attributes, or a context name
|
||||||
|
* such as 'post'.
|
||||||
|
* @param string[] $allowed_protocols Array of allowed URL protocols.
|
||||||
|
* @return string Filtered text to run through KSES.
|
||||||
|
*/
|
||||||
|
function wp_pre_kses_block_attributes( $string, $allowed_html, $allowed_protocols ) {
|
||||||
|
/*
|
||||||
|
* `filter_block_content` is expected to call `wp_kses`. Temporarily remove
|
||||||
|
* the filter to avoid recursion.
|
||||||
|
*/
|
||||||
|
remove_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10 );
|
||||||
|
$string = filter_block_content( $string, $allowed_html, $allowed_protocols );
|
||||||
|
add_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10, 3 );
|
||||||
|
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WordPress implementation of PHP sprintf() with filters.
|
* WordPress implementation of PHP sprintf() with filters.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1658,7 +1658,7 @@ function wp_kses_html_error( $string ) {
|
||||||
*/
|
*/
|
||||||
function wp_kses_bad_protocol_once( $string, $allowed_protocols, $count = 1 ) {
|
function wp_kses_bad_protocol_once( $string, $allowed_protocols, $count = 1 ) {
|
||||||
$string = preg_replace( '/(�*58(?![;0-9])|�*3a(?![;a-f0-9]))/i', '$1;', $string );
|
$string = preg_replace( '/(�*58(?![;0-9])|�*3a(?![;a-f0-9]))/i', '$1;', $string );
|
||||||
$string2 = preg_split( '/:|�*58;|�*3a;/i', $string, 2 );
|
$string2 = preg_split( '/:|�*58;|�*3a;|:/i', $string, 2 );
|
||||||
if ( isset( $string2[1] ) && ! preg_match( '%/\?%', $string2[0] ) ) {
|
if ( isset( $string2[1] ) && ! preg_match( '%/\?%', $string2[0] ) ) {
|
||||||
$string = trim( $string2[1] );
|
$string = trim( $string2[1] );
|
||||||
$protocol = wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols );
|
$protocol = wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols );
|
||||||
|
|
|
@ -499,7 +499,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
||||||
return new WP_Error( 'rest_cannot_edit_others', __( 'Sorry, you are not allowed to create posts as this user.' ), array( 'status' => rest_authorization_required_code() ) );
|
return new WP_Error( 'rest_cannot_edit_others', __( 'Sorry, you are not allowed to create posts as this user.' ), array( 'status' => rest_authorization_required_code() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $request['sticky'] ) && ! current_user_can( $post_type->cap->edit_others_posts ) ) {
|
if ( ! empty( $request['sticky'] ) && ! current_user_can( $post_type->cap->edit_others_posts ) && ! current_user_can( $post_type->cap->publish_posts ) ) {
|
||||||
return new WP_Error( 'rest_cannot_assign_sticky', __( 'Sorry, you are not allowed to make posts sticky.' ), array( 'status' => rest_authorization_required_code() ) );
|
return new WP_Error( 'rest_cannot_assign_sticky', __( 'Sorry, you are not allowed to make posts sticky.' ), array( 'status' => rest_authorization_required_code() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,7 +654,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
||||||
return new WP_Error( 'rest_cannot_edit_others', __( 'Sorry, you are not allowed to update posts as this user.' ), array( 'status' => rest_authorization_required_code() ) );
|
return new WP_Error( 'rest_cannot_edit_others', __( 'Sorry, you are not allowed to update posts as this user.' ), array( 'status' => rest_authorization_required_code() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $request['sticky'] ) && ! current_user_can( $post_type->cap->edit_others_posts ) ) {
|
if ( ! empty( $request['sticky'] ) && ! current_user_can( $post_type->cap->edit_others_posts ) && ! current_user_can( $post_type->cap->publish_posts ) ) {
|
||||||
return new WP_Error( 'rest_cannot_assign_sticky', __( 'Sorry, you are not allowed to make posts sticky.' ), array( 'status' => rest_authorization_required_code() ) );
|
return new WP_Error( 'rest_cannot_assign_sticky', __( 'Sorry, you are not allowed to make posts sticky.' ), array( 'status' => rest_authorization_required_code() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +956,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
||||||
* @return stdClass|WP_Error Post object or WP_Error.
|
* @return stdClass|WP_Error Post object or WP_Error.
|
||||||
*/
|
*/
|
||||||
protected function prepare_item_for_database( $request ) {
|
protected function prepare_item_for_database( $request ) {
|
||||||
$prepared_post = new stdClass;
|
$prepared_post = new stdClass();
|
||||||
|
|
||||||
// Post ID.
|
// Post ID.
|
||||||
if ( isset( $request['id'] ) ) {
|
if ( isset( $request['id'] ) ) {
|
||||||
|
|
Loading…
Reference in New Issue