ad_tag_ids = array( array( 'tag' => '728x90', 'url_vars' => array( 'tag' => '728x90', 'sz' => '728x90', 'height' => '90', 'width' => '728', ), 'enable_ui_mapping' => true, ), array( 'tag' => '300x250', 'url_vars' => array( 'tag' => '300x250', 'sz' => '300x250', 'width' => '300', 'height' => '250', ), 'enable_ui_mapping' => true, ), array( 'tag' => '120x600', 'url_vars' => array( 'tag' => '120x600', 'sz' => '120x600', 'width' => '120', 'height' => '600', ), 'enable_ui_mapping' => true, ), array( 'tag' => '160x600', 'url_vars' => array( 'tag' => '160x600', 'sz' => '160x600', 'width' => '160', 'height' => '600', ), 'enable_ui_mapping' => true, ), array( 'tag' => '300x600', 'url_vars' => array( 'tag' => '300x600', 'sz' => '300x600', 'width' => '300', 'height' => '600', ), 'enable_ui_mapping' => true, ), // An extra, special tag to make sure the gets the output we need it to array( 'tag' => 'dfp_head', 'url_vars' => array(), ), ); // Default fields for DFP Async $this->ad_code_args = array( array( 'key' => 'tag', 'label' => __( 'Tag', 'ad-code-manager' ), 'editable' => true, 'required' => true, 'type' => 'select', 'options' => array( // This is added later, through 'acm_ad_code_args' filter ), ), array( 'key' => 'tag_id', 'label' => __( 'Tag ID', 'ad-code-manager' ), 'editable' => true, 'required' => true, ), array( 'key' => 'dfp_id', 'label' => __( 'DFP ID', 'ad-code-manager' ), 'editable' => true, 'required' => true, ), array( 'key' => 'tag_name', 'label' => __( 'Tag Name', 'ad-code-manager' ), 'editable' => true, 'required' => true, ), ); add_filter( 'acm_ad_code_args', array( $this, 'filter_ad_code_args' ) ); add_filter( 'acm_output_html', array( $this, 'filter_output_html' ), 10, 2 ); add_filter( 'acm_validate_ad_code', array( $this, 'validate_unique_tag_id' ), 10, 4 ); add_filter( 'acm_display_ad_codes_without_conditionals', '__return_true' ); add_action( 'wp_head', array( $this, 'action_wp_head' ) ); parent::__construct(); } /** * Register the 'tag's available for mapping in the UI */ public function filter_ad_code_args( $ad_code_args ) { global $ad_code_manager; foreach ( $ad_code_args as $tag => $ad_code_arg ) { if ( 'tag' != $ad_code_arg['key'] ) { continue; } // Get all of the tags that are registered, and provide them as options foreach ( (array) $ad_code_manager->ad_tag_ids as $ad_tag ) { if ( isset( $ad_tag['enable_ui_mapping'] ) && $ad_tag['enable_ui_mapping'] ) { $ad_code_args[ $tag ]['options'][ $ad_tag['tag'] ] = $ad_tag['tag']; } } } return $ad_code_args; } /** * Filter the output HTML to automagically produce the "; } return $output_script; } /** * Add the initialization code in the head */ public function action_wp_head() { do_action( 'acm_tag', 'dfp_head' ); } /** * Allow ad sizes to be defined as arrays or as basic width x height. * The purpose of this is to solve for flex units, where multiple ad * sizes may be required to load in the same ad unit. */ public function parse_ad_tag_sizes( $url_vars ) { if ( empty( $url_vars ) ) { return; } $unit_sizes_output = array(); if ( ! empty( $url_vars['sizes'] ) ) { foreach ( $url_vars['sizes'] as $unit_size ) { $unit_sizes_output[] = array( (int) $unit_size['width'], (int) $unit_size['height'], ); } } else { // fallback for old style width x height $unit_sizes_output = array( (int) $url_vars['width'], (int) $url_vars['height'], ); } return $unit_sizes_output; } /** * Validate that the tag_id is unique for DFP Async. * * DFP Async uses the tag_id as a div ID, so each tag_id must be unique * to prevent conflicts when multiple ads are rendered on the same page. * * @since 0.8.0 * * @param true|WP_Error $valid Current validation state. * @param array $ad_code_vals The ad code values being saved. * @param int $id The ad code ID (0 for new ad codes). * @param string $method The method being performed ('add' or 'edit'). * @return true|WP_Error True if valid, WP_Error if tag_id is not unique. */ public function validate_unique_tag_id( $valid, $ad_code_vals, $id, $method ) { // If already invalid, don't override the error. if ( is_wp_error( $valid ) ) { return $valid; } // Check if tag_id is provided. if ( empty( $ad_code_vals['tag_id'] ) ) { return $valid; } global $ad_code_manager; $tag_id = $ad_code_vals['tag_id']; $existing_id = $this->find_ad_code_by_tag_id( $tag_id ); // If no existing ad code with this tag_id, it's valid. if ( ! $existing_id ) { return true; } // If editing and the existing ad code is the same one we're editing, it's valid. if ( 'edit' === $method && $existing_id === $id ) { return true; } return new WP_Error( 'duplicate-tag-id', sprintf( /* translators: %s: the duplicate tag ID */ __( 'The Tag ID "%s" is already in use. Each Tag ID must be unique to prevent conflicts with DFP Async.', 'ad-code-manager' ), esc_html( $tag_id ) ) ); } /** * Find an ad code by its tag_id. * * @since 0.8.0 * * @param string $tag_id The tag_id to search for. * @return int|false The ad code post ID if found, false otherwise. */ protected function find_ad_code_by_tag_id( $tag_id ) { global $ad_code_manager; $ad_codes = $ad_code_manager->get_ad_codes(); foreach ( $ad_codes as $ad_code ) { if ( isset( $ad_code['url_vars']['tag_id'] ) && $ad_code['url_vars']['tag_id'] === $tag_id ) { return $ad_code['post_id']; } } return false; } } class Doubleclick_For_Publishers_Async_ACM_WP_List_Table extends ACM_WP_List_Table { function __construct() { parent::__construct( array( 'singular' => 'doubleclick_for_publishers_async_acm_wp_list_table', // Singular label 'plural' => 'doubleclick_for_publishers_async_acm_wp_list_table', // plural label, also this well be one of the table css class 'ajax' => true, ) ); } /** * @return array The columns that shall be used */ function filter_columns() { return array( 'cb' => '', 'id' => __( 'ID', 'ad-code-manager' ), 'tag' => __( 'Tag', 'ad-code-manager' ), 'tag_id' => __( 'Tag ID', 'ad-code-manager' ), 'dfp_id' => __( 'DFP ID', 'ad-code-manager' ), 'tag_name' => __( 'Tag Name', 'ad-code-manager' ), 'priority' => __( 'Priority', 'ad-code-manager' ), 'operator' => __( 'Logical Operator', 'ad-code-manager' ), 'conditionals' => __( 'Conditionals', 'ad-code-manager' ), ); } /** * This is nuts and bolts of table representation */ function get_columns() { add_filter( 'acm_list_table_columns', array( $this, 'filter_columns' ) ); return parent::get_columns(); } /** * Output the tag cell in the list table */ function column_tag( $item ) { $output = isset( $item['tag'] ) ? esc_html( $item['tag'] ) : esc_html( $item['url_vars']['tag'] ); $output .= $this->row_actions_output( $item ); return $output; } }