PluginProbe ʕ •ᴥ•ʔ
Export/Import Media – CSV Media Library Import & Export / 1.0.3
Export/Import Media – CSV Media Library Import & Export v1.0.3
1.7.28 1.7.27 1.7.20 1.7.26 1.7.10 1.7.9 1.7.1 1.7 trunk 1.0 1.0.3 1.2.1 1.2.2 1.2.3 1.6.15 1.6.4
calliope-media-import-export / export-import-media.php
calliope-media-import-export Last commit date
assets 5 months ago languages 5 months ago export-import-media.php 5 months ago importer.js 5 months ago readme.txt 5 months ago style.css 5 months ago style.css.mine 5 months ago style.css.r0 5 months ago style.css.r3375314 5 months ago
export-import-media.php
443 lines
1 <?php
2 /* --- ARCHIVO export-import-media.php COMPLETO Y CORREGIDO --- */
3 /*
4 Plugin Name: Export/Import Media
5 Description: Exports and imports images with metadata using CSV. Includes real-time batch processing and prevents duplicates.
6 Version: 1.2.3
7 Author: Maira Forest
8 Author URI: https://calliope.com.ar/
9 License: GPLv2 or later
10 License URI: https://www.gnu.org/licenses/gpl-2.0.html
11 Text Domain: export-import-media
12 Domain Path: /languages
13 */
14
15 if (!defined('ABSPATH')) exit;
16
17 // Cargar el dominio de texto para traducciones
18 add_action('plugins_loaded', 'eim_load_textdomain');
19 function eim_load_textdomain() {
20 load_plugin_textdomain('export-import-media', false, dirname(plugin_basename(__FILE__)) . '/languages');
21 }
22
23 // Utility functions
24 if (!function_exists('eim_attachment_exists')) {
25 function eim_attachment_exists($relative_path, $local_path) {
26 global $wpdb;
27 if (file_exists($local_path)) {
28 $hash = md5_file($local_path);
29 if ($hash) {
30 $attachment_id_by_hash = $wpdb->get_var($wpdb->prepare("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_eim_file_hash', $hash));
31 if ($attachment_id_by_hash) return (int)$attachment_id_by_hash;
32 }
33 }
34 $db_path = ltrim($relative_path, '/');
35 $attachment_id_by_path = $wpdb->get_var($wpdb->prepare("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_wp_attached_file', $db_path));
36 return $attachment_id_by_path ? (int)$attachment_id_by_path : false;
37 }
38 }
39
40 if (!function_exists('eim_set_attachment_hash')) {
41 function eim_set_attachment_hash($attach_id, $file_path) {
42 if (file_exists($file_path) && $attach_id) {
43 $hash = md5_file($file_path);
44 if ($hash) update_post_meta($attach_id, '_eim_file_hash', $hash);
45 }
46 }
47 }
48
49 // Admin menu and script enqueueing
50 add_action('admin_menu', function () {
51 add_media_page(esc_html__('Export/Import Media', 'export-import-media'), esc_html__('Export/Import Media', 'export-import-media'), 'manage_options', 'export-import-media', 'eim_render_admin_page');
52 });
53
54 add_action('admin_enqueue_scripts', function($hook) {
55 if ($hook !== 'media_page_export-import-media') return;
56
57 $plugin_version = '1.2.3';
58
59 wp_enqueue_script('eim-importer-js', plugin_dir_url(__FILE__) . 'importer.js', ['jquery'], $plugin_version, true);
60 wp_localize_script('eim-importer-js', 'eim_ajax', [
61 'ajax_url' => admin_url('admin-ajax.php'),
62 'nonce' => wp_create_nonce('eim_import_nonce'),
63 'i18n' => [
64 'select_csv' => esc_html__('Please select a CSV file.', 'export-import-media'),
65 'validating' => esc_html__('Validating file...', 'export-import-media'),
66 'validation_failed' => esc_html__('Validation Failed:', 'export-import-media'),
67 'validation_success' => esc_html__('Validation successful.', 'export-import-media'),
68 'ready_to_import' => esc_html__('Ready to import.', 'export-import-media'),
69 'uploading_preparing' => esc_html__('Uploading and preparing file...', 'export-import-media'),
70 'file_ready' => esc_html__('File ready. Total images:', 'export-import-media'),
71 'empty_csv' => esc_html__('The CSV file is empty.', 'export-import-media'),
72 'error_prefix' => esc_html__('Error:', 'export-import-media'),
73 'server_error' => esc_html__('Server communication error.', 'export-import-media'),
74 'stopping_process' => esc_html__('Stopping the process...', 'export-import-media'),
75 'invalid_response' => esc_html__('Invalid response from server', 'export-import-media'),
76 'request_failed' => esc_html__('Batch request failed', 'export-import-media'),
77 'process_complete' => esc_html__('Process completed!', 'export-import-media'),
78 'process_stopped' => esc_html__('Process stopped by user.', 'export-import-media'),
79 'processing_batch' => esc_html__('Processing batch...', 'export-import-media'),
80 'batch_complete' => esc_html__('Batch completed.', 'export-import-media'),
81 'click_continue' => esc_html__('Click "Process Next Batch" to continue.', 'export-import-media'),
82 ]
83 ]);
84
85 wp_add_inline_script('eim-importer-js', '
86 jQuery(document).on("click", ".eim-review-notice-top .notice-dismiss", function() {
87 jQuery.ajax({
88 url: eim_ajax.ajax_url,
89 type: "POST",
90 data: {
91 action: "eim_dismiss_review_notice",
92 nonce: eim_ajax.nonce
93 }
94 });
95 });
96 ');
97
98 wp_enqueue_style('eim-custom-styles', plugin_dir_url(__FILE__) . 'style.css', [], $plugin_version);
99 });
100
101 // Admin page render
102 function eim_render_admin_page() {
103 if (!current_user_can('manage_options')) {
104 wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'export-import-media'));
105 }
106 ?>
107 <div class="wrap">
108 <div class="eim-main-banner">
109 <div class="eim-banner-content">
110 <div class="eim-banner-logo"><svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-down-circle"><circle cx="12" cy="12" r="10"></circle><polyline points="8 12 12 16 16 12"></polyline><line x1="12" y1="8" x2="12" y2="16"></line></svg></div>
111 <div class="eim-banner-text">
112 <h3><?php esc_html_e('Media Transfer Plugin', 'export-import-media'); ?></h3>
113 <p><?php esc_html_e('Your complete solution to import and export the media library.', 'export-import-media'); ?></p>
114 </div>
115 </div>
116 <div class="eim-banner-actions">
117 <a href="https://calliope.com.ar/documentacion-plugin/" target="_blank" class="eim-banner-link"><?php esc_html_e('Documentation', 'export-import-media'); ?></a>
118 <a href="https://wordpress.org/support/plugin/calliope-media-import-export/" target="_blank" class="eim-banner-link"><?php esc_html_e('Support', 'export-import-media'); ?></a>
119 <a href="https://ko-fi.com/O4O21MF4QW" target="_blank" class="button button-primary eim-kofi-button">
120 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0H24V24H0z"/><path d="M12.001 4.529c2.349-2.349 5.85-2.349 8.2 0 2.348 2.348 2.348 5.85 0 8.2L12 21l-8.2-8.282c-2.348-2.348-2.348-5.85 0-8.2 2.35-2.349 5.85-2.349 8.2 0z"/></svg>
121 <?php esc_html_e('Support me on Ko-fi', 'export-import-media'); ?>
122 </a>
123 </div>
124 </div>
125
126 <?php
127 if (!get_user_meta(get_current_user_id(), 'eim_review_notice_dismissed', true)) {
128 $review_link = 'https://wordpress.org/support/plugin/calliope-media-import-export/reviews/#new-post';
129 ?>
130 <div class="notice notice-info is-dismissible eim-review-notice-top" style="margin-bottom: 20px;">
131 <p>
132 <?php
133 printf(
134 wp_kses(
135 __('You are using Media Transfer Plugin! If you find it useful, please consider <a href="%s" target="_blank">leaving a positive review</a>. It really helps!', 'export-import-media'),
136 [ 'a' => [ 'href' => [], 'target' => [] ] ]
137 ),
138 esc_url($review_link)
139 );
140 ?>
141 </p>
142 </div>
143 <?php
144 }
145 ?>
146
147 <div id="eim-export-section" class="eim-card">
148 <h2><?php esc_html_e('1. Export Media Library', 'export-import-media'); ?></h2>
149 <p><?php esc_html_e('Generate a CSV file with the information of all images in your media library.', 'export-import-media'); ?></p>
150 <form method="post" action="">
151 <?php wp_nonce_field('eim_export_action', 'eim_export_nonce'); ?>
152 <?php submit_button(esc_html__('Export to CSV', 'export-import-media'), 'secondary', 'eim_export_csv', true, ['id' => 'eim_export_csv']); ?>
153 </form>
154 </div>
155
156 <div id="eim-import-section" class="eim-card">
157 <h2><?php esc_html_e('2. Import from CSV', 'export-import-media'); ?></h2>
158 <p><?php esc_html_e('Upload a CSV file. The process will run in batches, showing real-time progress.', 'export-import-media'); ?></p>
159 <form id="eim-import-form" method="post" enctype="multipart/form-data">
160 <p><label for="eim_csv"><strong><?php esc_html_e('Select the CSV file:', 'export-import-media'); ?></strong></label><br><input type="file" name="eim_csv" id="eim_csv" accept=".csv" required /></p>
161 <p><label for="batch_size"><strong><?php esc_html_e('Images per batch:', 'export-import-media'); ?></strong></label><br>
162 <select name="batch_size" id="batch_size"><option value="10">10</option><option value="25">25</option><option value="50" selected>50</option><option value="100">100</option><option value="250">250</option><option value="500">500</option></select>
163 </p>
164 <p>
165 <label for="eim_local_import">
166 <input type="checkbox" name="eim_local_import" id="eim_local_import" value="1" />
167 <span style="font-weight: bold;"><?php esc_html_e('Local Import Mode', 'export-import-media'); ?></span><br>
168 <small style="margin-left: 22px; display: inline-block;"><?php esc_html_e('Instead of downloading, find images in the local /uploads folder based on the "Relative Path". Files must already exist on this server.', 'export-import-media'); ?></small>
169 </label>
170 </p>
171 <button type="submit" class="button button-primary" id="eim-start-button"><?php esc_html_e('Start Import', 'export-import-media'); ?></button>
172 <button type="button" class="button button-primary" id="eim-continue-button" style="display:none;"><?php esc_html_e('Process Next Batch', 'export-import-media'); ?></button>
173 <button type="button" class="button" id="eim-stop-button" style="display:none;"><?php esc_html_e('Stop Process', 'export-import-media'); ?></button>
174 </form>
175 </div>
176
177 <div id="eimp-progress-container" class="eim-card" style="display:none; margin-top: 20px;">
178 <h3><?php esc_html_e('Import Progress:', 'export-import-media'); ?></h3>
179 <div style="background: #eee; border: 1px solid #ccc; padding: 5px; border-radius: 5px;">
180 <div id="eimp-progress-bar" style="width: 0%; height: 24px; background-color: #0073aa; text-align: center; line-height: 24px; color: white; font-weight: bold; transition: width 0.1s ease; border-radius: 3px;">0%</div>
181 </div>
182 <div class="eim-warning-message"><?php esc_html_e('Important! Do not reload or close this page until the process is complete.', 'export-import-media'); ?></div>
183 <div id="eimp-log" style="background: #fafafa; border: 1px solid #ccc; border-top: none; padding: 10px; max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 13px; margin-top: 5px;"></div>
184 </div>
185
186 <div class="eim-footer-review">
187 <?php
188 $review_link = 'https://wordpress.org/support/plugin/calliope-media-import-export/reviews/#new-post';
189 $stars_svg = '<svg width="18" height="18" viewBox="0 0 24 24"><path fill="#ffb900" d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>';
190 $allowed_html = [
191 'a' => [ 'href' => [], 'target' => [], 'aria-label' => [] ],
192 'svg' => [ 'width' => [], 'height' => [], 'viewBox' => [] ],
193 'path' => [ 'fill' => [], 'd' => [] ],
194 ];
195 printf(
196 wp_kses(
197 __('If you like our plugin, a %1$s%3$s%2$s rating will help us a lot, thanks in advance!', 'export-import-media'),
198 $allowed_html
199 ),
200 '<a href="' . esc_url($review_link) . '" target="_blank" aria-label="' . esc_attr__('Rate 5 stars', 'export-import-media') . '">',
201 '</a>',
202 str_repeat($stars_svg, 5)
203 );
204 ?>
205 </div>
206 </div>
207 <?php
208 }
209
210 // Export logic
211 add_action('admin_init', function () {
212 if ( ! isset( $_POST['eim_export_csv'] ) ) { return; }
213 if ( ! isset( $_POST['eim_export_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['eim_export_nonce'] ) ), 'eim_export_action' ) ) { wp_die( esc_html__( 'Security check failed.', 'export-import-media' ) ); }
214 if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions.', 'export-import-media' ) ); }
215 $args = ['post_type' => 'attachment', 'post_mime_type' => 'image', 'post_status' => 'inherit', 'posts_per_page' => -1];
216 $images = get_posts($args);
217 header('Content-Type: text/csv; charset=UTF-8');
218 header('Content-Disposition: attachment; filename="media-export.csv"');
219 $output = fopen('php://output', 'w');
220 if ( ! $output ) { return; }
221 fputcsv($output, ['ID', 'Absolute URL', 'Relative Path', 'File', 'Alt Text', 'Caption', 'Description', 'Title']);
222 foreach ($images as $image) {
223 $path = get_post_meta($image->ID, '_wp_attached_file', true);
224 fputcsv($output, [$image->ID, wp_get_attachment_url($image->ID), '/' . $path, basename($path), get_post_meta($image->ID, '_wp_attachment_image_alt', true), $image->post_excerpt, $image->post_content, $image->post_title]);
225 }
226 fclose($output);
227 exit;
228 });
229
230 // AJAX handlers for import
231 add_action('wp_ajax_eim_validate_csv', function() {
232 check_ajax_referer('eim_import_nonce', 'nonce');
233 if (empty($_FILES['eim_csv'])) {
234 wp_send_json_error(['message' => esc_html__('No file received.', 'export-import-media')]);
235 }
236
237 require_once ABSPATH . 'wp-admin/includes/file.php';
238 global $wp_filesystem;
239 WP_Filesystem();
240
241 $upload_dir = wp_upload_dir();
242 $temp_dir = trailingslashit($upload_dir['basedir']) . 'eim-temp/';
243 if (!$wp_filesystem->is_dir($temp_dir)) {
244 $wp_filesystem->mkdir($temp_dir);
245 }
246
247 $tmp_name = isset($_FILES['eim_csv']['tmp_name']) ? sanitize_text_field(wp_unslash($_FILES['eim_csv']['tmp_name'])) : '';
248 if (!file_exists($tmp_name)) {
249 wp_send_json_error(['message' => esc_html__('Error with temporary upload file.', 'export-import-media')]);
250 }
251
252 $content = $wp_filesystem->get_contents($tmp_name);
253
254 if (empty(trim($content))) {
255 wp_send_json_error(['message' => esc_html__('The selected CSV file is empty.', 'export-import-media')]);
256 }
257
258 $required_headers = ['ID', 'Absolute URL', 'Relative Path', 'File', 'Alt Text', 'Caption', 'Description', 'Title'];
259 $file_handle_check = fopen($tmp_name, 'r');
260 $read_headers = fgetcsv($file_handle_check);
261 fclose($file_handle_check);
262
263 if (!$read_headers) {
264 wp_send_json_error(['message' => esc_html__('Cannot read headers from CSV file.', 'export-import-media')]);
265 }
266
267 $missing_headers = array_diff($required_headers, $read_headers);
268 if (!empty($missing_headers)) {
269 wp_send_json_error([
270 'message' => sprintf(
271 esc_html__('Invalid CSV header. Missing columns: %s', 'export-import-media'),
272 implode(', ', $missing_headers)
273 )
274 ]);
275 }
276
277 $temp_filename = 'import-' . uniqid() . '.csv';
278 $temp_path = $temp_dir . $temp_filename;
279 $wp_filesystem->put_contents($temp_path, $content);
280
281 $lines = explode("\n", trim($content));
282 $linecount = count($lines) > 1 ? count($lines) - 1 : 0;
283
284 if ($linecount === 0) {
285 wp_send_json_error(['message' => esc_html__('The CSV file contains headers but no data rows.', 'export-import-media')]);
286 }
287
288 wp_send_json_success(['file' => $temp_filename, 'total_rows' => $linecount]);
289 });
290
291 add_action('wp_ajax_eim_process_batch', function() {
292 check_ajax_referer('eim_import_nonce', 'nonce');
293 set_time_limit(0);
294 require_once ABSPATH . 'wp-admin/includes/file.php';
295 require_once(ABSPATH . 'wp-admin/includes/image.php');
296 global $wp_filesystem; WP_Filesystem();
297 $file_name_sanitized = isset($_POST['file']) ? sanitize_file_name(wp_unslash($_POST['file'])) : '';
298 $start_row = isset($_POST['start_row']) ? intval($_POST['start_row']) : 0;
299 $batch_size = isset($_POST['batch_size']) ? intval($_POST['batch_size']) : 50;
300 $local_import = isset($_POST['local_import']) && $_POST['local_import'] === 'true';
301 $upload_dir = wp_upload_dir();
302 $csv_path = trailingslashit($upload_dir['basedir']) . 'eim-temp/' . $file_name_sanitized;
303 if (!$wp_filesystem->exists($csv_path)) {
304 wp_send_json_error(['results' => [['status' => 'ERROR', 'file' => esc_html__("File not found", 'export-import-media'), 'message' => esc_html__('The temporary file has disappeared.', 'export-import-media')]]]);
305 }
306 $results = [];
307 $file_handle = fopen($csv_path, 'r');
308 if (!$file_handle) {
309 wp_send_json_error(['results' => [['status' => 'ERROR', 'file' => 'System', 'message' => 'Could not open CSV file.']]]);
310 }
311 fgetcsv($file_handle);
312 for ($i = 0; $i < $start_row; $i++) {
313 if (feof($file_handle)) break;
314 fgetcsv($file_handle);
315 }
316 for ($i = 0; $i < $batch_size; $i++) {
317 if (feof($file_handle)) {
318 $results[] = ['status' => 'FINISHED'];
319 break;
320 }
321 $row = fgetcsv($file_handle);
322 if (empty($row) || !is_array($row)) continue;
323 $row = array_pad($row, 8, '');
324 list($id, $url, $rel_path, $file_name, $alt, $caption, $desc, $title) = $row;
325 if (empty($rel_path)) {
326 $results[] = ['status' => 'SKIPPED', 'file' => sprintf(esc_html__("Row %d", 'export-import-media'), $start_row + $i + 1), 'message' => esc_html__('Incomplete data: Relative Path is required.', 'export-import-media')];
327 continue;
328 }
329 $dest_path = $upload_dir['basedir'] . $rel_path;
330 if ($local_import) {
331 if (!$wp_filesystem->exists($dest_path)) {
332 $results[] = ['status' => 'ERROR', 'file' => $file_name, 'message' => esc_html__('Local file not found', 'export-import-media')];
333 continue;
334 }
335 } else {
336 if (empty($url)) {
337 $results[] = ['status' => 'SKIPPED', 'file' => $file_name, 'message' => esc_html__('Incomplete data: Absolute URL is required for remote import.', 'export-import-media')];
338 continue;
339 }
340 if (!$wp_filesystem->is_dir(dirname($dest_path))) {
341 wp_mkdir_p(dirname($dest_path));
342 }
343 if (!$wp_filesystem->exists($dest_path)) {
344 $response = wp_remote_get($url, ['timeout' => 120]);
345 if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
346 $error_message = '';
347 if (is_wp_error($response)) {
348 $error_message = $response->get_error_message();
349 } else {
350 $response_code = wp_remote_retrieve_response_code($response);
351 $response_message = wp_remote_retrieve_response_message($response);
352 $error_message = sprintf(
353 esc_html__('HTTP Error %d: %s', 'export-import-media'),
354 $response_code,
355 $response_message
356 );
357 }
358 $results[] = ['status' => 'ERROR', 'file' => $file_name, 'message' => $error_message];
359 continue;
360 }
361 $wp_filesystem->put_contents($dest_path, wp_remote_retrieve_body($response));
362 }
363 }
364 $existing_id = eim_attachment_exists($rel_path, $dest_path);
365 if ($existing_id) {
366 $results[] = ['status' => 'SKIPPED', 'file' => $file_name, 'message' => sprintf(esc_html__('Duplicate (ID %d)', 'export-import-media'), $existing_id)];
367 continue;
368 }
369 $filetype = wp_check_filetype(basename($dest_path), null);
370 $attachment = ['post_mime_type' => $filetype['type'], 'post_title' => sanitize_text_field($title), 'post_content' => wp_kses_post($desc), 'post_excerpt' => sanitize_text_field($caption), 'post_status' => 'inherit'];
371 $attach_id = wp_insert_attachment($attachment, $dest_path, 0, true);
372 if (is_wp_error($attach_id)) {
373 $results[] = ['status' => 'ERROR', 'file' => $file_name, 'message' => $attach_id->get_error_message()];
374 continue;
375 }
376 wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $dest_path));
377 update_post_meta($attach_id, '_wp_attachment_image_alt', sanitize_text_field($alt));
378 eim_set_attachment_hash($attach_id, $dest_path);
379 $results[] = ['status' => 'IMPORTED', 'file' => $file_name, 'message' => sprintf(esc_html__('OK (ID %d)', 'export-import-media'), $attach_id)];
380 }
381 fclose($file_handle);
382 if (end($results)['status'] === 'FINISHED') {
383 $wp_filesystem->delete($csv_path);
384 }
385 wp_send_json_success(['results' => $results]);
386 });
387
388 add_action('wp_ajax_eim_dismiss_review_notice', 'eim_dismiss_review_notice_handler');
389 function eim_dismiss_review_notice_handler() {
390 check_ajax_referer('eim_import_nonce', 'nonce');
391 update_user_meta(get_current_user_id(), 'eim_review_notice_dismissed', true);
392 wp_die();
393 }
394
395 register_activation_hook(__FILE__, 'eim_activate_plugin');
396 function eim_activate_plugin() {
397 if (!wp_next_scheduled('eim_daily_cleanup_event')) {
398 wp_schedule_event(time(), 'daily', 'eim_daily_cleanup_event');
399 }
400 }
401
402 register_deactivation_hook(__FILE__, 'eim_deactivate_plugin');
403 function eim_deactivate_plugin() {
404 wp_clear_scheduled_hook('eim_daily_cleanup_event');
405 require_once ABSPATH . 'wp-admin/includes/file.php';
406 global $wp_filesystem;
407 WP_Filesystem();
408 $upload_dir = wp_upload_dir();
409 $temp_dir = trailingslashit($upload_dir['basedir']) . 'eim-temp/';
410 if ($wp_filesystem->is_dir($temp_dir)) {
411 $wp_filesystem->delete($temp_dir, true);
412 }
413 }
414
415 add_action('eim_daily_cleanup_event', 'eim_cleanup_temp_files');
416 function eim_cleanup_temp_files() {
417 require_once ABSPATH . 'wp-admin/includes/file.php';
418 global $wp_filesystem;
419 WP_Filesystem();
420 $upload_dir = wp_upload_dir();
421 $temp_dir = trailingslashit($upload_dir['basedir']) . 'eim-temp/';
422 if (!$wp_filesystem->is_dir($temp_dir)) {
423 return;
424 }
425 $files = $wp_filesystem->dirlist($temp_dir);
426 $expiration_time = 86400;
427 if ($files) {
428 foreach ($files as $file) {
429 $file_path = $temp_dir . $file['name'];
430 if ($wp_filesystem->is_file($file_path) && (time() - $file['lastmod']) > $expiration_time) {
431 $wp_filesystem->delete($file_path);
432 }
433 }
434 }
435 }
436
437 add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'eim_add_settings_link');
438 function eim_add_settings_link($links) {
439 $settings_link = '<a href="upload.php?page=export-import-media">' . esc_html__('Settings', 'export-import-media') . '</a>';
440 array_unshift($links, $settings_link);
441 return $links;
442 }
443 ?>