Skip to content

Commit

Permalink
Embed block: fix embedding stories with plain permalinks (GoogleForCr…
Browse files Browse the repository at this point in the history
  • Loading branch information
swissspidy committed Dec 9, 2020
1 parent d1fceaa commit 9b710c7
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 62 deletions.
5 changes: 3 additions & 2 deletions assets/src/story-embed-block/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ function StoryEmbedEdit({

try {
setIsFetchingData(true);
const urlObj = new URL(url);
// Normalize input URL.
const urlToEmbed = encodeURIComponent(new URL(url).toString());

const data = await apiFetch({
path: `web-stories/v1/embed?url=${urlObj.toString()}`,
path: `web-stories/v1/embed?url=${urlToEmbed}`,
});

setCannotEmbed(!data?.title);
Expand Down
85 changes: 65 additions & 20 deletions includes/REST_API/Embed_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function register_routes() {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_proxy_item( $request ) {
$url = untrailingslashit( $request['url'] );
$url = urldecode( untrailingslashit( $request['url'] ) );

if ( empty( $url ) ) {
return new WP_Error( 'rest_invalid_url', __( 'Invalid URL', 'web-stories' ), [ 'status' => 404 ] );
Expand Down Expand Up @@ -168,15 +168,39 @@ public function get_proxy_item( $request ) {
/**
* Retrieves the story metadata for a given URL on the current site.
*
* @SuppressWarnings(PHPMD.NPathComplexity)
*
* @since 1.0.0
*
* @param string $url The URL that should be inspected for metadata.
*
* @return array|false Story metadata if the URL does belong to the current site. False otherwise.
*/
private function get_data_from_post( $url ) {
$post = $this->url_to_post( $url );

if ( ! $post || Story_Post_Type::POST_TYPE_SLUG !== $post->post_type ) {
return false;
}

return $this->get_data_from_document( $post->post_content );
}

/**
* Examines a URL and try to determine the post it represents.
*
* Checks are supposedly from the hosted site blog.
*
* @SuppressWarnings(PHPMD.NPathComplexity)
*
* @see get_oembed_response_data_for_url
* @see url_to_postid
*
* @since 1.2.0
*
* @param string $url Permalink to check.
* @return WP_Post|null Post object on success, null otherwise.
*/
private function url_to_post( $url ) {
$post = null;
$switched_blog = false;

if ( is_multisite() ) {
Expand All @@ -198,8 +222,12 @@ private function get_data_from_post( $url ) {

// In case of subdirectory configs, set the path.
if ( ! is_subdomain_install() ) {
// Get "sub-site" part of "http://example.org/sub-site/web-stories/my-story/".
// But given just "http://example.org/web-stories/my-story/", don't treat "web-stories" as site path.
// This differs from the logic in get_oembed_response_data_for_url() which does not do this.
// TODO: Investigate possible core bug in get_oembed_response_data_for_url()?
$path = explode( '/', ltrim( $url_parts['path'], '/' ) );
$path = reset( $path );
$path = count( $path ) > 2 ? reset( $path ) : false;
$network = get_network();
if ( $path && $network instanceof \WP_Network ) {
$qv['path'] = $network->path . $path . '/';
Expand All @@ -222,30 +250,47 @@ private function get_data_from_post( $url ) {
$post_id = url_to_postid( $url );
}

if ( ! $post_id ) {
if ( $switched_blog ) {
restore_current_blog();
}

return false;
}

$post = get_post( $post_id );
if ( ! $post instanceof WP_Post ) {
return false;
if ( $post_id ) {
$post = get_post( $post_id );
}

if ( Story_Post_Type::POST_TYPE_SLUG !== $post->post_type ) {
return false;
if ( ! $post_id ) {
// url_to_postid() does not recognize plain permalinks like https://example.com/?web-story=my-story.
// Let's check for that ourselves.

$url_host = str_replace( 'www.', '', wp_parse_url( $url, PHP_URL_HOST ) );
$home_url_host = str_replace( 'www.', '', wp_parse_url( home_url(), PHP_URL_HOST ) );

if ( $url_host === $home_url_host ) {
$values = [];
if (
preg_match(
'#[?&](' . preg_quote( Story_Post_Type::POST_TYPE_SLUG, '#' ) . ')=([^&]+)#',
$url,
$values
)
) {
$slug = $values[2];

if ( function_exists( 'wpcom_vip_get_page_by_path' ) ) {
$post = wpcom_vip_get_page_by_path( $slug, OBJECT, Story_Post_Type::POST_TYPE_SLUG );
} else {
// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions
$post = get_page_by_path( $slug, OBJECT, Story_Post_Type::POST_TYPE_SLUG );
}
}
}
}

$data = $this->get_data_from_document( $post->post_content );

if ( $switched_blog ) {
restore_current_blog();
}

return $data;
if ( ! $post instanceof WP_Post ) {
return null;
}

return $post;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase" />
</rule>

<rule ref="WordPress-VIP-Go" />
<rule ref="WordPress-VIP-Go">
<exclude-pattern>tests/*</exclude-pattern>
</rule>

<rule ref="WordPress.WP.I18n">
<properties>
Expand Down
11 changes: 11 additions & 0 deletions tests/phpstan/stubs/wpdotcom.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@
*/
function wpcom_vip_url_to_postid( $url ) {
}

/**
* @param string $page_path Page path.
* @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
* correspond to a WP_Post object, an associative array, or a numeric array,
* respectively. Default OBJECT.
* @param string|array $post_type Optional. Post type or array of post types. Default 'page'.
* @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
*/
function wpcom_vip_get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
}
3 changes: 3 additions & 0 deletions tests/phpunit/tests/Discovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,16 @@ public static function wpTearDownAfterClass() {

public function setUp() {
parent::setUp();

$this->set_permalink_structure( '/%postname%/' );
$this->go_to( get_permalink( self::$story_id ) );
}

public function tearDown() {
$this->set_permalink_structure( '' );
// Set by go_to();
$_SERVER['REQUEST_URI'] = '';

parent::tearDown();
}

Expand Down
Loading

0 comments on commit 9b710c7

Please sign in to comment.