*/ const EMBED_DEFAULT_PARAMS = array( 'hide_emojies' => 'false', 'hide_interactions' => 'false', 'hide_comments' => 'false', 'hide_owner' => 'false', 'hide_analytics' => 'false', 'hide_watch_on_dadan' => 'false', 'hide_chapters' => 'false', ); /** * Parse a Dadan URL. * * @param string $url Raw URL or bare share code. * @return array{id: string, kind: string}|null kind: share|video|embed */ public static function parse( $url ) { $url = trim( (string) $url ); if ( '' === $url ) { return null; } if ( preg_match( self::VIDEO_SHARE_PATTERN, $url, $m ) && ! empty( $m[1] ) ) { return array( 'id' => $m[1], 'kind' => 'share', ); } if ( preg_match( self::VIDEO_EMBED_HTML_PATTERN, $url ) ) { $parts = wp_parse_url( $url ); if ( ! empty( $parts['query'] ) ) { parse_str( $parts['query'], $query ); // DADAN-06: ?link[]= makes link an array; preg_match TypeErrors on PHP 8+. $link = isset( $query['link'] ) && is_string( $query['link'] ) ? $query['link'] : ''; if ( '' !== $link && preg_match( '/^[A-Za-z0-9_-]{1,64}$/', $link ) ) { return array( 'id' => $link, 'kind' => 'embed', ); } } return null; } if ( preg_match( self::VIDEO_ID_PATTERN, $url, $m ) && ! empty( $m[1] ) ) { return array( 'id' => $m[1], 'kind' => 'video', ); } if ( preg_match( self::LEGACY_SHARE_PATTERN, $url, $m ) && ! empty( $m[1] ) ) { return array( 'id' => $m[1], 'kind' => 'share', ); } if ( preg_match( self::LEGACY_EMBED_PATTERN, $url, $m ) && ! empty( $m[1] ) ) { return array( 'id' => $m[1], 'kind' => 'embed', ); } // DADAN-40: cap bare share-code length (same bound as embed ?link=). if ( preg_match( '/^[A-Za-z0-9_-]{1,128}$/', $url ) ) { return array( 'id' => $url, 'kind' => 'share', ); } return null; } /** * Whether the URL is a recognized Dadan video URL (full URL, not bare id). * * @param string $url URL to test. * @return bool */ public static function is_dadan_url( $url ) { $url = trim( (string) $url ); if ( '' === $url ) { return false; } if ( preg_match( self::VIDEO_SHARE_PATTERN, $url ) ) { return true; } if ( preg_match( self::VIDEO_EMBED_HTML_PATTERN, $url ) ) { $parsed = self::parse( $url ); return null !== $parsed; } if ( preg_match( self::VIDEO_ID_PATTERN, $url ) ) { return true; } if ( preg_match( self::LEGACY_SHARE_PATTERN, $url ) ) { return true; } if ( preg_match( self::LEGACY_EMBED_PATTERN, $url ) ) { return true; } return false; } /** * Whether this URL can be turned into an embed iframe (needs a share `link` code). * * @param string $url Dadan URL. * @return bool */ public static function can_embed( $url ) { $parsed = self::parse( $url ); if ( ! $parsed ) { return false; } // Direct /video/{hex} pages need a share link for embed.html?link=. return 'video' !== $parsed['kind']; } /** * Build canonical player URL: * https://app.dadan.io/video/embed.html?...&link={shareCode} * * @param string $shared_url Share / embed URL, or bare share code. * @return string|null */ public static function to_embed_url( $shared_url ) { $parsed = self::parse( $shared_url ); if ( ! $parsed || 'video' === $parsed['kind'] ) { return null; } $base = rtrim( DADAN_API_BASE, '/' ) . '/video/embed.html'; $params = self::EMBED_DEFAULT_PARAMS; $params['link'] = $parsed['id']; return $base . '?' . http_build_query( $params, '', '&', PHP_QUERY_RFC3986 ); } /** * Sanitize width attribute (pixels). * * @param mixed $width Width value. * @param int $default Default if invalid. * @return int */ public static function sanitize_dimension( $width, $default = 640 ) { $width = absint( $width ); if ( $width < 100 ) { return (int) $default; } if ( $width > 2560 ) { return 2560; } return $width; } }