111 lines
No EOL
3.3 KiB
PHP
111 lines
No EOL
3.3 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: Ansico Embed URL
|
|
* Description: A Gutenberg block to embed a URL with a social-media style preview card. Automatically fetches metadata and saves the image locally.
|
|
* Version: 1.0.0
|
|
* Author: Ansico
|
|
* Text Domain: ansico-embed-url
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
// Register the block and its assets
|
|
add_action( 'init', 'ansico_embed_url_register_block' );
|
|
function ansico_embed_url_register_block() {
|
|
wp_register_script(
|
|
'ansico-embed-url-script',
|
|
plugins_url( 'ansico-embed-url.js', __FILE__ ),
|
|
array( 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-api-fetch' ),
|
|
'1.0.0'
|
|
);
|
|
|
|
wp_register_style(
|
|
'ansico-embed-url-style',
|
|
plugins_url( 'ansico-embed-url.css', __FILE__ ),
|
|
array(),
|
|
'1.0.0'
|
|
);
|
|
|
|
register_block_type( 'ansico/embed-url', array(
|
|
'editor_script' => 'ansico-embed-url-script',
|
|
'editor_style' => 'ansico-embed-url-style',
|
|
'style' => 'ansico-embed-url-style',
|
|
) );
|
|
}
|
|
|
|
// Register REST API Route
|
|
add_action( 'rest_api_init', function () {
|
|
register_rest_route( 'ansico/v1', '/fetch-url', array(
|
|
'methods' => 'POST',
|
|
'callback' => 'ansico_embed_url_fetch_metadata',
|
|
'permission_callback' => function () {
|
|
return current_user_can( 'edit_posts' );
|
|
}
|
|
) );
|
|
} );
|
|
|
|
function ansico_embed_url_fetch_metadata( $request ) {
|
|
$url = esc_url_raw( $request->get_param( 'url' ) );
|
|
|
|
if ( empty( $url ) ) {
|
|
return new WP_Error( 'missing_url', 'No URL provided', array( 'status' => 400 ) );
|
|
}
|
|
|
|
$response = wp_remote_get( $url );
|
|
if ( is_wp_error( $response ) ) {
|
|
return new WP_Error( 'fetch_failed', 'Could not fetch URL', array( 'status' => 500 ) );
|
|
}
|
|
|
|
$html = wp_remote_retrieve_body( $response );
|
|
|
|
libxml_use_internal_errors(true);
|
|
$doc = new DOMDocument();
|
|
$doc->loadHTML( mb_convert_encoding( $html, 'HTML-ENTITIES', 'UTF-8' ) );
|
|
libxml_clear_errors();
|
|
|
|
$title = '';
|
|
$image_url = '';
|
|
$domain = parse_url( $url, PHP_URL_HOST );
|
|
$domain = str_replace( 'www.', '', $domain );
|
|
|
|
$tags = $doc->getElementsByTagName( 'meta' );
|
|
foreach ( $tags as $tag ) {
|
|
if ( $tag->getAttribute( 'property' ) === 'og:title' ) {
|
|
$title = $tag->getAttribute( 'content' );
|
|
}
|
|
if ( $tag->getAttribute( 'property' ) === 'og:image' ) {
|
|
$image_url = $tag->getAttribute( 'content' );
|
|
}
|
|
}
|
|
|
|
if ( empty( $title ) ) {
|
|
$nodes = $doc->getElementsByTagName( 'title' );
|
|
if ( $nodes->length > 0 ) {
|
|
$title = $nodes->item(0)->nodeValue;
|
|
}
|
|
}
|
|
|
|
$local_image_url = '';
|
|
if ( ! empty( $image_url ) ) {
|
|
require_once( ABSPATH . 'wp-admin/includes/media.php' );
|
|
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
|
require_once( ABSPATH . 'wp-admin/includes/image.php' );
|
|
|
|
$sideloaded = media_sideload_image( $image_url, 0, null, 'src' );
|
|
|
|
if ( ! is_wp_error( $sideloaded ) ) {
|
|
$local_image_url = $sideloaded;
|
|
} else {
|
|
$local_image_url = $image_url;
|
|
}
|
|
}
|
|
|
|
return rest_ensure_response( array(
|
|
'title' => $title,
|
|
'image' => $local_image_url,
|
|
'domain' => $domain,
|
|
) );
|
|
}
|
|
?>
|