'show_privacy_options', 'operator' => 'is', 'value' => '1' ], ]; } } } return $fields; } /** * Get fields for a specific type, optionally including global base fields. * * @param string|null $type_id * @param bool $include_global * * @return array */ public function get_fields_for_type_filtered( ?string $type_id = null, bool $include_global = false ): array { $fields = $this->get_fields_for_type( $type_id, $include_global ); /** * Filters the list of fields for a specific ad type. * * @param array $fields The list of field definitions. * @param string $type_id The ID of the ad type (e.g. 'html'). */ return apply_filters( 'adpresso_ad_type_fields', $fields, $type_id ); } /** * Registers the default fields for ads. * * @return void */ protected function load_default_fields(): void { $target_blank = (bool) Settings::get_setting( 'target_blank' ); $link_attributes = Util::get_checked_keys( Settings::get_setting( 'add_link_attributes', [] ) ); $add_sponsored = in_array( 'add_sponsored', $link_attributes, true ); $add_nofollow = in_array( 'add_nofollow', $link_attributes, true ); $current_user_id = get_current_user_id(); // UI notice: only catches __return_true/__return_false $link_masking_forced_notice = null; if ( has_filter( 'adpresso_ad_link_masking_enabled', '__return_true' ) || has_filter( 'adpresso_ad_link_masking_enabled', '__return_false' ) ) { /* translators: %s is the filter name. */ $link_masking_forced_notice = sprintf( __( 'This value is forced for all ads by the "%s" filter.', 'adpresso' ), 'adpresso_ad_link_masking_enabled' ); } $this->base_fields = apply_filters( 'adpresso/ads/fields/base', [ [ 'id' => 'ad_type', 'type' => 'image_group', 'sanitize_type' => 'key', 'label' => __( 'Ad Type', 'adpresso' ), 'description' => __( 'Choose the type of this ad.', 'adpresso' ), 'default' => 'html', 'options_callback' => [ AdTypeRegistry::get(), 'get_all_types_for_select' ], 'box' => Ad_Type_Box::class, 'controls_dependencies' => true, ], [ 'id' => 'target_url', 'type' => 'text', 'sanitize_type' => 'url', 'label' => __( 'Target URL', 'adpresso' ), 'description' => __( 'The URL where the ad should link to.', 'adpresso' ), 'box' => Ad_URL_Box::class, ], [ 'id' => 'link_masking', 'type' => 'toggle', 'label' => __( 'Link Masking', 'adpresso' ), 'description' => __( 'Whether to cloak the ad link using a custom URL.', 'adpresso' ), 'premium' => true, 'sanitize_type' => 'uint', 'default' => false, 'box' => Ad_URL_Box::class, 'notice' => $link_masking_forced_notice, ], [ 'id' => 'target_url_preview', 'type' => 'link_preview', 'label' => __( 'Preview of your URL', 'adpresso' ), 'box' => Ad_URL_Box::class, 'depends_on' => [ [ 'field_id' => 'link_masking', 'operator' => 'is', 'value' => '1' ], ], 'premium' => true, ], [ 'id' => 'linkbase_override', 'type' => 'text', 'sanitize_type' => 'text', 'label' => __( 'Override Linkbase', 'adpresso' ), 'description' => __( 'Override the global linkbase with a custom one.', 'adpresso' ), 'box' => Ad_URL_Box::class, 'depends_on' => [ [ 'field_id' => 'link_masking', 'operator' => 'is', 'value' => '1' ], ], 'premium' => true, 'placeholder' => Settings::get_setting( 'linkbase', Constants::LINK_MASKING_LINKBASE ), ], [ 'id' => 'redirect_click_tracking', 'type' => 'toggle', 'label' => __( 'Track Clicks via Redirect', 'adpresso' ), 'description' => __( 'Counts a click at the redirect itself instead of in the browser - needed for links used outside your site (e.g. newsletters), where no script runs before the click. Switching this changes how clicks for this ad are counted; numbers from before and after the switch aren\'t directly comparable.', 'adpresso' ), 'box' => Ad_URL_Box::class, 'depends_on' => [ [ 'field_id' => 'link_masking', 'operator' => 'is', 'value' => '1' ], ], 'premium' => true, 'sanitize_type' => 'uint', 'default' => false, ], [ 'id' => 'target_blank', 'type' => 'button_group', 'sanitize_type' => 'key', 'label' => __( 'Open in New Tab', 'adpresso' ), 'description' => __( 'Whether to open the ad link in a new tab.', 'adpresso' ), 'options' => [ '0' => [ 'key' => '1', 'label' => __( 'Yes', 'adpresso' ) ], '1' => [ 'key' => '0', 'label' => __( 'No', 'adpresso' ) ], /* translators: %s is the default value for target_blank from the settings. */ '2' => [ 'key' => 'default', 'label' => sprintf( __( 'Global Setting (%s)', 'adpresso' ), $target_blank ? __( 'Yes', 'adpresso' ) : __( 'No', 'adpresso' ) ) ], ], 'default' => 'default', 'box' => Ad_URL_Box::class, ], [ 'id' => 'add_nofollow', 'type' => 'button_group', 'sanitize_type' => 'key', 'label' => __( 'Add nofollow', 'adpresso' ), 'description' => __( 'Whether to add the nofollow attribute to programmatically created links.', 'adpresso' ), 'options' => [ '0' => [ 'key' => '1', 'label' => __( 'Yes', 'adpresso' ) ], '1' => [ 'key' => '0', 'label' => __( 'No', 'adpresso' ) ], /* translators: %s is the default value for adding nofollow from the settings. */ '2' => [ 'key' => 'default', 'label' => sprintf( __( 'Global Setting (%s)', 'adpresso' ), $add_nofollow ? __( 'Yes', 'adpresso' ) : __( 'No', 'adpresso' ) ) ], ], 'default' => 'default', 'box' => Ad_URL_Box::class, ], [ 'id' => 'add_sponsored', 'type' => 'button_group', 'sanitize_type' => 'key', 'label' => __( 'Add sponsored', 'adpresso' ), 'description' => __( 'Whether to add the sponsored attribute to programmatically created links.', 'adpresso' ), 'options' => [ '0' => [ 'key' => '1', 'label' => __( 'Yes', 'adpresso' ) ], '1' => [ 'key' => '0', 'label' => __( 'No', 'adpresso' ) ], /* translators: %s is the default value for adding sponsored from the settings. */ '2' => [ 'key' => 'default', 'label' => sprintf( __( 'Global Setting (%s)', 'adpresso' ), $add_sponsored ? __( 'Yes', 'adpresso' ) : __( 'No', 'adpresso' ) ) ], ], 'default' => 'default', 'box' => Ad_URL_Box::class, ], [ 'id' => 'display_only_once', 'type' => 'checkbox', 'sanitize_type' => 'uint', 'default' => 0, 'label' => __( 'Single Appearance', 'adpresso' ), 'description' => __( 'Ensures this ad is delivered only once per page.', 'adpresso' ), 'box' => Scheduling_Frequency_Box::class, 'premium' => true, ], [ 'id' => 'max_impressions_shortcut', 'type' => 'max_impressions', 'label' => __( 'Impression Limit', 'adpresso' ), 'description' => __( 'Limit how many times a visitor sees this ad within a time period.', 'adpresso' ), 'default' => [ 'enabled' => false, 'count' => 3, 'period_amount' => 1, 'period_unit' => 'day', 'cooldown_minutes' => 0 ], 'show_enabled_toggle' => true, // Scheduling_Frequency_Box::save() already writes this meta key itself before // delegating to the generic per-field loop; without a real sanitize_type the // loop's fallback (getString()) sees a non-scalar value and stomps it back to // an empty string. 'array:key' keeps the generic pass a harmless no-op re-write. 'sanitize_type' => 'array:key', 'box' => Scheduling_Frequency_Box::class, 'premium' => true, ], [ 'id' => 'margin', 'type' => 'spacing', 'label' => __( 'Margin', 'adpresso' ), 'description' => __( 'Define the ad margin in pixels.', 'adpresso' ), 'box' => Layout_Box::class, 'meta_key' => Layout_Box::META_KEY_LAYOUT, 'sanitize_type' => 'array:int', 'options' => [ 'top' => [ 'label' => _x( 'Top', 'Ad positioning spacing label', 'adpresso' ) ], 'right' => [ 'label' => _x( 'Right', 'Ad positioning spacing label', 'adpresso' ) ], 'bottom' => [ 'label' => _x( 'Bottom', 'Ad positioning spacing label', 'adpresso' ) ], 'left' => [ 'label' => _x( 'Left', 'Ad positioning spacing label', 'adpresso' ) ], ], ], [ 'id' => 'custom_id', 'type' => 'text', 'sanitize_type' => 'html_class', 'label' => __( 'Custom HTML ID', 'adpresso' ), 'description' => __( 'Set a custom HTML ID to style or control this ad using CSS or JavaScript.', 'adpresso' ), 'placeholder' => __( 'e.g., "ad-123"', 'adpresso' ), 'box' => Layout_Box::class, ], [ 'id' => 'custom_classes', 'type' => 'text', 'sanitize_type' => 'html_classes', 'label' => __( 'Custom HTML Classes', 'adpresso' ), 'description' => __( 'Add one or more custom class names to style or control this ad using CSS or JavaScript.', 'adpresso' ), 'placeholder' => __( 'e.g., "ad-123"', 'adpresso' ), 'box' => Layout_Box::class, ], [ 'id' => 'inline_css', 'type' => 'text', 'sanitize_type' => 'safe_css', 'label' => __( 'Inline CSS', 'adpresso' ), 'description' => __( 'Optional inline CSS for individual styling.', 'adpresso' ), 'placeholder' => __( 'e.g., "ad-123"', 'adpresso' ), 'box' => Layout_Box::class, ], [ 'id' => 'ignore_privacy_settings', 'label' => __( 'Ignore Privacy Settings', 'adpresso' ), 'type' => 'toggle', 'sanitize_type' => 'uint', 'default' => '0', 'box' => Ad_Content_Box::class, ], [ 'id' => 'custom_ad_code', 'type' => 'textarea', 'sanitize_type' => 'custom_code', 'label' => __( 'Custom Code', 'adpresso' ), 'placeholder' => __( 'Optional field for custom scripts or code snippets to be injected immediately after the ad unit.', 'adpresso' ), 'box' => Layout_Box::class, 'premium' => true, 'scan_for_script_lifecycle' => true, ], [ 'id' => 'label_override', 'type' => 'text', 'label' => __( 'Label override', 'adpresso' ), 'description' => __( 'Override the ad label with a custom one.', 'adpresso' ), 'link' => 'https://wpadpresso.com/docs/ad-labels/?utm_source=plugin-backend&utm_medium=manual-link&utm_campaign=ad-labels&utm_content=modal', 'box' => Layout_Box::class, 'sanitize_type' => 'text', 'placeholder' => 'e.g., "Sponsored"', ], [ 'id' => 'author', 'type' => 'token_select', 'sanitize_type' => 'int', 'label' => __( 'Author', 'adpresso' ), 'options_callback' => [ 'rest_endpoint' => 'adpresso/v1/filter-options/authors' ], 'default' => $current_user_id, 'isSingle' => true, 'box' => Ad_Content_Box::class, ], [ 'id' => 'assignments', 'type' => 'assignment', 'sanitize_type' => 'array:int', 'label' => __( 'Assignment', 'adpresso' ), 'options' => [ ], 'box' => Ad_Assignment_Box::class, ], [ 'id' => 'scheduling_enabled', 'type' => 'toggle', 'label' => __( 'Show Scheduling Options', 'adpresso' ), 'description' => __( 'Limit this ad to an active period, specific weekdays, and/or specific hours of the day.', 'adpresso' ), 'sanitize_type' => 'uint', 'default' => 0, 'box' => Scheduling_Frequency_Box::class, ], [ 'id' => 'schedule_period', 'type' => 'schedule_period', 'sanitize_type' => 'none', 'label' => __( 'Set the active period for this ad', 'adpresso' ), 'box' => Scheduling_Frequency_Box::class, 'depends_on' => [ [ 'field_id' => 'scheduling_enabled', 'operator' => 'is', 'value' => '1' ], ], ], [ 'id' => 'schedule_days', 'type' => 'checkbox_button_group', 'sanitize_type' => 'array:key', 'label' => __( 'Schedule for specific days of the week', 'adpresso' ), 'options' => [ '0' => [ 'label' => __( 'Mon', 'adpresso' ), 'key' => 'mon', 'className' => 'adpresso-color-primary' ], '1' => [ 'label' => __( 'Tue', 'adpresso' ), 'key' => 'tue', 'className' => 'adpresso-color-primary' ], '2' => [ 'label' => __( 'Wed', 'adpresso' ), 'key' => 'wed', 'className' => 'adpresso-color-primary' ], '3' => [ 'label' => __( 'Thu', 'adpresso' ), 'key' => 'thu', 'className' => 'adpresso-color-primary' ], '4' => [ 'label' => __( 'Fri', 'adpresso' ), 'key' => 'fri', 'className' => 'adpresso-color-primary' ], '5' => [ 'label' => __( 'Sat', 'adpresso' ), 'key' => 'sat', 'className' => 'adpresso-color-primary' ], '6' => [ 'label' => __( 'Sun', 'adpresso' ), 'key' => 'sun', 'className' => 'adpresso-color-primary' ], ], 'default' => [ 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun' ], 'box' => Scheduling_Frequency_Box::class, 'premium' => true, 'depends_on' => [ [ 'field_id' => 'scheduling_enabled', 'operator' => 'is', 'value' => '1' ], ], ], [ 'id' => 'schedule_time', 'type' => 'schedule_time', 'sanitize_type' => 'none', 'label' => __( 'Schedule for specific hours of the day', 'adpresso' ), 'box' => Scheduling_Frequency_Box::class, 'premium' => true, 'depends_on' => [ [ 'field_id' => 'scheduling_enabled', 'operator' => 'is', 'value' => '1' ], ], ], ] ); } }