wo_meta = new WOMeta( AdCommander::ns() );
$this->nonce = $this->nonce( basename( __FILE__ ), AdCommander::tax_group() );
add_action( AdCommander::tax_group() . '_edit_form_fields', array( $this, 'edit_term_fields' ), 10, 1 );
add_action( AdCommander::tax_group() . '_term_edit_form_top', array( $this, 'before_form_table' ), 10, 1 );
add_action( AdCommander::tax_group() . '_edit_form', array( $this, 'after_form_table' ), 10, 1 );
add_action( 'edited_' . AdCommander::tax_group(), array( $this, 'update_group_meta' ), 10, 1 );
add_action( 'created_' . AdCommander::tax_group(), array( $this, 'update_group_meta' ), 10, 1 );
add_action( 'set_object_terms', array( $this, 'set_object_terms_count' ), 10, 6 );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
foreach ( $this->get_action_keys() as $key ) {
$key_underscore = self::_key( $key );
add_action( 'wp_ajax_' . $this->action_string( $key ), array( $this, 'action_' . $key_underscore ) );
}
// Add info to the new columns
add_action( 'manage_' . AdCommander::tax_group() . '_custom_column', array( $this, 'manage_group_column_data' ), 10, 3 );
add_filter( 'manage_edit-' . AdCommander::tax_group() . '_columns', array( $this, 'manage_group_columns' ) );
add_filter( 'manage_edit-' . AdCommander::tax_group() . '_sortable_columns', array( $this, 'manage_sortable_columns' ) );
add_filter( 'quick_edit_enabled_for_taxonomy', array( $this, 'quick_edit_enabled_for_groups' ), 10, 2 );
add_filter( 'pre_get_terms', array( $this, 'sort_group_terms' ) );
$this->admin_targeting()->hooks();
}
/**
* Disable quick edit for groups.
*
* @param boolean $bool If quick edit is currently enabled.
* @param mixed $taxonomy The current taxonomy.
*
* @return bool
*/
public function quick_edit_enabled_for_groups( $bool, $taxonomy ) {
return ( $taxonomy === AdCommander::tax_group() ) ? false : $bool;
}
/**
* Potentially update the number of ads in a group when a term is saved.
*
* @param int $object_id The term that was saved.
* @param array $terms An array of object term IDs or slugs.
* @param array $tt_ids An array of term taxonomy IDs.
* @param string $taxonomy Taxonomy slug.
* @param bool $append Whether to append new terms to the old terms.
* @param array $old_tt_ids Old array of term taxonomy IDs.
*
* @return void
*/
public function set_object_terms_count( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
if ( $taxonomy !== AdCommander::tax_group() ) {
return;
}
/**
* Compare tt_ids and $old_ttids and refresh any that are different.
*/
$this->refresh_group_count_transient( $tt_ids, $old_tt_ids );
}
/**
* Compare new and old term IDs. Remove the count transient for any terms that were updated.
*
* @param array $tt_ids An array of term taxonomy IDs.
* @param array $old_tt_ids Old array of term taxonomy IDs.
*
* @return void
*/
private function refresh_group_count_transient( $tt_ids, $old_tt_ids ) {
$term_ids = array_merge( array_diff( $tt_ids, $old_tt_ids ), array_diff( $old_tt_ids, $tt_ids ) );
if ( ! empty( $term_ids ) ) {
foreach ( $term_ids as $term_id ) {
delete_transient( GroupTermMeta::group_count_transient( $term_id ) );
}
}
}
/**
* Enqueue scripts if we're on a screen that needs them.
*
* @return void
*/
public function admin_enqueue_scripts() {
if ( $this->is_screen( array( 'edit-' . AdCommander::tax_group() ) ) ) {
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'jquery-ui-core' );
wp_enqueue_script( 'jquery-ui-sortable' );
wp_enqueue_script( 'jquery-ui-autocomplete' );
$this->enqueue_jquery_ui_styles();
$targeting_handle = $this->admin_targeting()->enqueue();
wp_register_script( 'worotate', AdCommander::assets_url() . 'js/rotate.js', array(), AdCommander::version(), array( 'in_footer' => true ) );
wp_enqueue_script( 'worotate' );
$handle = Util::ns( 'term-meta' );
wp_register_script( $handle, AdCommander::assets_url() . 'js/term-meta.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-sortable', 'worotate', $targeting_handle ), AdCommander::version(), array( 'in_footer' => true ) );
wp_enqueue_script( $handle );
Util::enqueue_script_data(
$handle,
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'terms_url' => admin_url( 'term.php' ),
'tax_name' => AdCommander::tax_group(),
'post_type' => AdCommander::posttype_ad(),
'actions' => $this->get_ajax_actions(),
'save_button_text' => esc_html__( 'Save all settings', 'ad-commander' ),
'sort_handle_url' => self::sortable_handle_url(),
)
);
}
}
/**
* Get necessary action keys, which will be used to create wp_ajax hooks.
*
* @return array
*/
private function get_action_keys() {
return array(
'delete-ad-from-group',
'update-ad-order',
'get-ads-for-search',
'add-ad-to-term',
);
}
/**
* Creates an array of all of the necessary actions.
*
* @return array
*/
private function get_ajax_actions() {
$actions = array();
foreach ( $this->get_action_keys() as $key ) {
$actions[ self::_key( $key ) ] = array(
'action' => $this->action_string( $key ),
'security' => wp_create_nonce( $this->nonce_string( $key ) ),
);
}
return $actions;
}
/**
* A wp_ajax hook that updates the order of ads in a group.
*
* @return void
*/
public function action_update_ad_order() {
$action = 'update-ad-order';
check_ajax_referer( $this->nonce_string( $action ), 'security' );
if ( ! current_user_can( AdCommander::capability() ) ) {
wp_die();
}
if ( ! isset( $_POST['group_id'] ) ) {
wp_die();
}
$group_id = ( isset( $_POST['group_id'] ) ) ? absint( $_POST['group_id'] ) : null;
$ad_order = ( isset( $_POST['ad_order'] ) && ! empty( $_POST['ad_order'] ) ) ? array_map( 'absint', $_POST['ad_order'] ) : array();
if ( update_term_meta( $group_id, $this->wo_meta->make_key( 'ad_order' ), $ad_order ) ) {
wp_send_json_success(
array(
'action' => $action,
'groupid' => $group_id,
)
);
}
wp_die();
}
/**
* A wp_ajax hook that deletes an ad from a group.
*
* @return void
*/
public function action_delete_ad_from_group() {
$action = 'delete-ad-from-group';
check_ajax_referer( $this->nonce_string( $action ), 'security' );
if ( ! current_user_can( AdCommander::capability() ) ) {
wp_die();
}
if ( ! isset( $_POST['group_id'] ) || ! isset( $_POST['ad_id'] ) ) {
wp_die();
}
$group_id = ( isset( $_POST['group_id'] ) ) ? absint( $_POST['group_id'] ) : null;
$ad_id = ( isset( $_POST['ad_id'] ) ) ? absint( $_POST['ad_id'] ) : null;
if ( wp_remove_object_terms( $ad_id, $group_id, AdCommander::tax_group() ) ) {
delete_transient( GroupTermMeta::group_count_transient( $group_id ) );
wp_send_json_success(
array(
'action' => $action,
'groupid' => $group_id,
'adid' => $ad_id,
)
);
}
wp_die();
}
/**
* The name of the transient that stores our filtered ads.
*
* @return string
*/
public static function group_search_ads_transient() {
return Util::ns( 'group_search_ads', '_' );
}
/**
* Store the available filter ads in a transient so we don't have to query them every time.
*
* @return array
*/
private function get_ads_for_search() {
$ads = get_transient( self::group_search_ads_transient() );
if ( $ads === false ) {
$available_ads = Query::ads( 'post_title', 'asc', Util::any_post_status( 'trash' ), array(), array() );
$ads = array();
if ( ! empty( $available_ads ) ) {
foreach ( $available_ads as $ad ) {
$ads[] = array(
'id' => $ad->ID,
'title' => $ad->post_title,
'status' => ( $ad->post_status !== 'publish' ) ? wp_strip_all_tags( Util::post_status_label( $ad->post_status ) ) : 'publish',
);
}
}
set_transient( self::group_search_ads_transient(), $ads, 20 );
}
return $ads;
}
/**
* Wp_ajax hook. Gets all of the ads for use in the filter.
*
* @return void
*/
public function action_get_ads_for_search() {
$action = 'get-ads-for-search';
check_ajax_referer( $this->nonce_string( $action ), 'security' );
if ( ! current_user_can( AdCommander::capability() ) ) {
wp_die();
}
wp_send_json_success(
array(
'action' => $action,
'ads' => $this->get_ads_for_search(),
)
);
wp_die();
}
/**
* Wp_ajax hook. Gets all of the ads for use in the filter.
*
* @return void
*/
public function action_add_ad_to_term() {
$action = 'add-ad-to-term';
check_ajax_referer( $this->nonce_string( $action ), 'security' );
if ( ! current_user_can( AdCommander::capability() ) ) {
wp_die();
}
if ( ! isset( $_POST['group_id'] ) || ! isset( $_POST['ad_id'] ) ) {
wp_die();
}
$group_id = ( isset( $_POST['group_id'] ) ) ? absint( $_POST['group_id'] ) : null;
$ad_id = ( isset( $_POST['ad_id'] ) ) ? absint( $_POST['ad_id'] ) : null;
if ( wp_add_object_terms( $ad_id, $group_id, AdCommander::tax_group() ) ) {
delete_transient( GroupTermMeta::group_count_transient( $group_id ) );
wp_send_json_success(
array(
'action' => $action,
'groupid' => $group_id,
'adid' => $ad_id,
)
);
}
wp_die();
}
/**
* Ad fields before the form table while viewing a Group term.
*
* @param object $term The current term.
*
* @return void
*/
public function before_form_table( $term ) {
$this->nonce_field( $this->nonce );
$this->back_to_groups();
?>
group_ad_list( $term );
$this->group_preview( $term );
}
/**
* Back to groups link at top of term page.
*/
private function back_to_groups() {
?>
term_id, $this->wo_meta->make_key( 'ad_order' ), true );
$ad_weights = get_term_meta( $term->term_id, $this->wo_meta->make_key( 'ad_weights' ), true );
if ( ! $sorted_ids || ! is_array( $sorted_ids ) ) {
$sorted_ids = array();
}
$ads = Group::sort_ads_by_sorted_ids( Query::ads_by_group( $term->term_id, Util::any_post_status() ), $sorted_ids );
?>
term_id ) ) :
?>
term_id ) ) :
$this->usage( $term );
?>
info( __( 'Script tags and other unsafe HTML are removed in the admin preview. Ads may appear differently to visitors due to front-end styles from your theme or other plugins.', 'ad-commander' ) );
/**
* Stripping script tags because this is in the admin.
*/
echo wp_kses_post(
adcmdr_display_group(
$term->term_id,
array(
'display' => false,
'force_noajax' => true,
'disable_wrappers' => false,
)
)
);
?>
term_id ) ) {
$term_id = $term->term_id;
}
$this->current_meta = $this->wo_meta->get_term_meta( $term_id, GroupTermMeta::tax_group_meta_keys() );
/**
* Mode
*/
$modes = Group::modes();
$current_mode = $this->wo_meta->get_value( $this->current_meta, 'mode' );
if ( ! ProBridge::instance()->is_pro_loaded() ) {
$nonpro_modes = array();
foreach ( $modes as $key => $mode ) {
if ( in_array( $key, ProBridge::instance()->pro_group_modes() ) ) {
$key = 'disabled:' . $key;
$mode .= ProBridge::pro_label();
if ( $current_mode === $key ) {
$current_mode = 'single';
}
}
$nonpro_modes[ $key ] = $mode;
}
$modes = $nonpro_modes;
}
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'mode', __( 'Mode', 'ad-commander' ), array( 'display' => false ) ), // th
$this->wo_meta->select( 'mode', $modes, $current_mode, array( 'display' => false ) ) . Doc::doc_link( 'group_mode', false ), // td
array( 'message' => 'Choose a display mode for this group.' )
);
/**
* Grid
*/
$gridrowscols = '';
$gridrowscols .= $this->wo_meta->input( 'grid-cols', $this->wo_meta->get_value( $this->current_meta, 'grid-cols' ), 'number', array( 'display' => false ) );
$gridrowscols .= $this->wo_meta->label(
'grid-cols',
__( 'columns', 'ad-commander' ),
array(
'display' => false,
'classes' => Util::ns( 'inline' ),
)
);
$gridrowscols .= $this->wo_meta->input( 'grid-rows', $this->wo_meta->get_value( $this->current_meta, 'grid-rows' ), 'number', array( 'display' => false ) );
$gridrowscols .= $this->wo_meta->label(
'grid-rows',
__( 'rows', 'ad-commander' ),
array(
'display' => false,
'classes' => Util::ns( 'inline' ),
)
);
$gridrowscols .= '
';
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'grid-cols', __( 'Grid', 'ad-commander' ), array( 'display' => false ) ), // th
$gridrowscols,
array(
'classes' => array( Util::ns( 'mode-restrict' ), Util::ns( 'mode-restrict--grid' ) ),
'message' => __( 'Number of columns and rows to display in this grid.', 'ad-commander' ),
)
);
/**
* Refresh
*/
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'refresh', __( 'Rotate Interval', 'ad-commander' ), array( 'display' => false ) ), // th
$this->wo_meta->input( 'refresh', $this->wo_meta->get_value( $this->current_meta, 'refresh' ), 'number', array( 'display' => false ) ),
array(
'classes' => array( Util::ns( 'mode-restrict' ), Util::ns( 'mode-restrict--rotate' ) ),
'message' => __( 'Rotate ads every X seconds.', 'ad-commander' ),
)
);
/**
* Ad Order
*/
$methods = GroupTermMeta::allowed_order_methods();
if ( ! ProBridge::instance()->is_pro_loaded() ) {
$nonpro_methods = array();
foreach ( $methods as $key => $method ) {
if ( in_array( $key, ProBridge::instance()->pro_group_order_methods() ) ) {
$key = 'disabled:' . $key;
$method .= ProBridge::pro_label();
}
$nonpro_methods[ $key ] = $method;
}
$methods = $nonpro_methods;
}
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'order_method', __( 'Order Method', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->radiogroup( 'order_method', $methods, $this->wo_meta->get_value( $this->current_meta, 'order_method', 'random' ), array( 'display' => false ) ) . Doc::doc_link( 'group_order', false ),
);
/**
* Ad Label
*/
$radios = Util::site_default_options();
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'ad_label', __( 'Ad Label', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->radiogroup( 'ad_label', $radios, $this->wo_meta->get_value( $this->current_meta, 'ad_label', 'site_default' ), array( 'display' => false ) ),
);
/**
* Responsive
*/
$radios = Util::site_default_options();
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'responsive_banners', __( 'Responsive IMGs', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->radiogroup( 'responsive_banners', $radios, $this->wo_meta->get_value( $this->current_meta, 'responsive_banners', 'site_default' ), array( 'display' => false ) ),
array(
'classes' => array( Util::ns( 'field-divide' ) ),
)
);
/**
* Float
*/
$radios = Util::float_options();
$float_html = '' );
$float_html .= $this->wo_meta->radiogroup( 'float', $radios, $this->wo_meta->get_value( $this->current_meta, 'float', 'no' ), array( 'display' => false ) );
$float_html .= '
';
$float_html .= $this->wo_meta->checkbox( 'clear_float', $this->wo_meta->get_value( $this->current_meta, 'clear_float' ), 1, array( 'display' => false ) );
$float_html .= $this->wo_meta->label(
'clear_float',
__( 'Attempt to prevent text from wrapping around floated group', 'ad-commander' ),
array(
'display' => false,
'classes' => Util::ns( 'inline' ),
)
);
$float_html .= '
';
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'float', __( 'Float', 'ad-commander' ), array( 'display' => false ) ), // th
$float_html,
);
$float_html .= '
';
/**
* Margin
*/
$margin_html = '' );
foreach ( array(
'top' => __( 'top', 'ad-commander' ),
'right' => __( 'right', 'ad-commander' ),
'bottom' => __( 'bottom', 'ad-commander' ),
'left' => __( 'left', 'ad-commander' ),
) as $key => $margin ) {
$key = 'margin_' . $key;
$margin_html .= $this->wo_meta->input( $key, $this->wo_meta->get_value( $this->current_meta, $key ), 'number', array( 'display' => false ) );
$margin_html .= $this->wo_meta->label(
$key,
$margin,
array(
'display' => false,
'classes' => Util::ns( 'inline' ),
)
);
}
$margin_html .= '
';
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'margin_top', __( 'Margin', 'ad-commander' ), array( 'display' => false ) ), // th
$margin_html,
);
/**
* Custom classes
*/
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'custom_classes', __( 'Custom Classes', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->input( 'custom_classes', $this->wo_meta->get_value( $this->current_meta, 'custom_classes' ), 'text', array( 'display' => false ) ),
array(
'classes' => array( Util::ns( 'field-divide' ) ),
)
);
/**
* Custom code
*/
$this->wo_meta->term_meta_row(
Doc::doc_link( 'custom_code', false ),
'',
);
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'custom_code_before', __( 'Custom Code - Before Ads', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->textarea(
'custom_code_before',
$this->wo_meta->get_value( $this->current_meta, 'custom_code_before' ),
array(
'display' => false,
'rows' => 5,
)
),
array(
'allow_unfiltered_html' => true, // Allow scripts in this meta row.
)
);
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'custom_code_after', __( 'Custom Code - After Ads', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->textarea(
'custom_code_after',
$this->wo_meta->get_value( $this->current_meta, 'custom_code_after' ),
array(
'display' => false,
'rows' => 5,
)
),
array(
'allow_unfiltered_html' => true, // Allow scripts in this meta row.
)
);
$this->wo_meta->term_meta_row(
$this->wo_meta->label( 'disable_consent', __( 'Disable Consent', 'ad-commander' ), array( 'display' => false ) ),
$this->wo_meta->checkbox( 'disable_consent', $this->wo_meta->get_value( $this->current_meta, 'disable_consent' ), 1, array( 'display' => false ) ) .
$this->wo_meta->label( 'disable_consent', __( 'Ignore site-wide setting and disable consent requirement for this group.', 'ad-commander' ), array( 'display' => false ) )
);
}
/**
* Save posted meta data. Interfaces with WOMeta.
*
* @param int $term_id The Term ID that has saved.
*
* @return void
*/
public function update_group_meta( $term_id ) {
$group_allowed_meta = GroupTermMeta::tax_group_meta_keys();
$this->wo_meta->save_posted_term_metadata( $term_id, $group_allowed_meta, $this->nonce, AdCommander::capability() );
/**
* When term is first created in the admin UI, no meta saves because it was not posted.
* Save some required term meta for sorting purposes.
*/
$term_meta = get_term_meta( $term_id );
$no_empties = array( 'mode', 'order_method' );
foreach ( $no_empties as $no_empty ) {
$full_key = $this->wo_meta->make_key( $no_empty );
if ( ! isset( $term_meta[ $full_key ] ) && isset( $group_allowed_meta[ $no_empty ]['default'] ) ) {
update_term_meta( $term_id, $full_key, $group_allowed_meta[ $no_empty ]['default'] );
}
}
}
/**
* Output content within an individual column on the Group taxonomy page.
*
* @param string $string Column name.
* @param array $column Existing columns.
* @param int $term_id The Term ID.
*
* @return void
*/
public function manage_group_column_data( $string, $column, $term_id ) {
switch ( $column ) {
case 'mode':
$modes = Group::modes();
$key = get_term_meta( $term_id, $this->wo_meta->make_key( 'mode' ), true );
if ( ! $key ) {
$key = 'single';
}
echo ( isset( $modes[ $key ] ) ) ? esc_html( $modes[ $key ] ) : '';
break;
case 'order_method':
$order_method = get_term_meta( $term_id, $this->wo_meta->make_key( 'order_method' ), true );
echo esc_html( ucfirst( $order_method ? $order_method : 'random' ) );
break;
case 'shortcode':
self::copy_button_group_shortcode( $term_id );
break;
case 'template_tag':
self::copy_button_group_template_tag( $term_id );
break;
}
}
/**
* Update columns on the Group taxonomy page.
*
* @param array $columns The current columns.
*
* @return array
*/
public function manage_group_columns( $columns ) {
/**
* Change existing columns
*/
unset( $columns['description'] );
unset( $columns['slug'] );
$columns['posts'] = 'Ads';
/**
* Sort columns and add new
*/
$new_columns = array();
foreach ( $columns as $key => $label ) {
$new_columns[ $key ] = $label;
if ( $key === 'name' ) {
$new_columns['mode'] = __( 'Mode', 'ad-commander' );
$new_columns['order_method'] = __( 'Order Method', 'ad-commander' );
$new_columns['shortcode'] = __( 'Shortcode', 'ad-commander' );
$new_columns['template_tag'] = __( 'Template Tag', 'ad-commander' );
}
}
return $new_columns;
}
/**
* Update sortable columns on the group taxonomy page.
*
* @param array $columns The current columns.
*
* @return array
*/
public function manage_sortable_columns( $columns ) {
$columns['mode'] = 'mode';
$columns['order_method'] = 'order_method';
return $columns;
}
/**
* @param mixed $pieces
* @param mixed $taxonomies
* @param mixed $args
*
* @return [type]
*/
public function sort_group_terms( $term_query ) {
global $pagenow;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce not needed in this case
if ( ! is_admin() || $pagenow !== 'edit-tags.php' || ! isset( $_GET['taxonomy'] ) || sanitize_text_field( $_GET['taxonomy'] ) !== AdCommander::tax_group() || ! isset( $_GET['orderby'] ) ) {
return $term_query;
}
if ( ! current_user_can( AdCommander::capability() ) ) {
return $term_query;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce not needed in this case
$orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : '';
if ( $orderby ) {
$orderby_key = $this->wo_meta->make_key( $orderby );
$meta_query = array(
'relation' => 'OR',
array(
'key' => $orderby_key,
'compare' => 'NOT EXISTS',
),
array(
'key' => $orderby_key,
),
);
$term_query->meta_query = new \WP_Meta_Query( $meta_query );
$term_query->query_vars['orderby'] = 'meta_value';
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce not needed in this case
$term_query->query_vars['order'] = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'desc';
}
return $term_query;
}
}