initialize( $channel )->write_log( $message, $level ); } /** * Dump the content in the screen. * * @param mixed $var Content. * @param bool $exit Exit. * * @return void */ public static function dump( $var, bool $exit = false ) { echo '
';

		if ( is_array( $var ) || is_object( $var ) ) {
			echo esc_html( print_r( $var, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.debugging_print_r
		} elseif ( is_string( $var ) ) {
			echo esc_html( 'string(' . strlen( $var ) . ') "' . $var . "\";\n" );
		} else {
			ob_start();
			var_dump( $var ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.debugging_var_dump
			echo esc_html( ob_get_clean() );
		}

		echo "\n
"; if ( $exit ) { exit; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } /** * Menu Page URL. * * @param string $page_slug Page Slug. * @param array $parameters Parameter. * * @return string */ public static function menu_page_url( string $page_slug, array $parameters = array() ): string { if ( is_array( $parameters ) && count( $parameters ) ) { return admin_url( '/admin.php?page=' . $page_slug ) . '&' . http_build_query( $parameters ); } return admin_url( '/admin.php?page=' . $page_slug ); } /** * Encrypt a String. * * @param string $string String. * * @return string */ public static function encrypt( string $string ): string { $secret_key = wp_create_nonce(); $secret_iv = self::generate_secret(); $encrypt_method = 'AES-128-CBC'; $key = hash( 'sha256', $secret_key ); $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 ); return base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) ); } /** * Generate Secret. * * @return mixed */ public static function generate_secret() { $session = sanitize_text_field( $_SESSION ); if ( ! empty( $session['adfuz_secret'] ) ) { return $session['adfuz_secret']; } $session['adfuz_secret'] = self::get_random_string( 5 ); return $session['adfuz_secret']; } /** * Sanitize Text Field * * @param mixed $var Variable. * * @return mixed */ public static function sanitize_text_field( $var ) { if ( is_array( $var ) ) { return array_map( array( 'self', 'sanitize_text_field' ), $var ); } return is_scalar( $var ) ? \sanitize_text_field( $var ) : $var; } /** * Get Random String. * * @param int $length Length. * * @return string */ public static function get_random_string( int $length = 10 ): string { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $characters_length = strlen( $characters ); $random_string = ''; for ( $i = 0; $i < $length; $i++ ) { $random_string .= $characters[ wp_rand( 0, $characters_length - 1 ) ]; } return $random_string; } /** * Decrypt a String. * * @param string $string String. * * @return false|string */ public static function decrypt( $string ) { $secret_key = wp_create_nonce(); $secret_iv = self::generate_secret(); $encrypt_method = 'AES-128-CBC'; $key = hash( 'sha256', $secret_key ); $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 ); return openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv ); } /** * Verify Nonce. * * @param mixed $request Request. * * @return void */ public static function verifyNonce( $request = null, $permission = null ): void { if ( null === $request ) { $request = isset( $_REQUEST ) ? wp_unslash( $_REQUEST ) : array(); } $nonce_key = 'adfuz_nonce'; $nonce_raw = $request[ $nonce_key ] ?? null; if ( empty( $nonce_raw ) ) { self::handle_failure( __( 'Invalid Request - 700', 'ad-fuz' ) ); } // WordPress requires this specific combination before wp_verify_nonce. if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $nonce_raw ) ), $nonce_key ) ) { self::handle_failure( __( 'Invalid Request - 701', 'ad-fuz' ) ); } } /** * Check Capability. * * @param string $capability Capability. * * @return void */ public static function checkCapability( $capabilities = array( 'manage_options' ) ) { $capabilities = (array) $capabilities; foreach ( $capabilities as $capability ) { if ( current_user_can( $capability ) ) { return $capability; } } self::handle_failure( __( 'You do not have permission to perform this action.', 'ad-fuz' ) ); } /** * Get array value by path. * * @param array $array Array value. * @param string $path Array path. * * @return mixed|null */ protected static function get_array_value_by_path( $array, $path ) { $keys = explode( '.', $path ); foreach ( $keys as $key ) { if ( ! is_array( $array ) || ! array_key_exists( $key, $array ) ) { return null; } $array = $array[ $key ]; } return $array; } /** * Handle Nonce Failure. * * @param string $message Message. * * @return void */ protected static function handle_failure( $message ) { if ( wp_doing_ajax() ) { wp_send_json_error( array( 'message' => esc_html( $message ) ) ); } else { wp_die( esc_html( $message ) ); } } /** * Set value to Array. * * @param mixed $target Target. * @param mixed $key Key. * @param mixed $value Value. * @param bool $overwrite Overwrite. * * @return array|mixed */ public static function set( array &$target, $key, $value, bool $overwrite = true ) { $segments = is_array( $key ) ? $key : explode( '.', $key ); $segment = array_shift( $segments ); if ( $segment === '*' ) { if ( ! self::accessible( $target ) ) { $target = array(); } if ( $segments ) { foreach ( $target as &$inner ) { set( $inner, $segments, $value, $overwrite ); } } elseif ( $overwrite ) { foreach ( $target as &$inner ) { $inner = $value; } } } elseif ( self::accessible( $target ) ) { if ( $segments ) { if ( ! self::exists( $target, $segment ) ) { $target[ $segment ] = array(); } set( $target[ $segment ], $segments, $value, $overwrite ); } elseif ( $overwrite || ! self::exists( $target, $segment ) ) { $target[ $segment ] = $value; } } elseif ( is_object( $target ) ) { if ( $segments ) { if ( ! isset( $target->{$segment} ) ) { $target->{$segment} = array(); } set( $target->{$segment}, $segments, $value, $overwrite ); } elseif ( $overwrite || ! isset( $target->{$segment} ) ) { $target->{$segment} = $value; } } else { $target = array(); if ( $segments ) { set( $target[ $segment ], $segments, $value, $overwrite ); } elseif ( $overwrite ) { $target[ $segment ] = $value; } } return $target; } /** * Accessible. * * @param mixed $value Value. * * @return bool */ public static function accessible( $value ): bool { return is_array( $value ) || $value instanceof ArrayAccess; } /** * Exists or not. * * @param mixed $array Array. * @param mixed $key Key. * * @return bool */ public static function exists( $array, $key ): bool { if ( $array instanceof ArrayAccess ) { return $array->offsetExists( $key ); } return array_key_exists( $key, $array ); } /** * Convert Array to String. * * @param array $data Data. * @param string $prefix Prefix. * * @return string */ public static function array_to_string( $data, $prefix = '' ): string { $dataAttribute = ''; foreach ( $data as $key => $value ) { $escapedKey = htmlspecialchars( $key, ENT_QUOTES, 'UTF-8' ); $escapedValue = htmlspecialchars( $value, ENT_QUOTES, 'UTF-8' ); $dataAttribute .= $prefix . "$escapedKey='$escapedValue' "; } return $dataAttribute; } public static function with_html_attr( $find, $data, $attr = '', $append = '' ): string { $value = self::get( $find, $data, '' ); if ( empty( $attr ) ) { $parts = explode( '.', $find ); $attr = end( $parts ); } if ( ! empty( $append ) ) { $value .= ' ' . $append; } return ! empty( $value ) ? $attr . '="' . $value . '"' : ''; } /** * Get Value. * * @param string $key Key. * @param mixed $target Target. * @param string|null|array $default Default. * @param bool $sanitize Sanitize. * * @return array|\Closure|mixed|string|null */ public static function get( string $key, $target = null, $default = null, bool $sanitize = true ) { if ( $target === null && ! isset( $_REQUEST ) ) { return $default; } if ( null === $target ) { // Route through Request::input() so sanitization is applied correctly. // Direct $_REQUEST access is intentionally avoided here. $request = Request::get_instance(); $parts = explode( '.', $key ); $first = array_shift( $parts ); $value = $request->input( $first, 'request', $default ); if ( empty( $parts ) ) { return $value; } $target = $value; } foreach ( explode( '.', $key ) as $segment ) { if ( is_array( $target ) ) { if ( ! array_key_exists( $segment, $target ) ) { return self::get_value( $default, $sanitize ); } $target = $target[ $segment ]; } elseif ( $target instanceof ArrayAccess ) { if ( ! isset( $target[ $segment ] ) ) { return self::get_value( $default, $sanitize ); } $target = $target[ $segment ]; } elseif ( is_object( $target ) ) { if ( ! isset( $target->{$segment} ) ) { return self::get_value( $default, $sanitize ); } $target = $target->{$segment}; } else { return self::get_value( $default, $sanitize ); } } return self::get_value( $target, $sanitize ); } /** * Get Value. * * @param \Closure | array | string $value Value. * @param bool $sanitize Sanitize. * * @return mixed */ public static function get_value( $value, bool $sanitize = true ) { return ( $value instanceof Closure ) ? $value() : ( $sanitize ? sanitize_text_field( $value ) : $value ); } public static function devices( $device_id = null ) { $devices = array( 'mobile' => 'Mobile', 'tablet' => 'Tablet', 'desktop' => 'Desktop', 'laptop' => 'Laptop', 'smarttv' => 'Smart TV', ); return $device_id ? ( $devices[ $device_id ] ?? '' ) : $devices; } public static function ad_sequence( $sequence_id = null ) { $sequences = array( 'random' => 'Random Order', 'sequential' => 'Sequential Order', 'priority' => 'Priority Order', ); $sequences = apply_filters( 'adfuz/ads/ad_sequence/sequence', $sequences ); return $sequence_id ? ( $sequences[ $sequence_id ] ?? '' ) : $sequences; } public static function currency( $currency_id = null ) { $currency_list = array( 'ALL' => array( 'name' => 'Albanian Lek', 'symbol' => 'Lek', ), 'DZD' => array( 'name' => 'Algerian Dinar', 'symbol' => 'دج', ), 'AOA' => array( 'name' => 'Angolan Kwanza', 'symbol' => 'Kz', ), 'ARS' => array( 'name' => 'Argentine Peso', 'symbol' => '$', ), 'AMD' => array( 'name' => 'Armenian Dram', 'symbol' => '֏', ), 'AWG' => array( 'name' => 'Aruban Florin', 'symbol' => 'ƒ', ), 'AUD' => array( 'name' => 'Australian Dollar', 'symbol' => '$', ), 'AZN' => array( 'name' => 'Azerbaijani Manat', 'symbol' => 'm', ), 'BSD' => array( 'name' => 'Bahamian Dollar', 'symbol' => 'B$', ), 'BHD' => array( 'name' => 'Bahraini Dinar', 'symbol' => '.د.ب', ), 'BDT' => array( 'name' => 'Bangladeshi Taka', 'symbol' => '৳', ), 'BBD' => array( 'name' => 'Barbadian Dollar', 'symbol' => 'Bds$', ), 'BYR' => array( 'name' => 'Belarusian Ruble', 'symbol' => 'Br', ), 'BEF' => array( 'name' => 'Belgian Franc', 'symbol' => 'fr', ), 'BZD' => array( 'name' => 'Belize Dollar', 'symbol' => '$', ), 'BMD' => array( 'name' => 'Bermudan Dollar', 'symbol' => '$', ), 'BTN' => array( 'name' => 'Bhutanese Ngultrum', 'symbol' => 'Nu.', ), 'BTC' => array( 'name' => 'Bitcoin', 'symbol' => '฿', ), 'BOB' => array( 'name' => 'Bolivian Boliviano', 'symbol' => 'Bs.', ), 'BAM' => array( 'name' => 'Bosnia', 'symbol' => 'KM', ), 'BWP' => array( 'name' => 'Botswanan Pula', 'symbol' => 'P', ), 'BRL' => array( 'name' => 'Brazilian Real', 'symbol' => 'R$', ), 'GBP' => array( 'name' => 'British Pound Sterling', 'symbol' => '£', ), 'BND' => array( 'name' => 'Brunei Dollar', 'symbol' => 'B$', ), 'BGN' => array( 'name' => 'Bulgarian Lev', 'symbol' => 'Лв.', ), 'BIF' => array( 'name' => 'Burundian Franc', 'symbol' => 'FBu', ), 'KHR' => array( 'name' => 'Cambodian Riel', 'symbol' => 'KHR', ), 'CAD' => array( 'name' => 'Canadian Dollar', 'symbol' => '$', ), 'CVE' => array( 'name' => 'Cape Verdean Escudo', 'symbol' => '$', ), 'KYD' => array( 'name' => 'Cayman Islands Dollar', 'symbol' => '$', ), 'XOF' => array( 'name' => 'CFA Franc BCEAO', 'symbol' => 'CFA', ), 'XAF' => array( 'name' => 'CFA Franc BEAC', 'symbol' => 'FCFA', ), 'XPF' => array( 'name' => 'CFP Franc', 'symbol' => '₣', ), 'CLP' => array( 'name' => 'Chilean Peso', 'symbol' => '$', ), 'CLF' => array( 'name' => 'Chilean Unit of Account', 'symbol' => 'CLF', ), 'CNY' => array( 'name' => 'Chinese Yuan', 'symbol' => '¥', ), 'COP' => array( 'name' => 'Colombian Peso', 'symbol' => '$', ), 'KMF' => array( 'name' => 'Comorian Franc', 'symbol' => 'CF', ), 'CDF' => array( 'name' => 'Congolese Franc', 'symbol' => 'FC', ), 'CRC' => array( 'name' => 'Costa Rican Colón', 'symbol' => '₡', ), 'HRK' => array( 'name' => 'Croatian Kuna', 'symbol' => 'kn', ), 'CUC' => array( 'name' => 'Cuban Convertible Peso', 'symbol' => '$, CUC', ), 'CZK' => array( 'name' => 'Czech Republic Koruna', 'symbol' => 'Kč', ), 'DKK' => array( 'name' => 'Danish Krone', 'symbol' => 'Kr.', ), 'DJF' => array( 'name' => 'Djiboutian Franc', 'symbol' => 'Fdj', ), 'DOP' => array( 'name' => 'Dominican Peso', 'symbol' => '$', ), 'XCD' => array( 'name' => 'East Caribbean Dollar', 'symbol' => '$', ), 'EGP' => array( 'name' => 'Egyptian Pound', 'symbol' => 'ج.م', ), 'ERN' => array( 'name' => 'Eritrean Nakfa', 'symbol' => 'Nfk', ), 'EEK' => array( 'name' => 'Estonian Kroon', 'symbol' => 'kr', ), 'ETB' => array( 'name' => 'Ethiopian Birr', 'symbol' => 'Nkf', ), 'EUR' => array( 'name' => 'Euro', 'symbol' => '€', ), 'FKP' => array( 'name' => 'Falkland Islands Pound', 'symbol' => '£', ), 'FJD' => array( 'name' => 'Fijian Dollar', 'symbol' => 'FJ$', ), 'GMD' => array( 'name' => 'Gambian Dalasi', 'symbol' => 'D', ), 'GEL' => array( 'name' => 'Georgian Lari', 'symbol' => 'ლ', ), 'DEM' => array( 'name' => 'German Mark', 'symbol' => 'DM', ), 'GHS' => array( 'name' => 'Ghanaian Cedi', 'symbol' => 'GH₵', ), 'GIP' => array( 'name' => 'Gibraltar Pound', 'symbol' => '£', ), 'GRD' => array( 'name' => 'Greek Drachma', 'symbol' => '₯, Δρχ, Δρ', ), 'GTQ' => array( 'name' => 'Guatemalan Quetzal', 'symbol' => 'Q', ), 'GNF' => array( 'name' => 'Guinean Franc', 'symbol' => 'FG', ), 'GYD' => array( 'name' => 'Guyanaese Dollar', 'symbol' => '$', ), 'HTG' => array( 'name' => 'Haitian Gourde', 'symbol' => 'G', ), 'HNL' => array( 'name' => 'Honduran Lempira', 'symbol' => 'L', ), 'HKD' => array( 'name' => 'Hong Kong Dollar', 'symbol' => '$', ), 'HUF' => array( 'name' => 'Hungarian Forint', 'symbol' => 'Ft', ), 'ISK' => array( 'name' => 'Icelandic Króna', 'symbol' => 'kr', ), 'INR' => array( 'name' => 'Indian Rupee', 'symbol' => '₹', ), 'IDR' => array( 'name' => 'Indonesian Rupiah', 'symbol' => 'Rp', ), 'IRR' => array( 'name' => 'Iranian Rial', 'symbol' => '﷼', ), 'IQD' => array( 'name' => 'Iraqi Dinar', 'symbol' => 'د.ع', ), 'ILS' => array( 'name' => 'Israeli New Sheqel', 'symbol' => '₪', ), 'ITL' => array( 'name' => 'Italian Lira', 'symbol' => 'L,£', ), 'JMD' => array( 'name' => 'Jamaican Dollar', 'symbol' => 'J$', ), 'JPY' => array( 'name' => 'Japanese Yen', 'symbol' => '¥', ), 'JOD' => array( 'name' => 'Jordanian Dinar', 'symbol' => 'ا.د', ), 'KZT' => array( 'name' => 'Kazakhstani Tenge', 'symbol' => 'лв', ), 'KES' => array( 'name' => 'Kenyan Shilling', 'symbol' => 'KSh', ), 'KWD' => array( 'name' => 'Kuwaiti Dinar', 'symbol' => 'ك.د', ), 'KGS' => array( 'name' => 'Kyrgystani Som', 'symbol' => 'лв', ), 'LAK' => array( 'name' => 'Laotian Kip', 'symbol' => '₭', ), 'LVL' => array( 'name' => 'Latvian Lats', 'symbol' => 'Ls', ), 'LBP' => array( 'name' => 'Lebanese Pound', 'symbol' => '£', ), 'LSL' => array( 'name' => 'Lesotho Loti', 'symbol' => 'L', ), 'LRD' => array( 'name' => 'Liberian Dollar', 'symbol' => '$', ), 'LYD' => array( 'name' => 'Libyan Dinar', 'symbol' => 'د.ل', ), 'LTC' => array( 'name' => 'Litecoin', 'symbol' => 'Ł', ), 'LTL' => array( 'name' => 'Lithuanian Litas', 'symbol' => 'Lt', ), 'MOP' => array( 'name' => 'Macanese Pataca', 'symbol' => '$', ), 'MKD' => array( 'name' => 'Macedonian Denar', 'symbol' => 'ден', ), 'MGA' => array( 'name' => 'Malagasy Ariary', 'symbol' => 'Ar', ), 'MWK' => array( 'name' => 'Malawian Kwacha', 'symbol' => 'MK', ), 'MYR' => array( 'name' => 'Malaysian Ringgit', 'symbol' => 'RM', ), 'MVR' => array( 'name' => 'Maldivian Rufiyaa', 'symbol' => 'Rf', ), 'MRO' => array( 'name' => 'Mauritanian Ouguiya', 'symbol' => 'MRU', ), 'MUR' => array( 'name' => 'Mauritian Rupee', 'symbol' => '₨', ), 'MXN' => array( 'name' => 'Mexican Peso', 'symbol' => '$', ), 'MDL' => array( 'name' => 'Moldovan Leu', 'symbol' => 'L', ), 'MNT' => array( 'name' => 'Mongolian Tugrik', 'symbol' => '₮', ), 'MAD' => array( 'name' => 'Moroccan Dirham', 'symbol' => 'MAD', ), 'MZM' => array( 'name' => 'Mozambican Metical', 'symbol' => 'MT', ), 'MMK' => array( 'name' => 'Myanmar Kyat', 'symbol' => 'K', ), 'NAD' => array( 'name' => 'Namibian Dollar', 'symbol' => '$', ), 'NPR' => array( 'name' => 'Nepalese Rupee', 'symbol' => '₨', ), 'ANG' => array( 'name' => 'Netherlands Antillean Guilder', 'symbol' => 'ƒ', ), 'TWD' => array( 'name' => 'New Taiwan Dollar', 'symbol' => '$', ), 'NZD' => array( 'name' => 'New Zealand Dollar', 'symbol' => '$', ), 'NIO' => array( 'name' => 'Nicaraguan Córdoba', 'symbol' => 'C$', ), 'NGN' => array( 'name' => 'Nigerian Naira', 'symbol' => '₦', ), 'KPW' => array( 'name' => 'North Korean Won', 'symbol' => '₩', ), 'NOK' => array( 'name' => 'Norwegian Krone', 'symbol' => 'kr', ), 'OMR' => array( 'name' => 'Omani Rial', 'symbol' => '.ع.ر', ), 'PKR' => array( 'name' => 'Pakistani Rupee', 'symbol' => '₨', ), 'PAB' => array( 'name' => 'Panamanian Balboa', 'symbol' => 'B/.', ), 'PGK' => array( 'name' => 'Papua New Guinean Kina', 'symbol' => 'K', ), 'PYG' => array( 'name' => 'Paraguayan Guarani', 'symbol' => '₲', ), 'PEN' => array( 'name' => 'Peruvian Nuevo Sol', 'symbol' => 'S/.', ), 'PHP' => array( 'name' => 'Philippine Peso', 'symbol' => '₱', ), 'PLN' => array( 'name' => 'Polish Zloty', 'symbol' => 'zł', ), 'QAR' => array( 'name' => 'Qatari Rial', 'symbol' => 'ق.ر', ), 'RON' => array( 'name' => 'Romanian Leu', 'symbol' => 'lei', ), 'RUB' => array( 'name' => 'Russian Ruble', 'symbol' => '₽', ), 'RWF' => array( 'name' => 'Rwandan Franc', 'symbol' => 'FRw', ), 'SVC' => array( 'name' => 'Salvadoran Colón', 'symbol' => '₡', ), 'WST' => array( 'name' => 'Samoan Tala', 'symbol' => 'SAT', ), 'STD' => array( 'name' => 'São Tomé and Príncipe Dobra', 'symbol' => 'Db', ), 'SAR' => array( 'name' => 'Saudi Riyal', 'symbol' => '﷼', ), 'RSD' => array( 'name' => 'Serbian Dinar', 'symbol' => 'din', ), 'SCR' => array( 'name' => 'Seychellois Rupee', 'symbol' => 'SRe', ), 'SLL' => array( 'name' => 'Sierra Leonean Leone', 'symbol' => 'Le', ), 'SGD' => array( 'name' => 'Singapore Dollar', 'symbol' => '$', ), 'SKK' => array( 'name' => 'Slovak Koruna', 'symbol' => 'Sk', ), 'SBD' => array( 'name' => 'Solomon Islands Dollar', 'symbol' => 'Si$', ), 'SOS' => array( 'name' => 'Somali Shilling', 'symbol' => 'Sh.so.', ), 'ZAR' => array( 'name' => 'South African Rand', 'symbol' => 'R', ), 'KRW' => array( 'name' => 'South Korean Won', 'symbol' => '₩', ), 'SSP' => array( 'name' => 'South Sudanese Pound', 'symbol' => '£', ), 'XDR' => array( 'name' => 'Special Drawing Rights', 'symbol' => 'SDR', ), 'LKR' => array( 'name' => 'Sri Lankan Rupee', 'symbol' => 'Rs', ), 'SHP' => array( 'name' => 'St. Helena Pound', 'symbol' => '£', ), 'SDG' => array( 'name' => 'Sudanese Pound', 'symbol' => '.س.ج', ), 'SRD' => array( 'name' => 'Surinamese Dollar', 'symbol' => '$', ), 'SZL' => array( 'name' => 'Swazi Lilangeni', 'symbol' => 'E', ), 'SEK' => array( 'name' => 'Swedish Krona', 'symbol' => 'kr', ), 'CHF' => array( 'name' => 'Swiss Franc', 'symbol' => 'CHf', ), 'SYP' => array( 'name' => 'Syrian Pound', 'symbol' => 'LS', ), 'TJS' => array( 'name' => 'Tajikistani Somoni', 'symbol' => 'SM', ), 'TZS' => array( 'name' => 'Tanzanian Shilling', 'symbol' => 'TSh', ), 'THB' => array( 'name' => 'Thai Baht', 'symbol' => '฿', ), 'TOP' => array( 'name' => "Tongan Pa'anga", 'symbol' => '$', ), 'TTD' => array( 'name' => 'Trinidad & Tobago Dollar', 'symbol' => '$', ), 'TND' => array( 'name' => 'Tunisian Dinar', 'symbol' => 'ت.د', ), 'TRY' => array( 'name' => 'Turkish Lira', 'symbol' => '₺', ), 'TMT' => array( 'name' => 'Turkmenistani Manat', 'symbol' => 'T', ), 'UGX' => array( 'name' => 'Ugandan Shilling', 'symbol' => 'USh', ), 'UAH' => array( 'name' => 'Ukrainian Hryvnia', 'symbol' => '₴', ), 'AED' => array( 'name' => 'United Arab Emirates Dirham', 'symbol' => 'إ.د', ), 'UYU' => array( 'name' => 'Uruguayan Peso', 'symbol' => '$', ), 'USD' => array( 'name' => 'US Dollar', 'symbol' => '$', ), 'UZS' => array( 'name' => 'Uzbekistan Som', 'symbol' => 'лв', ), 'VUV' => array( 'name' => 'Vanuatu Vatu', 'symbol' => 'VT', ), 'VEF' => array( 'name' => 'Venezuelan BolÃvar', 'symbol' => 'Bs', ), 'VND' => array( 'name' => 'Vietnamese Dong', 'symbol' => '₫', ), 'YER' => array( 'name' => 'Yemeni Rial', 'symbol' => '﷼', ), 'ZMK' => array( 'name' => 'Zambian Kwacha', 'symbol' => 'ZK', ), ); return $currency_id ? ( $currency_list[ $currency_id ] ?? '' ) : $currency_list; } public static function countries( $country_code = null ) { $countries = array( 'AF' => array( 'name' => 'Afghanistan', 'continent' => 'Asia', ), 'AX' => array( 'name' => 'Åland Islands', 'continent' => 'Europe', ), 'AL' => array( 'name' => 'Albania', 'continent' => 'Europe', ), 'DZ' => array( 'name' => 'Algeria', 'continent' => 'Africa', ), 'AS' => array( 'name' => 'American Samoa', 'continent' => 'Oceania', ), 'AD' => array( 'name' => 'Andorra', 'continent' => 'Europe', ), 'AO' => array( 'name' => 'Angola', 'continent' => 'Africa', ), 'AI' => array( 'name' => 'Anguilla', 'continent' => 'North America', ), 'AQ' => array( 'name' => 'Antarctica', 'continent' => 'Antarctica', ), 'AG' => array( 'name' => 'Antigua and Barbuda', 'continent' => 'North America', ), 'AR' => array( 'name' => 'Argentina', 'continent' => 'South America', ), 'AM' => array( 'name' => 'Armenia', 'continent' => 'Asia', ), 'AW' => array( 'name' => 'Aruba', 'continent' => 'North America', ), 'AU' => array( 'name' => 'Australia', 'continent' => 'Oceania', ), 'AT' => array( 'name' => 'Austria', 'continent' => 'Europe', ), 'AZ' => array( 'name' => 'Azerbaijan', 'continent' => 'Asia', ), 'BS' => array( 'name' => 'Bahamas', 'continent' => 'North America', ), 'BH' => array( 'name' => 'Bahrain', 'continent' => 'Asia', ), 'BD' => array( 'name' => 'Bangladesh', 'continent' => 'Asia', ), 'BB' => array( 'name' => 'Barbados', 'continent' => 'North America', ), 'BY' => array( 'name' => 'Belarus', 'continent' => 'Europe', ), 'BE' => array( 'name' => 'Belgium', 'continent' => 'Europe', ), 'BZ' => array( 'name' => 'Belize', 'continent' => 'North America', ), 'BJ' => array( 'name' => 'Benin', 'continent' => 'Africa', ), 'BM' => array( 'name' => 'Bermuda', 'continent' => 'North America', ), 'BT' => array( 'name' => 'Bhutan', 'continent' => 'Asia', ), 'BO' => array( 'name' => 'Bolivia', 'continent' => 'South America', ), 'BA' => array( 'name' => 'Bosnia and Herzegovina', 'continent' => 'Europe', ), 'BW' => array( 'name' => 'Botswana', 'continent' => 'Africa', ), 'BV' => array( 'name' => 'Bouvet Island', 'continent' => 'Antarctica', ), 'BR' => array( 'name' => 'Brazil', 'continent' => 'South America', ), 'IO' => array( 'name' => 'British Indian Ocean Territory', 'continent' => 'Asia', ), 'BN' => array( 'name' => 'Brunei Darussalam', 'continent' => 'Asia', ), 'BG' => array( 'name' => 'Bulgaria', 'continent' => 'Europe', ), 'BF' => array( 'name' => 'Burkina Faso', 'continent' => 'Africa', ), 'BI' => array( 'name' => 'Burundi', 'continent' => 'Africa', ), 'KH' => array( 'name' => 'Cambodia', 'continent' => 'Asia', ), 'CM' => array( 'name' => 'Cameroon', 'continent' => 'Africa', ), 'CA' => array( 'name' => 'Canada', 'continent' => 'North America', ), 'CV' => array( 'name' => 'Cape Verde', 'continent' => 'Africa', ), 'KY' => array( 'name' => 'Cayman Islands', 'continent' => 'North America', ), 'CF' => array( 'name' => 'Central African Republic', 'continent' => 'Africa', ), 'TD' => array( 'name' => 'Chad', 'continent' => 'Africa', ), 'CL' => array( 'name' => 'Chile', 'continent' => 'South America', ), 'CN' => array( 'name' => 'China', 'continent' => 'Asia', ), 'CX' => array( 'name' => 'Christmas Island', 'continent' => 'Asia', ), 'CC' => array( 'name' => 'Cocos (Keeling] Islands', 'continent' => 'Asia', ), 'CO' => array( 'name' => 'Colombia', 'continent' => 'South America', ), 'KM' => array( 'name' => 'Comoros', 'continent' => 'Africa', ), 'CG' => array( 'name' => 'Congo', 'continent' => 'Africa', ), 'CD' => array( 'name' => 'The Democratic Republic of The Congo', 'continent' => 'Africa', ), 'CK' => array( 'name' => 'Cook Islands', 'continent' => 'Oceania', ), 'CR' => array( 'name' => 'Costa Rica', 'continent' => 'North America', ), 'CI' => array( 'name' => "Cote D'ivoire", 'continent' => 'Africa', ), 'HR' => array( 'name' => 'Croatia', 'continent' => 'Europe', ), 'CU' => array( 'name' => 'Cuba', 'continent' => 'North America', ), 'CY' => array( 'name' => 'Cyprus', 'continent' => 'Asia', ), 'CZ' => array( 'name' => 'Czech Republic', 'continent' => 'Europe', ), 'DK' => array( 'name' => 'Denmark', 'continent' => 'Europe', ), 'DJ' => array( 'name' => 'Djibouti', 'continent' => 'Africa', ), 'DM' => array( 'name' => 'Dominica', 'continent' => 'North America', ), 'DO' => array( 'name' => 'Dominican Republic', 'continent' => 'North America', ), 'EC' => array( 'name' => 'Ecuador', 'continent' => 'South America', ), 'EG' => array( 'name' => 'Egypt', 'continent' => 'Africa', ), 'SV' => array( 'name' => 'El Salvador', 'continent' => 'North America', ), 'GQ' => array( 'name' => 'Equatorial Guinea', 'continent' => 'Africa', ), 'ER' => array( 'name' => 'Eritrea', 'continent' => 'Africa', ), 'EE' => array( 'name' => 'Estonia', 'continent' => 'Europe', ), 'ET' => array( 'name' => 'Ethiopia', 'continent' => 'Africa', ), 'FK' => array( 'name' => 'Falkland Islands (Malvinas]', 'continent' => 'South America', ), 'FO' => array( 'name' => 'Faroe Islands', 'continent' => 'Europe', ), 'FJ' => array( 'name' => 'Fiji', 'continent' => 'Oceania', ), 'FI' => array( 'name' => 'Finland', 'continent' => 'Europe', ), 'FR' => array( 'name' => 'France', 'continent' => 'Europe', ), 'GF' => array( 'name' => 'French Guiana', 'continent' => 'South America', ), 'PF' => array( 'name' => 'French Polynesia', 'continent' => 'Oceania', ), 'TF' => array( 'name' => 'French Southern Territories', 'continent' => 'Antarctica', ), 'GA' => array( 'name' => 'Gabon', 'continent' => 'Africa', ), 'GM' => array( 'name' => 'Gambia', 'continent' => 'Africa', ), 'GE' => array( 'name' => 'Georgia', 'continent' => 'Asia', ), 'DE' => array( 'name' => 'Germany', 'continent' => 'Europe', ), 'GH' => array( 'name' => 'Ghana', 'continent' => 'Africa', ), 'GI' => array( 'name' => 'Gibraltar', 'continent' => 'Europe', ), 'GR' => array( 'name' => 'Greece', 'continent' => 'Europe', ), 'GL' => array( 'name' => 'Greenland', 'continent' => 'North America', ), 'GD' => array( 'name' => 'Grenada', 'continent' => 'North America', ), 'GP' => array( 'name' => 'Guadeloupe', 'continent' => 'North America', ), 'GU' => array( 'name' => 'Guam', 'continent' => 'Oceania', ), 'GT' => array( 'name' => 'Guatemala', 'continent' => 'North America', ), 'GG' => array( 'name' => 'Guernsey', 'continent' => 'Europe', ), 'GN' => array( 'name' => 'Guinea', 'continent' => 'Africa', ), 'GW' => array( 'name' => 'Guinea-bissau', 'continent' => 'Africa', ), 'GY' => array( 'name' => 'Guyana', 'continent' => 'South America', ), 'HT' => array( 'name' => 'Haiti', 'continent' => 'North America', ), 'HM' => array( 'name' => 'Heard Island and Mcdonald Islands', 'continent' => 'Antarctica', ), 'VA' => array( 'name' => 'Holy See (Vatican City State]', 'continent' => 'Europe', ), 'HN' => array( 'name' => 'Honduras', 'continent' => 'North America', ), 'HK' => array( 'name' => 'Hong Kong', 'continent' => 'Asia', ), 'HU' => array( 'name' => 'Hungary', 'continent' => 'Europe', ), 'IS' => array( 'name' => 'Iceland', 'continent' => 'Europe', ), 'IN' => array( 'name' => 'India', 'continent' => 'Asia', ), 'ID' => array( 'name' => 'Indonesia', 'continent' => 'Asia', ), 'IR' => array( 'name' => 'Iran', 'continent' => 'Asia', ), 'IQ' => array( 'name' => 'Iraq', 'continent' => 'Asia', ), 'IE' => array( 'name' => 'Ireland', 'continent' => 'Europe', ), 'IM' => array( 'name' => 'Isle of Man', 'continent' => 'Europe', ), 'IL' => array( 'name' => 'Israel', 'continent' => 'Asia', ), 'IT' => array( 'name' => 'Italy', 'continent' => 'Europe', ), 'JM' => array( 'name' => 'Jamaica', 'continent' => 'North America', ), 'JP' => array( 'name' => 'Japan', 'continent' => 'Asia', ), 'JE' => array( 'name' => 'Jersey', 'continent' => 'Europe', ), 'JO' => array( 'name' => 'Jordan', 'continent' => 'Asia', ), 'KZ' => array( 'name' => 'Kazakhstan', 'continent' => 'Asia', ), 'KE' => array( 'name' => 'Kenya', 'continent' => 'Africa', ), 'KI' => array( 'name' => 'Kiribati', 'continent' => 'Oceania', ), 'KP' => array( 'name' => "Democratic People's Republic of Korea", 'continent' => 'Asia', ), 'KR' => array( 'name' => 'Republic of Korea', 'continent' => 'Asia', ), 'KW' => array( 'name' => 'Kuwait', 'continent' => 'Asia', ), 'KG' => array( 'name' => 'Kyrgyzstan', 'continent' => 'Asia', ), 'LA' => array( 'name' => "Lao People's Democratic Republic", 'continent' => 'Asia', ), 'LV' => array( 'name' => 'Latvia', 'continent' => 'Europe', ), 'LB' => array( 'name' => 'Lebanon', 'continent' => 'Asia', ), 'LS' => array( 'name' => 'Lesotho', 'continent' => 'Africa', ), 'LR' => array( 'name' => 'Liberia', 'continent' => 'Africa', ), 'LY' => array( 'name' => 'Libya', 'continent' => 'Africa', ), 'LI' => array( 'name' => 'Liechtenstein', 'continent' => 'Europe', ), 'LT' => array( 'name' => 'Lithuania', 'continent' => 'Europe', ), 'LU' => array( 'name' => 'Luxembourg', 'continent' => 'Europe', ), 'MO' => array( 'name' => 'Macao', 'continent' => 'Asia', ), 'MK' => array( 'name' => 'Macedonia', 'continent' => 'Europe', ), 'MG' => array( 'name' => 'Madagascar', 'continent' => 'Africa', ), 'MW' => array( 'name' => 'Malawi', 'continent' => 'Africa', ), 'MY' => array( 'name' => 'Malaysia', 'continent' => 'Asia', ), 'MV' => array( 'name' => 'Maldives', 'continent' => 'Asia', ), 'ML' => array( 'name' => 'Mali', 'continent' => 'Africa', ), 'MT' => array( 'name' => 'Malta', 'continent' => 'Europe', ), 'MH' => array( 'name' => 'Marshall Islands', 'continent' => 'Oceania', ), 'MQ' => array( 'name' => 'Martinique', 'continent' => 'North America', ), 'MR' => array( 'name' => 'Mauritania', 'continent' => 'Africa', ), 'MU' => array( 'name' => 'Mauritius', 'continent' => 'Africa', ), 'YT' => array( 'name' => 'Mayotte', 'continent' => 'Africa', ), 'MX' => array( 'name' => 'Mexico', 'continent' => 'North America', ), 'FM' => array( 'name' => 'Micronesia', 'continent' => 'Oceania', ), 'MD' => array( 'name' => 'Moldova', 'continent' => 'Europe', ), 'MC' => array( 'name' => 'Monaco', 'continent' => 'Europe', ), 'MN' => array( 'name' => 'Mongolia', 'continent' => 'Asia', ), 'ME' => array( 'name' => 'Montenegro', 'continent' => 'Europe', ), 'MS' => array( 'name' => 'Montserrat', 'continent' => 'North America', ), 'MA' => array( 'name' => 'Morocco', 'continent' => 'Africa', ), 'MZ' => array( 'name' => 'Mozambique', 'continent' => 'Africa', ), 'MM' => array( 'name' => 'Myanmar', 'continent' => 'Asia', ), 'NA' => array( 'name' => 'Namibia', 'continent' => 'Africa', ), 'NR' => array( 'name' => 'Nauru', 'continent' => 'Oceania', ), 'NP' => array( 'name' => 'Nepal', 'continent' => 'Asia', ), 'NL' => array( 'name' => 'Netherlands', 'continent' => 'Europe', ), 'AN' => array( 'name' => 'Netherlands Antilles', 'continent' => 'North America', ), 'NC' => array( 'name' => 'New Caledonia', 'continent' => 'Oceania', ), 'NZ' => array( 'name' => 'New Zealand', 'continent' => 'Oceania', ), 'NI' => array( 'name' => 'Nicaragua', 'continent' => 'North America', ), 'NE' => array( 'name' => 'Niger', 'continent' => 'Africa', ), 'NG' => array( 'name' => 'Nigeria', 'continent' => 'Africa', ), 'NU' => array( 'name' => 'Niue', 'continent' => 'Oceania', ), 'NF' => array( 'name' => 'Norfolk Island', 'continent' => 'Oceania', ), 'MP' => array( 'name' => 'Northern Mariana Islands', 'continent' => 'Oceania', ), 'NO' => array( 'name' => 'Norway', 'continent' => 'Europe', ), 'OM' => array( 'name' => 'Oman', 'continent' => 'Asia', ), 'PK' => array( 'name' => 'Pakistan', 'continent' => 'Asia', ), 'PW' => array( 'name' => 'Palau', 'continent' => 'Oceania', ), 'PS' => array( 'name' => 'Palestinia', 'continent' => 'Asia', ), 'PA' => array( 'name' => 'Panama', 'continent' => 'North America', ), 'PG' => array( 'name' => 'Papua New Guinea', 'continent' => 'Oceania', ), 'PY' => array( 'name' => 'Paraguay', 'continent' => 'South America', ), 'PE' => array( 'name' => 'Peru', 'continent' => 'South America', ), 'PH' => array( 'name' => 'Philippines', 'continent' => 'Asia', ), 'PN' => array( 'name' => 'Pitcairn', 'continent' => 'Oceania', ), 'PL' => array( 'name' => 'Poland', 'continent' => 'Europe', ), 'PT' => array( 'name' => 'Portugal', 'continent' => 'Europe', ), 'PR' => array( 'name' => 'Puerto Rico', 'continent' => 'North America', ), 'QA' => array( 'name' => 'Qatar', 'continent' => 'Asia', ), 'RE' => array( 'name' => 'Reunion', 'continent' => 'Africa', ), 'RO' => array( 'name' => 'Romania', 'continent' => 'Europe', ), 'RU' => array( 'name' => 'Russian Federation', 'continent' => 'Europe', ), 'RW' => array( 'name' => 'Rwanda', 'continent' => 'Africa', ), 'SH' => array( 'name' => 'Saint Helena', 'continent' => 'Africa', ), 'KN' => array( 'name' => 'Saint Kitts and Nevis', 'continent' => 'North America', ), 'LC' => array( 'name' => 'Saint Lucia', 'continent' => 'North America', ), 'PM' => array( 'name' => 'Saint Pierre and Miquelon', 'continent' => 'North America', ), 'VC' => array( 'name' => 'Saint Vincent and The Grenadines', 'continent' => 'North America', ), 'WS' => array( 'name' => 'Samoa', 'continent' => 'Oceania', ), 'SM' => array( 'name' => 'San Marino', 'continent' => 'Europe', ), 'ST' => array( 'name' => 'Sao Tome and Principe', 'continent' => 'Africa', ), 'SA' => array( 'name' => 'Saudi Arabia', 'continent' => 'Asia', ), 'SN' => array( 'name' => 'Senegal', 'continent' => 'Africa', ), 'RS' => array( 'name' => 'Serbia', 'continent' => 'Europe', ), 'SC' => array( 'name' => 'Seychelles', 'continent' => 'Africa', ), 'SL' => array( 'name' => 'Sierra Leone', 'continent' => 'Africa', ), 'SG' => array( 'name' => 'Singapore', 'continent' => 'Asia', ), 'SK' => array( 'name' => 'Slovakia', 'continent' => 'Europe', ), 'SI' => array( 'name' => 'Slovenia', 'continent' => 'Europe', ), 'SB' => array( 'name' => 'Solomon Islands', 'continent' => 'Oceania', ), 'SO' => array( 'name' => 'Somalia', 'continent' => 'Africa', ), 'ZA' => array( 'name' => 'South Africa', 'continent' => 'Africa', ), 'GS' => array( 'name' => 'South Georgia and The South Sandwich Islands', 'continent' => 'Antarctica', ), 'ES' => array( 'name' => 'Spain', 'continent' => 'Europe', ), 'LK' => array( 'name' => 'Sri Lanka', 'continent' => 'Asia', ), 'SD' => array( 'name' => 'Sudan', 'continent' => 'Africa', ), 'SR' => array( 'name' => 'Suriname', 'continent' => 'South America', ), 'SJ' => array( 'name' => 'Svalbard and Jan Mayen', 'continent' => 'Europe', ), 'SZ' => array( 'name' => 'Swaziland', 'continent' => 'Africa', ), 'SE' => array( 'name' => 'Sweden', 'continent' => 'Europe', ), 'CH' => array( 'name' => 'Switzerland', 'continent' => 'Europe', ), 'SY' => array( 'name' => 'Syrian Arab Republic', 'continent' => 'Asia', ), 'TW' => array( 'name' => 'Taiwan, Province of China', 'continent' => 'Asia', ), 'TJ' => array( 'name' => 'Tajikistan', 'continent' => 'Asia', ), 'TZ' => array( 'name' => 'Tanzania, United Republic of', 'continent' => 'Africa', ), 'TH' => array( 'name' => 'Thailand', 'continent' => 'Asia', ), 'TL' => array( 'name' => 'Timor-leste', 'continent' => 'Asia', ), 'TG' => array( 'name' => 'Togo', 'continent' => 'Africa', ), 'TK' => array( 'name' => 'Tokelau', 'continent' => 'Oceania', ), 'TO' => array( 'name' => 'Tonga', 'continent' => 'Oceania', ), 'TT' => array( 'name' => 'Trinidad and Tobago', 'continent' => 'North America', ), 'TN' => array( 'name' => 'Tunisia', 'continent' => 'Africa', ), 'TR' => array( 'name' => 'Turkey', 'continent' => 'Asia', ), 'TM' => array( 'name' => 'Turkmenistan', 'continent' => 'Asia', ), 'TC' => array( 'name' => 'Turks and Caicos Islands', 'continent' => 'North America', ), 'TV' => array( 'name' => 'Tuvalu', 'continent' => 'Oceania', ), 'UG' => array( 'name' => 'Uganda', 'continent' => 'Africa', ), 'UA' => array( 'name' => 'Ukraine', 'continent' => 'Europe', ), 'AE' => array( 'name' => 'United Arab Emirates', 'continent' => 'Asia', ), 'GB' => array( 'name' => 'United Kingdom', 'continent' => 'Europe', ), 'US' => array( 'name' => 'United States', 'continent' => 'North America', ), 'UM' => array( 'name' => 'United States Minor Outlying Islands', 'continent' => 'Oceania', ), 'UY' => array( 'name' => 'Uruguay', 'continent' => 'South America', ), 'UZ' => array( 'name' => 'Uzbekistan', 'continent' => 'Asia', ), 'VU' => array( 'name' => 'Vanuatu', 'continent' => 'Oceania', ), 'VE' => array( 'name' => 'Venezuela', 'continent' => 'South America', ), 'VN' => array( 'name' => 'Viet Nam', 'continent' => 'Asia', ), 'VG' => array( 'name' => 'Virgin Islands, British', 'continent' => 'North America', ), 'VI' => array( 'name' => 'Virgin Islands, U.S.', 'continent' => 'North America', ), 'WF' => array( 'name' => 'Wallis and Futuna', 'continent' => 'Oceania', ), 'EH' => array( 'name' => 'Western Sahara', 'continent' => 'Africa', ), 'YE' => array( 'name' => 'Yemen', 'continent' => 'Asia', ), 'ZM' => array( 'name' => 'Zambia', 'continent' => 'Africa', ), 'ZW' => array( 'name' => 'Zimbabwe', 'continent' => 'Africa', ), ); return $country_code ? ( $countries[ $country_code ] ?? '' ) : $countries; } public static function ad_format( $ad_format_id = null ) { $ad_formats = array( // ───────────────────────────────────────────── // Banner // ───────────────────────────────────────────── 'banner' => array( 'name' => 'Banner', 'description' => 'Displays a standard banner ad.', 'status' => 'active', 'placement_type' => 'positional', 'max_spaces' => null, ), // ───────────────────────────────────────────── // Slider // ───────────────────────────────────────────── 'slider' => array( 'name' => 'Slider', 'description' => 'Displays a slider with multiple ads.', 'status' => 'active', 'placement_type' => 'positional', 'max_spaces' => null, ), // ───────────────────────────────────────────── // POPUP // ───────────────────────────────────────────── 'popup' => array( 'name' => 'Popup', 'description' => 'Shows a popup ad on page load or user action.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 1, // 'conversion_note' => __( // 'Use a 600×400 px landscape banner (JPEG/PNG under 150 KB). ' // . 'A bold headline + single CTA converts best. ' // . 'Set the trigger delay to 3–5 s — early enough to catch attention, late enough not to annoy visitors. ' // . 'Include a discount code or urgency message ("Limited time offer!") to maximise click-through.', // 'ad-fuz' // ), 'settings' => array( 'delay' => array( 'label' => __( 'Trigger Delay (seconds)', 'ad-fuz' ), 'hint' => __( 'How many seconds after page load before the popup appears (0 = instant).', 'ad-fuz' ), 'type' => 'number', 'default' => 3, 'min' => 0, 'max' => 30, 'sanitize' => fn( $v ) => max( 0, min( 30, absint( $v ) ) ), ), 'overlay_color' => array( 'label' => __( 'Overlay Background Color', 'ad-fuz' ), 'hint' => __( 'Color of the semi-transparent backdrop behind the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'overlay_opacity' => array( 'label' => __( 'Overlay Opacity (%)', 'ad-fuz' ), 'hint' => __( 'Backdrop opacity from 0 (transparent) to 100 (solid).', 'ad-fuz' ), 'type' => 'number', 'default' => 60, 'min' => 0, 'max' => 100, 'sanitize' => fn( $v ) => max( 0, min( 100, absint( $v ) ) ), ), 'box_bg_color' => array( 'label' => __( 'Popup Box Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the popup box itself.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'box_padding' => array( 'label' => __( 'Popup Box Padding (px)', 'ad-fuz' ), 'hint' => __( 'Padding inside the popup box.', 'ad-fuz' ), 'type' => 'number', 'default' => 20, 'min' => 0, 'max' => 100, 'sanitize' => fn( $v ) => max( 0, min( 100, absint( $v ) ) ), ), 'box_radius' => array( 'label' => __( 'Popup Box Border Radius (px)', 'ad-fuz' ), 'hint' => __( 'Rounded corners for the popup box.', 'ad-fuz' ), 'type' => 'number', 'default' => 12, 'min' => 0, 'max' => 50, 'sanitize' => fn( $v ) => max( 0, min( 50, absint( $v ) ) ), ), 'box_width' => array( 'label' => __( 'Popup Box Width (px)', 'ad-fuz' ), 'hint' => __( 'Width of the popup box in pixels.', 'ad-fuz' ), 'type' => 'number', 'default' => 600, 'min' => 300, 'max' => 1200, 'sanitize' => fn( $v ) => max( 300, min( 1200, absint( $v ) ) ), ), 'box_max_width' => array( 'label' => __( 'Popup Box Max Width (vw)', 'ad-fuz' ), 'hint' => __( 'Maximum width of the popup box as a percentage of viewport width.', 'ad-fuz' ), 'type' => 'number', 'default' => 90, 'min' => 50, 'max' => 100, 'sanitize' => fn( $v ) => max( 50, min( 100, absint( $v ) ) ), ), 'title_color' => array( 'label' => __( 'Title Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad title text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'desc_color' => array( 'label' => __( 'Description Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad description text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'cta_color' => array( 'label' => __( 'CTA Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#2271b1', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#2271b1', ), 'cta_text_color' => array( 'label' => __( 'CTA Button Text Color', 'ad-fuz' ), 'hint' => __( 'Text color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'close_color' => array( 'label' => __( 'Close Button Color', 'ad-fuz' ), 'hint' => __( 'Color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'close_bg_color' => array( 'label' => __( 'Close Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => 'transparent', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: 'transparent', ), ), ), // ───────────────────────────────────────────── // EXIT POPUP // ───────────────────────────────────────────── 'exit_popup' => array( 'name' => 'Exit Popup', 'description' => 'Triggers a popup when the user tries to leave the page.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 1, // 'conversion_note' => __( // 'Use a 600×400 px landscape banner. ' // . 'Last-chance offers ("Wait! Get 20% off") can recover 10–15% of abandoning users. ' // . 'Keep copy short: one bold headline + one CTA button. ' // . 'Avoid heavy imagery — keep file size under 150 KB so it renders before the user navigates away.', // 'ad-fuz' // ), 'settings' => array( 'overlay_color' => array( 'label' => __( 'Overlay Background Color', 'ad-fuz' ), 'hint' => __( 'Color of the semi-transparent backdrop behind the exit popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'overlay_opacity' => array( 'label' => __( 'Overlay Opacity (%)', 'ad-fuz' ), 'hint' => __( 'Backdrop opacity from 0 (transparent) to 100 (solid).', 'ad-fuz' ), 'type' => 'number', 'default' => 60, 'min' => 0, 'max' => 100, 'sanitize' => fn( $v ) => max( 0, min( 100, absint( $v ) ) ), ), 'box_bg_color' => array( 'label' => __( 'Popup Box Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the popup box itself.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'box_padding' => array( 'label' => __( 'Popup Box Padding (px)', 'ad-fuz' ), 'hint' => __( 'Padding inside the popup box.', 'ad-fuz' ), 'type' => 'number', 'default' => 20, 'min' => 0, 'max' => 100, 'sanitize' => fn( $v ) => max( 0, min( 100, absint( $v ) ) ), ), 'box_radius' => array( 'label' => __( 'Popup Box Border Radius (px)', 'ad-fuz' ), 'hint' => __( 'Rounded corners for the popup box.', 'ad-fuz' ), 'type' => 'number', 'default' => 12, 'min' => 0, 'max' => 50, 'sanitize' => fn( $v ) => max( 0, min( 50, absint( $v ) ) ), ), 'box_width' => array( 'label' => __( 'Popup Box Width (px)', 'ad-fuz' ), 'hint' => __( 'Width of the popup box in pixels.', 'ad-fuz' ), 'type' => 'number', 'default' => 600, 'min' => 300, 'max' => 1200, 'sanitize' => fn( $v ) => max( 300, min( 1200, absint( $v ) ) ), ), 'box_max_width' => array( 'label' => __( 'Popup Box Max Width (vw)', 'ad-fuz' ), 'hint' => __( 'Maximum width of the popup box as a percentage of viewport width.', 'ad-fuz' ), 'type' => 'number', 'default' => 90, 'min' => 50, 'max' => 100, 'sanitize' => fn( $v ) => max( 50, min( 100, absint( $v ) ) ), ), 'title_color' => array( 'label' => __( 'Title Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad title text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'desc_color' => array( 'label' => __( 'Description Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad description text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'cta_color' => array( 'label' => __( 'CTA Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#2271b1', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#2271b1', ), 'cta_text_color' => array( 'label' => __( 'CTA Button Text Color', 'ad-fuz' ), 'hint' => __( 'Text color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'close_color' => array( 'label' => __( 'Close Button Color', 'ad-fuz' ), 'hint' => __( 'Color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'close_bg_color' => array( 'label' => __( 'Close Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => 'transparent', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: 'transparent', ), ), ), // ───────────────────────────────────────────── // BACKGROUND // ───────────────────────────────────────────── 'background' => array( 'name' => 'Background', 'description' => 'Sets the background of the page as an advertisement.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 1, // 'conversion_note' => __( // 'Provide a high-resolution image of at least 1920×1080 px (16:9, JPEG 80% quality). ' // . 'Use a light or subtly blurred image so it does not compete with page content. ' // . 'For video backgrounds, use a muted MP4 under 5 MB — autoplay only works when muted. ' // . 'Pair with a prominent on-page CTA since the background itself is the ad canvas.', // 'ad-fuz' // ), // No behaviour settings needed — the background is purely visual, // driven entirely by the ad's media URL. // 'settings' => array(), ), // ───────────────────────────────────────────── // CORNER PEEL // ───────────────────────────────────────────── 'corner_peel' => array( 'name' => 'Corner Peel', 'description' => 'Displays a peel effect in the corner revealing the ad.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 4, 'positions' => array( 'top_left' => 'Top Left', 'top_right' => 'Top Right', 'bottom_left' => 'Bottom Left', 'bottom_right' => 'Bottom Right', ), // 'conversion_note' => __( // 'Use the IAB Medium Rectangle (300×250 px) inside the expanded peel — ' // . 'it is the most widely accepted ad size and fills the expanded area cleanly. ' // . 'Set Peek Size to 100–120 px: noticeable without being disruptive. ' // . 'Works great for coupon reveals and teaser creatives — use curiosity-driven copy on the peel tab.', // 'ad-fuz' // ), 'settings' => array( 'peek_size' => array( 'label' => __( 'Peek Size (px)', 'ad-fuz' ), 'hint' => __( 'Size of the folded corner triangle shown before hover (default 120px, Min:60px and Max:200px).', 'ad-fuz' ), 'type' => 'number', 'default' => 120, 'min' => 60, 'max' => 200, 'sanitize' => fn( $v ) => max( 60, min( 200, absint( $v ) ) ), ), 'expand_width' => array( 'label' => __( 'Expanded Width (px)', 'ad-fuz' ), 'hint' => __( 'Width of the peel when fully expanded on hover (default 300px, Min:150px and Max:500px).', 'ad-fuz' ), 'type' => 'number', 'default' => 300, 'min' => 150, 'max' => 500, 'sanitize' => fn( $v ) => max( 150, min( 500, absint( $v ) ) ), ), 'expand_height' => array( 'label' => __( 'Expanded Height (px)', 'ad-fuz' ), 'hint' => __( 'Height of the peel when fully expanded on hover (default 250px, Min:100px and Max:500px).', 'ad-fuz' ), 'type' => 'number', 'default' => 250, 'min' => 100, 'max' => 500, 'sanitize' => fn( $v ) => max( 100, min( 500, absint( $v ) ) ), ), ), ), // ───────────────────────────────────────────── // SCROLL TRIGGER // ───────────────────────────────────────────── 'scroll_trigger' => array( 'name' => 'Scroll Trigger', 'description' => 'Shows the ad after the user scrolls a certain distance.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 1, // 'conversion_note' => __( // 'For desktop use a 728×90 px Leaderboard; for mobile use a 320×50 px Mobile Banner. ' // . 'Triggering at 50% scroll depth targets engaged, mid-content readers. ' // . 'Keep creative simple with a clear CTA — the visitor is reading, not browsing. ' // . 'Bottom Center placement is the least intrusive and has the highest acceptance rate.', // 'ad-fuz' // ), 'settings' => array( 'scroll_depth' => array( 'label' => __( 'Scroll Depth (%)', 'ad-fuz' ), 'hint' => __( 'Page scroll percentage that triggers the ad (0–100).', 'ad-fuz' ), 'type' => 'number', 'default' => 50, 'min' => 5, 'max' => 100, 'sanitize' => fn( $v ) => max( 5, min( 100, absint( $v ) ) ), ), 'position' => array( 'label' => __( 'Ad Position', 'ad-fuz' ), 'hint' => __( 'Where the scroll-triggered ad appears on screen.', 'ad-fuz' ), 'type' => 'select', 'default' => 'bottom_center', 'options' => array( 'bottom_center' => __( 'Bottom Center', 'ad-fuz' ), 'bottom_left' => __( 'Bottom Left', 'ad-fuz' ), 'bottom_right' => __( 'Bottom Right', 'ad-fuz' ), ), 'sanitize' => fn( $v ) => in_array( $v, array( 'bottom_center', 'bottom_left', 'bottom_right' ), true ) ? $v : 'bottom_center', ), 'box_bg_color' => array( 'label' => __( 'Box Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the scroll trigger box.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'box_padding' => array( 'label' => __( 'Box Padding (px)', 'ad-fuz' ), 'hint' => __( 'Padding inside the scroll trigger box.', 'ad-fuz' ), 'type' => 'number', 'default' => 16, 'min' => 0, 'max' => 50, 'sanitize' => fn( $v ) => max( 0, min( 50, absint( $v ) ) ), ), 'box_radius' => array( 'label' => __( 'Box Border Radius (px)', 'ad-fuz' ), 'hint' => __( 'Rounded corners for the scroll trigger box.', 'ad-fuz' ), 'type' => 'number', 'default' => 12, 'min' => 0, 'max' => 50, 'sanitize' => fn( $v ) => max( 0, min( 50, absint( $v ) ) ), ), 'box_shadow' => array( 'label' => __( 'Box Shadow', 'ad-fuz' ), 'hint' => __( 'CSS box shadow for the scroll trigger box.', 'ad-fuz' ), 'type' => 'text', 'default' => '0 4px 24px rgba(0,0,0,0.18)', 'sanitize' => fn( $v ) => sanitize_text_field( $v ), ), 'title_color' => array( 'label' => __( 'Title Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad title text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'desc_color' => array( 'label' => __( 'Description Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad description text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'cta_color' => array( 'label' => __( 'CTA Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#2271b1', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#2271b1', ), 'cta_text_color' => array( 'label' => __( 'CTA Button Text Color', 'ad-fuz' ), 'hint' => __( 'Text color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'close_color' => array( 'label' => __( 'Close Button Color', 'ad-fuz' ), 'hint' => __( 'Color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'close_bg_color' => array( 'label' => __( 'Close Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => 'transparent', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: 'transparent', ), ), ), // ───────────────────────────────────────────── // INTERSTITIAL // ───────────────────────────────────────────── 'interstitial' => array( 'name' => 'Interstitial', 'description' => 'Full-screen ad shown between content or during transitions.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 1, // 'conversion_note' => __( // 'Design at 1080×1920 px for portrait mobile or 1280×720 px for landscape desktop. ' // . 'Always allow a skip after 5 s — this complies with Google\'s Better Ads Standards and avoids ranking penalties. ' // . 'Use a single bold CTA with high-contrast colours against the black backdrop. ' // . 'High-impact visuals (product hero shots, full-bleed photography) maximise recall and CTR.', // 'ad-fuz' // ), 'settings' => array( 'skip_after' => array( 'label' => __( 'Skip After (seconds)', 'ad-fuz' ), 'hint' => __( 'Seconds the visitor must wait before the Skip button appears (1–60).', 'ad-fuz' ), 'type' => 'number', 'default' => 5, 'min' => 1, 'max' => 60, 'sanitize' => fn( $v ) => max( 1, min( 60, absint( $v ) ) ), ), 'title_color' => array( 'label' => __( 'Title Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the overlay title text — make sure it contrasts with the black background.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'desc_color' => array( 'label' => __( 'Description Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the overlay description text.', 'ad-fuz' ), 'type' => 'color', 'default' => '#cccccc', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#cccccc', ), 'bg_color' => array( 'label' => __( 'Background Color', 'ad-fuz' ), 'hint' => __( 'Background color for the interstitial overlay.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'content_width' => array( 'label' => __( 'Content Width (%)', 'ad-fuz' ), 'hint' => __( 'Width of the ad content as a percentage of viewport width.', 'ad-fuz' ), 'type' => 'number', 'default' => 80, 'min' => 50, 'max' => 100, 'sanitize' => fn( $v ) => max( 50, min( 100, absint( $v ) ) ), ), 'content_max_width' => array( 'label' => __( 'Content Max Width (px)', 'ad-fuz' ), 'hint' => __( 'Maximum width of the ad content in pixels.', 'ad-fuz' ), 'type' => 'number', 'default' => 1200, 'min' => 400, 'max' => 2000, 'sanitize' => fn( $v ) => max( 400, min( 2000, absint( $v ) ) ), ), ), ), // ───────────────────────────────────────────── // COUNTDOWN // ───────────────────────────────────────────── 'countdown' => array( 'name' => 'Countdown', 'description' => 'Displays an ad with a countdown before allowing action.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 1, // 'conversion_note' => __( // 'Use a 600×400 px banner with a contrasting countdown badge colour. ' // . 'Urgency-driven creatives — flash sales, limited seats, expiring discounts — can lift conversions by up to 30%. ' // . 'Auto-close after the timer creates the smoothest UX; only show a manual close button when compliance requires it. ' // . 'Keep countdown duration under 15 s — longer timers frustrate users and increase bounce.', // 'ad-fuz' // ), 'settings' => array( 'duration' => array( 'label' => __( 'Countdown Duration (seconds)', 'ad-fuz' ), 'hint' => __( 'How long the countdown runs before the close button appears (3–60).', 'ad-fuz' ), 'type' => 'number', 'default' => 10, 'min' => 3, 'max' => 60, 'sanitize' => fn( $v ) => max( 3, min( 60, absint( $v ) ) ), ), 'auto_close' => array( 'label' => __( 'Auto Close After Timer', 'ad-fuz' ), 'hint' => __( 'Automatically close the ad once the countdown completes. If disabled, a close button appears instead.', 'ad-fuz' ), 'type' => 'toggle', 'default' => '1', 'sanitize' => fn( $v ) => $v ? '1' : '0', ), 'badge_color' => array( 'label' => __( 'Badge Background Color', 'ad-fuz' ), 'hint' => __( 'Color of the countdown timer badge shown above the ad.', 'ad-fuz' ), 'type' => 'color', 'default' => '#e53e3e', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#e53e3e', ), 'badge_text_color' => array( 'label' => __( 'Badge Text Color', 'ad-fuz' ), 'hint' => __( 'Color of the number/text inside the countdown badge.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'overlay_color' => array( 'label' => __( 'Overlay Background Color', 'ad-fuz' ), 'hint' => __( 'Color of the overlay backdrop behind the countdown ad.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'overlay_opacity' => array( 'label' => __( 'Overlay Opacity (%)', 'ad-fuz' ), 'hint' => __( 'Backdrop opacity from 0 (transparent) to 100 (solid).', 'ad-fuz' ), 'type' => 'number', 'default' => 65, 'min' => 0, 'max' => 100, 'sanitize' => fn( $v ) => max( 0, min( 100, absint( $v ) ) ), ), 'box_bg_color' => array( 'label' => __( 'Popup Box Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the popup box itself.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'box_padding' => array( 'label' => __( 'Popup Box Padding (px)', 'ad-fuz' ), 'hint' => __( 'Padding inside the popup box.', 'ad-fuz' ), 'type' => 'number', 'default' => 20, 'min' => 0, 'max' => 100, 'sanitize' => fn( $v ) => max( 0, min( 100, absint( $v ) ) ), ), 'box_radius' => array( 'label' => __( 'Popup Box Border Radius (px)', 'ad-fuz' ), 'hint' => __( 'Rounded corners for the popup box.', 'ad-fuz' ), 'type' => 'number', 'default' => 12, 'min' => 0, 'max' => 50, 'sanitize' => fn( $v ) => max( 0, min( 50, absint( $v ) ) ), ), 'box_width' => array( 'label' => __( 'Popup Box Width (px)', 'ad-fuz' ), 'hint' => __( 'Width of the popup box in pixels.', 'ad-fuz' ), 'type' => 'number', 'default' => 600, 'min' => 300, 'max' => 1200, 'sanitize' => fn( $v ) => max( 300, min( 1200, absint( $v ) ) ), ), 'box_max_width' => array( 'label' => __( 'Popup Box Max Width (vw)', 'ad-fuz' ), 'hint' => __( 'Maximum width of the popup box as a percentage of viewport width.', 'ad-fuz' ), 'type' => 'number', 'default' => 90, 'min' => 50, 'max' => 100, 'sanitize' => fn( $v ) => max( 50, min( 100, absint( $v ) ) ), ), 'title_color' => array( 'label' => __( 'Title Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad title text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#000000', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#000000', ), 'desc_color' => array( 'label' => __( 'Description Font Color', 'ad-fuz' ), 'hint' => __( 'Color of the ad description text inside the popup.', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'cta_color' => array( 'label' => __( 'CTA Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#2271b1', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#2271b1', ), 'cta_text_color' => array( 'label' => __( 'CTA Button Text Color', 'ad-fuz' ), 'hint' => __( 'Text color of the CTA button.', 'ad-fuz' ), 'type' => 'color', 'default' => '#ffffff', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#ffffff', ), 'close_color' => array( 'label' => __( 'Close Button Color', 'ad-fuz' ), 'hint' => __( 'Color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => '#666666', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: '#666666', ), 'close_bg_color' => array( 'label' => __( 'Close Button Background Color', 'ad-fuz' ), 'hint' => __( 'Background color of the close button (X).', 'ad-fuz' ), 'type' => 'color', 'default' => 'transparent', 'sanitize' => fn( $v ) => sanitize_hex_color( $v ) ?: 'transparent', ), ), ), // ───────────────────────────────────────────── // EDGE BAR // ───────────────────────────────────────────── 'edge_bar' => array( 'name' => 'Edge Bar', 'description' => 'A fixed bar anchored to any edge of the screen.', 'status' => 'active', 'placement_type' => 'global', 'max_spaces' => 4, 'positions' => array( 'top' => 'Top', 'bottom' => 'Bottom', 'left' => 'Left', 'right' => 'Right', ), // 'conversion_note' => __( // 'For horizontal bars (Top/Bottom) use a 1200×90 px strip or a standard 728×90 px Leaderboard centred inside it. ' // . 'For vertical bars (Left/Right) use a 120×600 px Wide Skyscraper. ' // . 'Keep messaging brief — 5–8 words + one CTA button. ' // . 'Enabling the Hide/Show toggle significantly reduces user annoyance and lowers bounce rate.', // 'ad-fuz' // ), 'settings' => array( 'show_toggle' => array( 'label' => __( 'Enable Hide/Show Button', 'ad-fuz' ), 'hint' => __( 'Show a button so visitors can hide or reveal the bar.', 'ad-fuz' ), 'type' => 'toggle', 'default' => '1', 'sanitize' => fn( $v ) => $v ? 1 : 0, ), 'toggle_hide_text' => array( 'label' => __( 'Hide Button Text', 'ad-fuz' ), 'hint' => __( 'Text on the button that hides the bar.', 'ad-fuz' ), 'type' => 'text', 'default' => 'Hide', 'sanitize' => fn( $v ) => sanitize_text_field( $v ) ?: 'Hide', ), 'toggle_show_text' => array( 'label' => __( 'Show Tab Text', 'ad-fuz' ), 'hint' => __( 'Text on the peek tab that brings the bar back.', 'ad-fuz' ), 'type' => 'text', 'default' => 'Show Ad', 'sanitize' => fn( $v ) => sanitize_text_field( $v ) ?: 'Show Ad', ), 'toggle_align' => array( 'label' => __( 'Button Alignment', 'ad-fuz' ), 'hint' => __( 'Where along the bar the hide/show button sits. For horizontal bars (top/bottom) this is left/center/right. For vertical bars (left/right) this is top/center/bottom.', 'ad-fuz' ), 'type' => 'select', 'default' => 'flex-end', 'options' => array( 'flex-start' => __( 'Start', 'ad-fuz' ), 'center' => __( 'Center', 'ad-fuz' ), 'flex-end' => __( 'End', 'ad-fuz' ), ), 'sanitize' => fn( $v ) => in_array( $v, array( 'flex-start', 'center', 'flex-end' ), true ) ? $v : 'flex-end', ), 'toggle_side' => array( 'label' => __( 'Button Side', 'ad-fuz' ), 'hint' => __( 'Which side of the bar the button appears on "Inner" places it adjacent to the ad content (always visible) "Outer" places it on the screen-edge side — note this pushes the button partially off-screen on bottom and right bars.', 'ad-fuz' ), 'type' => 'select', 'default' => 'inner', 'options' => array( 'inner' => __( 'Inner (content side)', 'ad-fuz' ), 'outer' => __( 'Outer (screen-edge side)', 'ad-fuz' ), ), 'sanitize' => fn( $v ) => in_array( $v, array( 'inner', 'outer' ), true ) ? $v : 'inner', ), ), ), 'global' => array( 'name' => 'Global', 'description' => 'Ad that will be placed in the Global spaces.', 'status' => 'active', 'placement_type' => 'positional', 'max_spaces' => null, ), ); $ad_formats = apply_filters( 'adfuz/ads/ad_format/formats', $ad_formats ); if ( $ad_format_id ) { return $ad_formats[ $ad_format_id ]['name'] ?? ''; } return array_filter( $ad_formats, function ( $format ) { return ( 'active' === $format['status'] ); } ); } public static function active_positional_ad_format() { return array_filter( self::ad_format(), function ( $format ) { return ( 'positional' === $format['placement_type'] ); } ); } public static function active_global_ad_format() { return array_filter( self::ad_format(), function ( $format ) { return ( 'global' === $format['placement_type'] ); } ); } public static function is_global_format( $ad_format_id ): bool { $format = self::ad_format( $ad_format_id ); return ( $format['placement_type'] ?? 'positional' ) === 'global'; } // Global formats are never shown in Ad Space listings public static function get_positional_formats(): array { return array_filter( self::ad_format(), fn( $f ) => $f['placement_type'] === 'positional' ); } public static function get_global_formats(): array { return array_filter( self::ad_format(), fn( $f ) => $f['placement_type'] === 'global' ); } /** * Output an icon (default: “info” Dashicon) that shows a tooltip. * * @param string $tooltip Tooltip text or HTML. Required. * @param array|string $args Optional settings **or** a shortcut label string. * If you pass a string here it becomes the visible label. * For array options see below. * * Array options (all optional): * - label (string) Visible text next to the icon. Default '' (icon-only). * - icon (string) SVG filename in /assets/icons/ (no “.svg”) **or** raw HTML. * Default uses Dashicon info. * - href (string) If set: output . Otherwise