|
|
@@ -36,13 +36,15 @@ class Studiou_WC_Product_Cat_Manage_Manipulator {
|
|
|
add_action('wp_ajax_studiou_wcpcm_batch_description', array($this, 'handle_batch_description_ajax'));
|
|
|
add_action('wp_ajax_studiou_wcpcm_delete_products', array($this, 'handle_delete_products_ajax'));
|
|
|
add_action('wp_ajax_studiou_wcpcm_delete_products_batch', array($this, 'handle_delete_products_batch_ajax'));
|
|
|
+ add_action('wp_ajax_studiou_wcpcm_clear_media', array($this, 'handle_clear_media_ajax'));
|
|
|
+ add_action('wp_ajax_studiou_wcpcm_clear_media_batch', array($this, 'handle_clear_media_batch_ajax'));
|
|
|
|
|
|
// Add a test AJAX handler to verify AJAX is working
|
|
|
add_action('wp_ajax_studiou_wcpcm_test', array($this, 'handle_test_ajax'));
|
|
|
|
|
|
// Debug: Log that the handler is being registered
|
|
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
- error_log('STUDIOU WC: AJAX handlers registered - move_products, batch_description, and delete_products');
|
|
|
+ error_log('STUDIOU WC: AJAX handlers registered - move_products, batch_description, delete_products, and clear_media');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -854,4 +856,341 @@ class Studiou_WC_Product_Cat_Manage_Manipulator {
|
|
|
'failed_products' => $failed_products
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get all media categories with file counts for select lists
|
|
|
+ *
|
|
|
+ * @return array Array of media categories with ID, name, and file count
|
|
|
+ */
|
|
|
+ public function get_media_categories_with_counts() {
|
|
|
+ $taxonomy = $this->get_media_category_taxonomy();
|
|
|
+
|
|
|
+ if (!$taxonomy) {
|
|
|
+ return array();
|
|
|
+ }
|
|
|
+
|
|
|
+ $args = array(
|
|
|
+ 'taxonomy' => $taxonomy,
|
|
|
+ 'orderby' => 'name',
|
|
|
+ 'hide_empty' => false,
|
|
|
+ );
|
|
|
+
|
|
|
+ $categories = get_terms($args);
|
|
|
+ $categories_with_counts = array();
|
|
|
+
|
|
|
+ if (!is_wp_error($categories)) {
|
|
|
+ foreach ($categories as $category) {
|
|
|
+ $file_count = $this->get_media_category_file_count($category->term_id, $taxonomy);
|
|
|
+
|
|
|
+ $categories_with_counts[] = array(
|
|
|
+ 'id' => $category->term_id,
|
|
|
+ 'name' => $category->name,
|
|
|
+ 'count' => $file_count,
|
|
|
+ 'display_name' => sprintf('%s (%d %s)', $category->name, $file_count, __('files', 'studiou-wc-product-cat-manage'))
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $categories_with_counts;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get the media category taxonomy name
|
|
|
+ *
|
|
|
+ * Checks for common media category taxonomies used by popular plugins
|
|
|
+ *
|
|
|
+ * @return string|false Taxonomy name or false if none found
|
|
|
+ */
|
|
|
+ private function get_media_category_taxonomy() {
|
|
|
+ $possible_taxonomies = array(
|
|
|
+ 'media_category',
|
|
|
+ 'attachment_category',
|
|
|
+ 'media-category',
|
|
|
+ );
|
|
|
+
|
|
|
+ foreach ($possible_taxonomies as $taxonomy) {
|
|
|
+ if (taxonomy_exists($taxonomy)) {
|
|
|
+ return $taxonomy;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get file count for a media category
|
|
|
+ *
|
|
|
+ * @param int $category_id Category term ID
|
|
|
+ * @param string $taxonomy Taxonomy name
|
|
|
+ * @return int File count
|
|
|
+ */
|
|
|
+ private function get_media_category_file_count($category_id, $taxonomy) {
|
|
|
+ global $wpdb;
|
|
|
+
|
|
|
+ $sql = "
|
|
|
+ SELECT COUNT(DISTINCT p.ID)
|
|
|
+ FROM {$wpdb->posts} p
|
|
|
+ INNER JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
|
|
|
+ INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
|
|
|
+ WHERE tt.term_id = %d
|
|
|
+ AND tt.taxonomy = %s
|
|
|
+ AND p.post_type = 'attachment'
|
|
|
+ ";
|
|
|
+
|
|
|
+ $count = $wpdb->get_var($wpdb->prepare($sql, $category_id, $taxonomy));
|
|
|
+
|
|
|
+ return intval($count);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get all media IDs from multiple media categories
|
|
|
+ *
|
|
|
+ * @param array $category_ids Array of category term IDs
|
|
|
+ * @return array Array of unique attachment IDs
|
|
|
+ */
|
|
|
+ private function get_media_from_categories($category_ids) {
|
|
|
+ global $wpdb;
|
|
|
+
|
|
|
+ $taxonomy = $this->get_media_category_taxonomy();
|
|
|
+
|
|
|
+ if (!$taxonomy || empty($category_ids)) {
|
|
|
+ return array();
|
|
|
+ }
|
|
|
+
|
|
|
+ $placeholders = implode(',', array_fill(0, count($category_ids), '%d'));
|
|
|
+
|
|
|
+ $sql = "
|
|
|
+ SELECT DISTINCT p.ID
|
|
|
+ FROM {$wpdb->posts} p
|
|
|
+ INNER JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
|
|
|
+ INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
|
|
|
+ WHERE tt.term_id IN ($placeholders)
|
|
|
+ AND tt.taxonomy = %s
|
|
|
+ AND p.post_type = 'attachment'
|
|
|
+ ";
|
|
|
+
|
|
|
+ $params = array_merge($category_ids, array($taxonomy));
|
|
|
+ $media = $wpdb->get_col($wpdb->prepare($sql, $params));
|
|
|
+
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Found ' . count($media) . ' media files in media categories ' . implode(', ', $category_ids));
|
|
|
+ }
|
|
|
+
|
|
|
+ return $media ? array_map('intval', $media) : array();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Delete a batch of media files permanently
|
|
|
+ *
|
|
|
+ * @param array $media_ids Array of attachment IDs to delete
|
|
|
+ * @return array Result with counts
|
|
|
+ */
|
|
|
+ private function delete_media_batch($media_ids) {
|
|
|
+ $deleted_count = 0;
|
|
|
+ $failed_count = 0;
|
|
|
+ $failed_media = array();
|
|
|
+
|
|
|
+ foreach ($media_ids as $media_id) {
|
|
|
+ try {
|
|
|
+ $attachment = get_post($media_id);
|
|
|
+
|
|
|
+ if (!$attachment || $attachment->post_type !== 'attachment') {
|
|
|
+ $failed_count++;
|
|
|
+ $failed_media[] = $media_id;
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Media file ' . $media_id . ' not found or not an attachment');
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Force delete attachment and its files from disk
|
|
|
+ $result = wp_delete_attachment($media_id, true);
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $deleted_count++;
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Successfully deleted media file ' . $media_id);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $failed_count++;
|
|
|
+ $failed_media[] = $media_id;
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Failed to delete media file ' . $media_id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception $e) {
|
|
|
+ $failed_count++;
|
|
|
+ $failed_media[] = $media_id;
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Exception deleting media file ' . $media_id . ': ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return array(
|
|
|
+ 'deleted_count' => $deleted_count,
|
|
|
+ 'failed_count' => $failed_count,
|
|
|
+ 'failed_media' => $failed_media
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handle AJAX clear media request (initial request to get media IDs)
|
|
|
+ */
|
|
|
+ public function handle_clear_media_ajax() {
|
|
|
+ while (ob_get_level()) {
|
|
|
+ ob_end_clean();
|
|
|
+ }
|
|
|
+
|
|
|
+ ob_start();
|
|
|
+
|
|
|
+ $original_error_reporting = error_reporting();
|
|
|
+ error_reporting(0);
|
|
|
+
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Clear media AJAX handler called');
|
|
|
+ error_log('STUDIOU WC: POST data: ' . print_r($_POST, true));
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'studiou-wcpcm-nonce')) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('Security check failed', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!current_user_can('manage_woocommerce')) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('You do not have sufficient permissions', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isset($_POST['media_categories'])) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('Missing required parameters', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ $category_ids = array_map('intval', $_POST['media_categories']);
|
|
|
+
|
|
|
+ if (empty($category_ids)) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('Please select at least one category', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ $media_ids = $this->get_media_from_categories($category_ids);
|
|
|
+
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Found ' . count($media_ids) . ' media files to delete');
|
|
|
+ }
|
|
|
+
|
|
|
+ ob_clean();
|
|
|
+
|
|
|
+ wp_send_json_success(array(
|
|
|
+ 'media_ids' => $media_ids,
|
|
|
+ 'total_count' => count($media_ids),
|
|
|
+ 'message' => sprintf(
|
|
|
+ __('Found %d media files to delete', 'studiou-wc-product-cat-manage'),
|
|
|
+ count($media_ids)
|
|
|
+ )
|
|
|
+ ));
|
|
|
+
|
|
|
+ } catch (Exception $e) {
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Clear media operation failed - ' . $e->getMessage());
|
|
|
+ error_log('STUDIOU WC: Exception trace: ' . $e->getTraceAsString());
|
|
|
+ }
|
|
|
+
|
|
|
+ ob_clean();
|
|
|
+
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => sprintf(
|
|
|
+ __('Error during clear media operation: %s', 'studiou-wc-product-cat-manage'),
|
|
|
+ $e->getMessage()
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ } finally {
|
|
|
+ error_reporting($original_error_reporting);
|
|
|
+ ob_end_clean();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handle AJAX clear media batch request (processes media in batches)
|
|
|
+ */
|
|
|
+ public function handle_clear_media_batch_ajax() {
|
|
|
+ while (ob_get_level()) {
|
|
|
+ ob_end_clean();
|
|
|
+ }
|
|
|
+
|
|
|
+ ob_start();
|
|
|
+
|
|
|
+ $original_error_reporting = error_reporting();
|
|
|
+ error_reporting(0);
|
|
|
+
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Clear media batch AJAX handler called');
|
|
|
+ error_log('STUDIOU WC: POST data: ' . print_r($_POST, true));
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'studiou-wcpcm-nonce')) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('Security check failed', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!current_user_can('manage_woocommerce')) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('You do not have sufficient permissions', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isset($_POST['media_ids'])) {
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => __('Missing required parameters', 'studiou-wc-product-cat-manage')
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ $media_ids = array_map('intval', $_POST['media_ids']);
|
|
|
+
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Processing batch of ' . count($media_ids) . ' media files for deletion');
|
|
|
+ }
|
|
|
+
|
|
|
+ $result = $this->delete_media_batch($media_ids);
|
|
|
+
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Batch media deletion completed - Deleted: ' . $result['deleted_count'] . ', Failed: ' . $result['failed_count']);
|
|
|
+ }
|
|
|
+
|
|
|
+ ob_clean();
|
|
|
+
|
|
|
+ wp_send_json_success(array(
|
|
|
+ 'deleted_count' => $result['deleted_count'],
|
|
|
+ 'failed_count' => $result['failed_count'],
|
|
|
+ 'failed_media' => $result['failed_media']
|
|
|
+ ));
|
|
|
+
|
|
|
+ } catch (Exception $e) {
|
|
|
+ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
+ error_log('STUDIOU WC: Clear media batch operation failed - ' . $e->getMessage());
|
|
|
+ error_log('STUDIOU WC: Exception trace: ' . $e->getTraceAsString());
|
|
|
+ }
|
|
|
+
|
|
|
+ ob_clean();
|
|
|
+
|
|
|
+ wp_send_json_error(array(
|
|
|
+ 'message' => sprintf(
|
|
|
+ __('Error during clear media batch operation: %s', 'studiou-wc-product-cat-manage'),
|
|
|
+ $e->getMessage()
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ } finally {
|
|
|
+ error_reporting($original_error_reporting);
|
|
|
+ ob_end_clean();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|