bulk_tools = new AdFusion_Bulk_Tools();
add_action( 'admin_post_adfusion_save_group_dimensions', array( $this, 'handle_save_group_dimensions' ) );
}
/** Term meta keys for Ad Group max dimensions (shared with Premium). */
const META_MAX_WIDTH = '_adf_max_width';
const META_MAX_HEIGHT = '_adf_max_height';
const META_MAX_WIDTH_UNIT = '_adf_max_width_unit';
const META_MAX_HEIGHT_UNIT = '_adf_max_height_unit';
/**
* Enqueue media library and admin scripts on the Ad edit screen.
*
* @param string $hook_suffix The current admin page. Unused but required by the hook.
* @return void
*/
public function enqueue_ad_edit_scripts( $hook_suffix ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
$screen = get_current_screen();
if ( ! $screen || 'adfusion_ad' !== $screen->post_type ) {
return;
}
wp_enqueue_media();
$script_url = defined( 'ADFUSION_PREMIUM_URL' )
? ADFUSION_PREMIUM_URL . 'assets/js/adf-admin-media.js'
: ADFUSION_PLUGIN_URL . 'assets/js/adf-admin-media.js';
wp_enqueue_script(
'adf-admin-media',
$script_url,
array( 'jquery' ),
defined( 'ADFUSION_PREMIUM_VERSION' ) ? ADFUSION_PREMIUM_VERSION : ADFUSION_VERSION,
true
);
wp_localize_script(
'adf-admin-media',
'adfAdminMedia',
array(
'selectImage' => __( 'Select or Upload Image', 'adfusion-ad-manager-and-monetization' ),
'useThisImage' => __( 'Use this image', 'adfusion-ad-manager-and-monetization' ),
)
);
}
/**
* Register the custom meta box for the 'adfusion_ad' post type.
*
* @return void
*/
public function add_ad_meta_boxes() {
add_meta_box(
'adfusion_ad_details', // Unique ID for the meta box.
__( 'Ad Details & Configuration', 'adfusion-ad-manager-and-monetization' ), // Meta box title.
array( $this, 'render_ad_meta_box' ), // Callback function to render the HTML.
'adfusion_ad', // Post type to display it on.
'normal', // Placement on the screen (normal, side, advanced).
'high' // Priority.
);
}
/**
* Render the HTML inside the custom meta box.
*
* @param WP_Post $post The current post object.
* @return void
*/
public function render_ad_meta_box( $post ) {
// Add a nonce field for security to verify the request later.
wp_nonce_field( 'adfusion_save_ad_data', 'adfusion_ad_meta_nonce' );
// Retrieve existing values from the database if they exist.
$ad_type = get_post_meta( $post->ID, '_adf_ad_type', true );
$destination_url = get_post_meta( $post->ID, '_adf_destination_url', true );
if ( empty( $destination_url ) ) {
$destination_url = get_post_meta( $post->ID, '_adf_ad_url', true );
}
$start_datetime = get_post_meta( $post->ID, '_adf_start_datetime', true );
$end_datetime = get_post_meta( $post->ID, '_adf_end_datetime', true );
if ( empty( $start_datetime ) ) {
$start_date = get_post_meta( $post->ID, '_adf_start_date', true );
$start_datetime = ! empty( $start_date ) ? $start_date . ' 00:00:00' : '';
}
if ( empty( $end_datetime ) ) {
$end_date = get_post_meta( $post->ID, '_adf_end_date', true );
$end_datetime = ! empty( $end_date ) ? $end_date . ' 23:59:59' : '';
}
$start_date_val = ! empty( $start_datetime ) ? substr( $start_datetime, 0, 10 ) : '';
$start_time_val = ! empty( $start_datetime ) ? substr( $start_datetime, 11, 5 ) : '';
$end_date_val = ! empty( $end_datetime ) ? substr( $end_datetime, 0, 10 ) : '';
$end_time_val = ! empty( $end_datetime ) ? substr( $end_datetime, 11, 5 ) : '';
$ad_code = get_post_meta( $post->ID, '_adf_ad_code', true );
$google_ad_slot = get_post_meta( $post->ID, '_adf_google_ad_slot', true );
$ad_image = get_post_meta( $post->ID, '_adf_ad_image', true );
$ad_image_mobile = get_post_meta( $post->ID, '_adf_ad_image_mobile', true );
$adf_desktop_only = get_post_meta( $post->ID, '_adf_desktop_only', true );
$adf_mobile_only = get_post_meta( $post->ID, '_adf_mobile_only', true );
// Default to 'image' if no type is set.
if ( empty( $ad_type ) ) {
$ad_type = 'image';
}
// Begin HTML output.
?>
validate_adf_date_ymd( sanitize_text_field( wp_unslash( $_POST['adf_start_date'] ) ) );
}
$start_time = '';
if ( isset( $_POST['adf_start_time'] ) ) {
$start_time = preg_replace( '/[^0-9:]/', '', sanitize_text_field( wp_unslash( $_POST['adf_start_time'] ) ) );
}
if ( preg_match( '/^\d{1,2}:\d{2}$/', $start_time ) ) {
$parts = explode( ':', $start_time );
$start_time = sprintf( '%02d:%02d', (int) $parts[0], (int) $parts[1] );
} else {
$start_time = '';
}
$start_val = ( ! empty( $start_date ) && ! empty( $start_time ) ) ? $start_date . ' ' . $start_time . ':00' : ( ! empty( $start_date ) ? $start_date . ' 00:00:00' : '' );
update_post_meta( $post_id, '_adf_start_datetime', $start_val );
// 13. End Date & Time.
$end_date = '';
if ( isset( $_POST['adf_end_date'] ) ) {
$end_date = $this->validate_adf_date_ymd( sanitize_text_field( wp_unslash( $_POST['adf_end_date'] ) ) );
}
$end_time = '';
if ( isset( $_POST['adf_end_time'] ) ) {
$end_time = preg_replace( '/[^0-9:]/', '', sanitize_text_field( wp_unslash( $_POST['adf_end_time'] ) ) );
}
if ( preg_match( '/^\d{1,2}:\d{2}$/', $end_time ) ) {
$parts = explode( ':', $end_time );
$end_time = sprintf( '%02d:%02d', (int) $parts[0], (int) $parts[1] );
} else {
$end_time = '';
}
$end_val = ( ! empty( $end_date ) && ! empty( $end_time ) ) ? $end_date . ' ' . $end_time . ':00' : ( ! empty( $end_date ) ? $end_date . ' 23:59:59' : '' );
update_post_meta( $post_id, '_adf_end_datetime', $end_val );
do_action( 'adfusion_after_save_ad_meta', $post_id );
}
/**
* Validate a sanitized string is Y-m-d or return empty.
*
* @param string $sanitized Already sanitized text (e.g. from sanitize_text_field).
* @return string Empty or Y-m-d.
*/
private function validate_adf_date_ymd( $sanitized ) {
if ( '' === $sanitized || ! is_string( $sanitized ) ) {
return '';
}
if ( 1 !== preg_match( '/^\d{4}-\d{2}-\d{2}$/', $sanitized ) ) {
return '';
}
return $sanitized;
}
/**
* Add Settings submenu under AdFusion CPT.
*
* @return void
*/
public function add_settings_page() {
add_submenu_page(
'edit.php?post_type=adfusion_ad',
__( 'Settings', 'adfusion-ad-manager-and-monetization' ),
__( 'Settings', 'adfusion-ad-manager-and-monetization' ),
'manage_options',
'adfusion-settings',
array( $this, 'render_settings_page' )
);
}
/**
* Register settings for automatic ad injection.
*
* @return void
*/
public function register_settings() {
register_setting(
'adfusion_settings_group',
'adfusion_before_content_group',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
'adfusion_settings_group',
'adfusion_after_content_group',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
'adfusion_settings_group',
'adfusion_premium_popup_duration_seconds',
array(
'type' => 'integer',
'default' => 30,
'sanitize_callback' => function ( $value ) {
$val = absint( $value );
return $val >= 0 ? $val : 30;
},
)
);
register_setting(
'adfusion_settings_group',
'adfusion_story_header_position',
array(
'type' => 'string',
'default' => 'above',
'sanitize_callback' => function ( $value ) {
return in_array( $value, array( 'above', 'below' ), true ) ? $value : 'above';
},
)
);
register_setting(
'adfusion_settings_group',
'adf_ads_txt_enabled',
array(
'type' => 'string',
'default' => '1',
'sanitize_callback' => function ( $value ) {
return ( ! empty( $value ) && '1' === (string) $value ) ? '1' : '0';
},
)
);
if ( ! defined( 'ADFUSION_PREMIUM_VERSION' ) ) {
register_setting(
'adfusion_settings_group',
'adf_google_adsense_id',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'default' => '',
)
);
}
}
/**
* Render the Settings page.
*
* @return void
*/
public function render_settings_page() {
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.NonceVerification.Recommended -- Tab is display-only; sanitized.
$current_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'settings';
$base_url = add_query_arg(
array(
'post_type' => 'adfusion_ad',
'page' => 'adfusion-settings',
),
admin_url( 'edit.php' )
);
?>
render_dimensions_tab();
echo '
';
return;
}
if ( 'tools' === $current_tab ) {
$this->render_import_notices();
$this->bulk_tools->render_tools_tab();
echo '';
return;
}
$cache_key = ADFUSION_PLUGIN_SLUG . '_ad_groups';
$ad_groups = get_transient( $cache_key );
if ( false === $ad_groups ) {
$ad_groups = get_terms(
array(
'taxonomy' => 'adfusion_group',
'hide_empty' => false,
)
);
if ( ! is_wp_error( $ad_groups ) ) {
set_transient( $cache_key, $ad_groups, DAY_IN_SECONDS );
} else {
$ad_groups = array();
}
}
if ( is_wp_error( $ad_groups ) ) {
$ad_groups = array();
}
?>
'adfusion_group',
'hide_empty' => false,
)
);
if ( is_wp_error( $terms ) || empty( $terms ) ) {
echo '' . esc_html__( 'No Ad Groups found. Create Ad Groups first under Ads → Ad Groups.', 'adfusion-ad-manager-and-monetization' ) . '
';
return;
}
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Display-only from our redirect.
$saved = isset( $_GET['adfusion_dimensions_saved'] ) && '1' === sanitize_text_field( wp_unslash( $_GET['adfusion_dimensions_saved'] ) );
// phpcs:enable WordPress.Security.NonceVerification.Recommended
?>
'adfusion_group',
'hide_empty' => false,
'fields' => 'ids',
)
);
if ( ! is_wp_error( $terms ) ) {
foreach ( $terms as $tid ) {
$tid = (int) $tid;
$w = isset( $raw_w[ $tid ] ) ? absint( $raw_w[ $tid ] ) : 0;
$h = isset( $raw_h[ $tid ] ) ? absint( $raw_h[ $tid ] ) : 0;
$wu = isset( $raw_wu[ $tid ] ) && in_array( $raw_wu[ $tid ], array( 'px', 'vw' ), true ) ? $raw_wu[ $tid ] : 'px';
$hu = isset( $raw_hu[ $tid ] ) && in_array( $raw_hu[ $tid ], array( 'px', 'vh' ), true ) ? $raw_hu[ $tid ] : 'px';
update_term_meta( $tid, self::META_MAX_WIDTH, $w > 0 ? $w : '' );
update_term_meta( $tid, self::META_MAX_HEIGHT, $h > 0 ? $h : '' );
update_term_meta( $tid, self::META_MAX_WIDTH_UNIT, $w > 0 ? $wu : '' );
update_term_meta( $tid, self::META_MAX_HEIGHT_UNIT, $h > 0 ? $hu : '' );
}
}
wp_safe_redirect(
add_query_arg(
array(
'post_type' => 'adfusion_ad',
'page' => 'adfusion-settings',
'tab' => 'dimensions',
'adfusion_dimensions_saved' => 1,
),
admin_url( 'edit.php' )
)
);
exit;
}
/**
* Render admin notices for CSV import results.
*
* @return void
*/
private function render_import_notices() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Import/sync result params from our own redirect; sanitized.
if ( isset( $_GET['adfusion_sync_urls'] ) && 'success' === sanitize_key( wp_unslash( $_GET['adfusion_sync_urls'] ) ) ) {
$count = isset( $_GET['adfusion_sync_count'] ) ? absint( $_GET['adfusion_sync_count'] ) : 0;
echo '';
echo esc_html(
sprintf(
/* translators: %d: number of ads updated */
__( 'Destination URLs synced. %d ad(s) updated.', 'adfusion-ad-manager-and-monetization' ),
$count
)
);
echo '
';
return;
}
if ( ! isset( $_GET['adfusion_import'] ) ) {
return;
}
$status = isset( $_GET['adfusion_import'] ) ? sanitize_key( wp_unslash( $_GET['adfusion_import'] ) ) : '';
if ( 'success' === $status ) {
$created = isset( $_GET['adfusion_created'] ) ? absint( $_GET['adfusion_created'] ) : 0;
$updated = isset( $_GET['adfusion_updated'] ) ? absint( $_GET['adfusion_updated'] ) : 0;
echo '';
echo esc_html(
sprintf(
/* translators: 1: number of ads created, 2: number of ads updated */
__( 'Import complete. %1$d ad(s) created, %2$d ad(s) updated.', 'adfusion-ad-manager-and-monetization' ),
$created,
$updated
)
);
echo '
';
} elseif ( 'error' === $status ) {
$msg = isset( $_GET['adfusion_import_msg'] ) ? sanitize_key( wp_unslash( $_GET['adfusion_import_msg'] ) ) : '';
$messages = array(
'no_file' => __( 'No file was uploaded.', 'adfusion-ad-manager-and-monetization' ),
'read_failed' => __( 'Could not read the uploaded file.', 'adfusion-ad-manager-and-monetization' ),
'empty_file' => __( 'The CSV file is empty or invalid.', 'adfusion-ad-manager-and-monetization' ),
);
$text = isset( $messages[ $msg ] ) ? $messages[ $msg ] : __( 'An error occurred during import.', 'adfusion-ad-manager-and-monetization' );
echo '' . esc_html( $text ) . '
';
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended
}
}
// Instantiate the class.
if ( is_admin() ) {
new AdFusion_Admin();
}