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.
MCP ability
lh-add-media-from-url/add-media-from-url— wrapssave_external_file()so an MCP agent can pull a remote file into the media library the same way the manual wp-admin form does. Acceptsurl(required),post_id,desc. Returns the new attachmentidandurl.- Gated to
upload_files, matching the manual form’s own capability check inhandle_upload_v2()— deliberately not theedit_postspattern used by content-operation abilities like lh-portfolio’s, since a Contributor withedit_postsbut notupload_filesshould not gain upload access through this ability that the wp-admin screen would refuse them.
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 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.
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.