From 2449603682c395dd8c8f0c9878bdaef6d16eb50a Mon Sep 17 00:00:00 2001
From: Erick Hitter <git-contrib@ethitter.com>
Date: Sun, 17 Jul 2022 15:54:31 -0700
Subject: [PATCH] Add oEmbed support

---
 inc/class-plugin.php | 91 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 90 insertions(+), 1 deletion(-)

diff --git a/inc/class-plugin.php b/inc/class-plugin.php
index 461c552..84c65fc 100644
--- a/inc/class-plugin.php
+++ b/inc/class-plugin.php
@@ -11,6 +11,27 @@ namespace ETH_Embed_Anchor_FM;
  * Class Plugin.
  */
 class Plugin {
+	/**
+	 * Regex pattern to match URL to be oEmbedded.
+	 *
+	 * @var string
+	 */
+	private const OEMBED_FORMAT = '#^https://anchor\.fm/(?!api)([^/]+)/episodes/([^/\s]+)/?#i';
+
+	/**
+	 * Anchor oEmbed endpoint with placeholder.
+	 *
+	 * @var string
+	 */
+	private const OEMBED_ENDPOINT = 'https://anchor.fm/api/v3/episodes/__EPISODE_ID__/oembed';
+
+	/**
+	 * Placeholder in self::OEMBED_ENDPOINT to be replaced with episode ID.
+	 *
+	 * @var string
+	 */
+	private const EPISODE_ID_PLACEHOLDER = '__EPISODE_ID__';
+
 	/**
 	 * Singleton.
 	 *
@@ -43,7 +64,75 @@ class Plugin {
 	 * @return void
 	 */
 	private function setup(): void {
-		// TODO: add oEmbed handler.
+		add_action( 'init', [ $this, 'action_init' ] );
+		add_filter(
+			'oembed_fetch_url',
+			[ $this, 'filter_oembed_fetch_url' ],
+			10,
+			3
+		);
+
 		// TODO: add shortcode.
 	}
+
+	/**
+	 * Register oEmbed handler.
+	 *
+	 * @return void
+	 */
+	public function action_init(): void {
+		wp_oembed_add_provider(
+			self::OEMBED_FORMAT,
+			self::OEMBED_ENDPOINT,
+			true
+		);
+	}
+
+	/**
+	 * Filter oEmbed URL.
+	 *
+	 * Anchor.fm's oEmbed endpoint is specific to an episode ID, which must be
+	 * extracted from the episode URL.
+	 *
+	 * @param string $provider URL of the oEmbed provider.
+	 * @param string $url      URL of the content to be embedded.
+	 * @param array  $args     Optional. Additional arguments for retrieving
+	 *                         embed HTML.
+	 * @return string
+	 */
+	public function filter_oembed_fetch_url(
+		string $provider,
+		string $url,
+		array $args = []
+	): string {
+		if ( 0 !== stripos( $provider, self::OEMBED_ENDPOINT ) ) {
+			return $provider;
+		}
+
+		if ( ! preg_match( self::OEMBED_FORMAT, $url, $matches ) ) {
+			return '';
+		}
+
+		$episode_slug_parts = explode( '-', $matches[2] );
+		$id                 = array_pop( $episode_slug_parts );
+
+		$provider = str_replace(
+			self::EPISODE_ID_PLACEHOLDER,
+			$id,
+			self::OEMBED_ENDPOINT
+		);
+
+		// Anchor.fm's oEmbed endpoint offers limited support for arguments.
+		if ( isset( $args['width'], $args['height'] ) ) {
+			$provider = add_query_arg(
+				[
+					'maxwidth'  => (int) $args['width'],
+					'maxheight' => (int) $args['height'],
+				],
+				$provider
+			);
+		}
+
+		return $provider;
+	}
 }
-- 
GitLab