cloudProvider = $cloudProvider;
}
/**
* Register the observer with WordPress hooks.
*
* @return void
*/
public function register(): void
{
add_filter('attachment_fields_to_edit', [$this, 'run'], 10, 2);
add_action('wp_ajax_advmo_offload_single_attachment', [$this, 'handle_ajax_offload']);
add_action('admin_footer', [$this, 'enqueue_scripts']);
}
/**
* Add the "Offload Now" button to attachment fields.
*
* @param array $form_fields The form fields for the attachment.
* @param \WP_Post $post The attachment post object.
* @return array The modified form fields.
*/
public function run(array $form_fields, \WP_Post $post): array
{
// Add the button if the attachment is not already offloaded
// This includes both new attachments and those with failed offload attempts
if (!$this->is_offloaded($post->ID)) {
$buttonText = $this->has_errors($post->ID) ?
__('Retry Offload', 'advanced-media-offloader') :
__('Offload Now', 'advanced-media-offloader');
$form_fields['advmo_offload_button'] = [
'label' => __('Cloud Offload:', 'advanced-media-offloader'),
'input' => 'html',
'html' => $this->generateOffloadButtonHtml($post->ID, $buttonText),
];
}
return $form_fields;
}
/**
* Generate the HTML for the "Offload Now" button.
*
* @param int $attachment_id The attachment ID.
* @param string|null $button_text The text to display on the button.
* @return string The generated HTML.
*/
private function generateOffloadButtonHtml(int $attachment_id, ?string $button_text = null): string
{
$nonce = wp_create_nonce('advmo_offload_single_' . $attachment_id);
$button_text = $button_text ?: __('Offload Now', 'advanced-media-offloader');
// Always use blue button style
$button_style = 'background: #0073aa; color: white; border-color: #0073aa; min-width: 120px;';
return sprintf(
'
',
esc_attr($attachment_id),
esc_attr($nonce),
esc_attr($button_text),
esc_attr($button_style),
esc_html($button_text),
esc_html__('Uploading to cloud storage, please wait...', 'advanced-media-offloader')
);
}
/**
* Handle the Ajax request for offloading a single attachment.
*
* @return void
*/
public function handle_ajax_offload(): void
{
// Verify the request
if (!$this->verify_ajax_request()) {
wp_send_json_error([
'message' => __('Invalid request.', 'advanced-media-offloader')
]);
}
$attachment_id = intval($_POST['attachment_id']);
// Verify attachment exists and is not already offloaded
if (!get_post($attachment_id) || $this->is_offloaded($attachment_id)) {
wp_send_json_error([
'message' => __('Invalid attachment or already offloaded.', 'advanced-media-offloader')
]);
}
try {
// Use the existing CloudAttachmentUploader service
$uploader = new \Advanced_Media_Offloader\Services\CloudAttachmentUploader($this->cloudProvider);
$result = $uploader->uploadAttachment($attachment_id);
if ($result) {
wp_send_json_success([
'message' => __('Attachment successfully offloaded to cloud storage.', 'advanced-media-offloader'),
'attachment_id' => $attachment_id
]);
} else {
// Check for specific error messages
$errors = get_post_meta($attachment_id, 'advmo_error_log', true);
$error_message = !empty($errors) ?
(is_array($errors) ? implode('; ', $errors) : $errors) :
__('Failed to offload attachment. Please try again.', 'advanced-media-offloader');
wp_send_json_error([
'message' => $error_message
]);
}
} catch (\Exception $e) {
wp_send_json_error([
'message' => sprintf(
__('Error: %s', 'advanced-media-offloader'),
$e->getMessage()
)
]);
}
}
/**
* Verify the Ajax request is valid.
*
* @return bool
*/
private function verify_ajax_request(): bool
{
if (!current_user_can('upload_files')) {
return false;
}
if (!isset($_POST['attachment_id']) || !isset($_POST['nonce'])) {
return false;
}
$attachment_id = intval($_POST['attachment_id']);
$nonce = sanitize_text_field(wp_unslash($_POST['nonce']));
return wp_verify_nonce($nonce, 'advmo_offload_single_' . $attachment_id);
}
/**
* Check if attachment has errors.
*
* @param int $attachment_id The attachment ID.
* @return bool
*/
private function has_errors(int $attachment_id): bool
{
$errors = get_post_meta($attachment_id, 'advmo_error_log', true);
return !empty($errors);
}
/**
* Enqueue scripts for the offload button functionality.
*
* @return void
*/
public function enqueue_scripts(): void
{
if (!$this->is_media_page()) {
return;
}
?>
id === 'attachment' ||
$current_screen->base === 'upload' ||
$current_screen->base === 'media'
);
}
}