Files
lh-add-media-from-url.php— main plugin file. SingletonLH_add_media_from_url_plugin, hooked viaplugins_loaded. Registers the Media -> Add from URL admin page and handles the upload form submission onadmin_init. Thin controller only — no HTML lives in this class.includes/lh-add-media-from-url-copy-from-url.php—LH_add_media_from_url_copy_from_url, a composed helper class (not a PHP subclass of the main plugin) that does the actual remote fetch and sideload into the media library.includes/lh-add-media-from-url-abilities.php—LH_add_media_from_url_abilities, registers the plugin’s MCP ability. Loaded fromplugins_init()only on the main site and only if the Abilities API is present.partials/admin-page.php— the admin page’s own markup: header, any upload error, the upload form include, and the bookmarklet block.partials/upload.php— the upload form markup itself, included fromadmin-page.php.
Key methods
LH_add_media_from_url_copy_from_url::save_external_file( $url, $post_id, $desc, $check )— downloads$urlto a temp file viawp_safe_remote_get(), validates it, guesses its extension withwp_check_filetype_and_ext(), and sideloads it viamedia_handle_sideload(). Stores the original URL as post meta_lh_copy_from_url-original_file.guess_file_extension()inspects the already-downloaded local temp file rather than re-fetching the remote URL, so extension/MIME detection stays inside WP core’s own SSRF-protected fetch path.
Hooks
- Filter
lh_add_media_from_url_remote_get_args— filters the args array passed towp_safe_remote_get()when fetching the remote file. - Filter
lh_add_media_from_url_init_plugin— returnfalseto prevent the plugin’sadmin_menu/admin_inithooks and the MCP ability (see Abilities) from registering.
Capability
Gated to upload_files rather than the LH-standard install_plugins default — deliberate, since this is a media-upload tool for any user who can already upload files, not developer/admin tooling. The MCP ability uses the same capability as the manual form, not edit_posts, so a Contributor who cannot upload in wp-admin cannot upload through MCP either.
Database / cron
No custom database tables. No cron jobs. The only persistent data is the _lh_copy_from_url-original_file post meta on each created attachment.
Notes
- The bookmarklet’s
$_GETread inplugin_options()is a read-only display convenience (pre-filling the URL field), not a state-changing action — it can’t carry a nonce, since a bookmarklet is a static link with no server round-trip to mint one. The actual state-changing step,handle_upload_v2(), does verify a nonce before anything is fetched or written.