Column header labels. */ private static function get_csv_headers() { return array( __( 'Title', 'adfusion-ad-manager-and-monetization' ), __( 'Link URL', 'adfusion-ad-manager-and-monetization' ), __( 'Desktop Image URL', 'adfusion-ad-manager-and-monetization' ), __( 'Mobile Image URL', 'adfusion-ad-manager-and-monetization' ), __( 'Start Date', 'adfusion-ad-manager-and-monetization' ), __( 'End Date', 'adfusion-ad-manager-and-monetization' ), __( 'Weight', 'adfusion-ad-manager-and-monetization' ), __( 'Whitelisted Category IDs', 'adfusion-ad-manager-and-monetization' ), ); } /** * Constructor. */ public function __construct() { add_action( 'admin_post_adfusion_export_ads_csv', array( $this, 'handle_export' ) ); add_action( 'admin_post_adfusion_import_ads_csv', array( $this, 'handle_import' ) ); add_action( 'admin_post_adfusion_sync_destination_urls', array( $this, 'handle_sync_destination_urls' ) ); } /** * Render the Tools tab content. * * @return void */ public function render_tools_tab() { if ( ! current_user_can( 'manage_options' ) ) { return; } ?>

'adfusion_ad', 'posts_per_page' => -1, 'post_status' => 'any', 'orderby' => 'title', 'order' => 'ASC', ) ); header( 'Content-Type: text/csv; charset=utf-8' ); header( 'Content-Disposition: attachment; filename=adfusion-ads-' . gmdate( 'Y-m-d' ) . '.csv' ); $output = fopen( 'php://output', 'w' ); if ( false === $output ) { wp_die( esc_html__( 'Could not create export file.', 'adfusion-ad-manager-and-monetization' ) ); } fputcsv( $output, self::get_csv_headers() ); foreach ( $ads as $ad ) { $start = get_post_meta( $ad->ID, '_adf_start_datetime', true ); if ( empty( $start ) ) { $start = get_post_meta( $ad->ID, '_adf_start_date', true ); } $end = get_post_meta( $ad->ID, '_adf_end_datetime', true ); if ( empty( $end ) ) { $end = get_post_meta( $ad->ID, '_adf_end_date', true ); } $target_cats = get_post_meta( $ad->ID, '_adf_target_categories', true ); $cat_ids = is_array( $target_cats ) ? implode( ',', array_map( 'absint', $target_cats ) ) : ''; fputcsv( $output, array( $ad->post_title, get_post_meta( $ad->ID, '_adf_destination_url', true ), get_post_meta( $ad->ID, '_adf_ad_image', true ), get_post_meta( $ad->ID, '_adf_ad_image_mobile', true ), $start ? substr( $start, 0, 10 ) : '', $end ? substr( $end, 0, 10 ) : '', $this->get_weight_for_export( $ad->ID ), $cat_ids, ) ); } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Streaming to php://output for CSV download. fclose( $output ); exit; } /** * Get weight value for CSV export (default 1 if empty). * * @param int $post_id Post ID. * @return string Weight as string. */ private function get_weight_for_export( $post_id ) { $weight = get_post_meta( $post_id, '_adf_weight', true ); return ! empty( $weight ) ? (string) $weight : '1'; } /** * Handle CSV import. * * @return void */ public function handle_import() { check_admin_referer( 'adfusion_import_ads_csv', 'adfusion_import_nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'adfusion-ad-manager-and-monetization' ) ); } // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- tmp_name validated by is_uploaded_file; path is server-generated. $tmp_path = isset( $_FILES['adfusion_csv_file']['tmp_name'] ) ? $_FILES['adfusion_csv_file']['tmp_name'] : ''; if ( empty( $tmp_path ) || ! is_uploaded_file( $tmp_path ) ) { wp_safe_redirect( add_query_arg( array( 'page' => 'adfusion-settings', 'tab' => 'tools', 'adfusion_import' => 'error', 'adfusion_import_msg' => 'no_file', ), admin_url( 'edit.php?post_type=adfusion_ad' ) ) ); exit; } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- CSV import requires fopen for fgetcsv. $handle = fopen( $tmp_path, 'r' ); if ( false === $handle ) { wp_safe_redirect( add_query_arg( array( 'page' => 'adfusion-settings', 'tab' => 'tools', 'adfusion_import' => 'error', 'adfusion_import_msg' => 'read_failed', ), admin_url( 'edit.php?post_type=adfusion_ad' ) ) ); exit; } $created = 0; $updated = 0; // Skip header row. $header = fgetcsv( $handle ); if ( false === $header ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Standard PHP file handle. fclose( $handle ); wp_safe_redirect( add_query_arg( array( 'page' => 'adfusion-settings', 'tab' => 'tools', 'adfusion_import' => 'error', 'adfusion_import_msg' => 'empty_file', ), admin_url( 'edit.php?post_type=adfusion_ad' ) ) ); exit; } $row = fgetcsv( $handle ); while ( false !== $row ) { if ( empty( $row[0] ) ) { continue; } $title = sanitize_text_field( $row[0] ); $link_url = isset( $row[1] ) ? esc_url_raw( trim( $row[1] ) ) : ''; $desktop_img = isset( $row[2] ) ? esc_url_raw( trim( $row[2] ) ) : ''; $mobile_img = isset( $row[3] ) ? esc_url_raw( trim( $row[3] ) ) : ''; $start_date = isset( $row[4] ) ? sanitize_text_field( trim( $row[4] ) ) : ''; $end_date = isset( $row[5] ) ? sanitize_text_field( trim( $row[5] ) ) : ''; $weight = isset( $row[6] ) ? max( 1, min( 10, (int) $row[6] ) ) : 1; $cat_ids_raw = isset( $row[7] ) ? trim( $row[7] ) : ''; global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Single lookup by title; caching not practical. $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_title = %s AND post_status != 'trash' LIMIT 1", 'adfusion_ad', $title ) ); $existing = $post_id ? get_post( $post_id ) : null; if ( $existing ) { $post_id = $existing->ID; ++$updated; } else { $post_id = wp_insert_post( array( 'post_title' => $title, 'post_type' => 'adfusion_ad', 'post_status' => 'publish', ) ); if ( is_wp_error( $post_id ) ) { continue; } ++$created; } if ( ! $post_id ) { continue; } update_post_meta( $post_id, '_adf_destination_url', $link_url ); update_post_meta( $post_id, '_adf_ad_url', $link_url ); update_post_meta( $post_id, '_adf_ad_image', $desktop_img ); update_post_meta( $post_id, '_adf_ad_image_mobile', $mobile_img ); update_post_meta( $post_id, '_adf_ad_type', 'image' ); update_post_meta( $post_id, '_adf_weight', (string) $weight ); if ( ! empty( $start_date ) ) { $start_val = preg_match( '/^\d{4}-\d{2}-\d{2}$/', $start_date ) ? $start_date . ' 00:00:00' : $start_date; update_post_meta( $post_id, '_adf_start_datetime', $start_val ); } if ( ! empty( $end_date ) ) { $end_val = preg_match( '/^\d{4}-\d{2}-\d{2}$/', $end_date ) ? $end_date . ' 23:59:59' : $end_date; update_post_meta( $post_id, '_adf_end_datetime', $end_val ); } $target_cats = array(); if ( ! empty( $cat_ids_raw ) ) { $target_cats = array_filter( array_map( 'absint', array_map( 'trim', explode( ',', $cat_ids_raw ) ) ) ); } update_post_meta( $post_id, '_adf_target_categories', $target_cats ); $row = fgetcsv( $handle ); } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Standard PHP file handle. fclose( $handle ); wp_safe_redirect( add_query_arg( array( 'page' => 'adfusion-settings', 'tab' => 'tools', 'adfusion_import' => 'success', 'adfusion_created' => $created, 'adfusion_updated' => $updated, ), admin_url( 'edit.php?post_type=adfusion_ad' ) ) ); exit; } /** * Sync _adf_destination_url and _adf_ad_url for all ads en masse. * Ensures both meta keys have the destination URL so click redirects work. * * @return void */ public function handle_sync_destination_urls() { check_admin_referer( 'adfusion_sync_destination_urls', 'adfusion_sync_urls_nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'adfusion-ad-manager-and-monetization' ) ); } $ads = get_posts( array( 'post_type' => 'adfusion_ad', 'posts_per_page' => -1, 'post_status' => 'any', ) ); $updated = 0; foreach ( $ads as $ad ) { $dest = get_post_meta( $ad->ID, '_adf_destination_url', true ); $url = get_post_meta( $ad->ID, '_adf_ad_url', true ); $canonical = ! empty( $dest ) ? $dest : $url; if ( empty( $canonical ) ) { continue; } $changed = false; if ( $dest !== $canonical ) { update_post_meta( $ad->ID, '_adf_destination_url', $canonical ); $changed = true; } if ( $url !== $canonical ) { update_post_meta( $ad->ID, '_adf_ad_url', $canonical ); $changed = true; } if ( $changed ) { ++$updated; } } wp_safe_redirect( add_query_arg( array( 'page' => 'adfusion-settings', 'tab' => 'tools', 'adfusion_sync_urls' => 'success', 'adfusion_sync_count' => $updated, ), admin_url( 'edit.php?post_type=adfusion_ad' ) ) ); exit; } }