'floating', ]; const CONTENT_ZONES = ['incontent', 'before_content', 'after_content']; const WRAP_ZONES = ['incontent', 'before_content', 'after_content', 'selector', 'shortcode', 'hook']; public static function render(array $unit, $zone, $index = 0) { $unit = AdGhost_Helper::normalize_unit($unit); $slot_id = sanitize_html_class('adghost-' . str_replace('_', '-', $zone) . '-' . (int) $index); $sizes = str_replace(';', ',', (string) ($unit['sizes'] ?? '300x250')); if (in_array($zone, self::CONTENT_ZONES, true) && class_exists('AdGhost_Content_Analyzer')) { $sizes = str_replace(';', ',', AdGhost_Content_Analyzer::filter_sizes($sizes, AdGhost_Content_Analyzer::content_max_width())); } if (class_exists('AdGhost_AMP') && AdGhost_AMP::is_amp()) { return AdGhost_AMP::ad($unit, $zone, $sizes); } $align = $unit['align']; if (strpos($align, 'float-') === 0 && !in_array($zone, self::WRAP_ZONES, true)) { $align = 'center'; } $classes = [ 'adghost-ad-container', 'adghost-' . str_replace('_', '-', $zone), 'adghost-align-' . $align, ]; $attrs = [ 'class' => implode(' ', $classes), 'id' => $slot_id, 'data-adghost-slot' => $slot_id, 'data-adghost-id' => (string) ($unit['id'] ?? ''), 'data-adghost-unit' => AdGhost_Helper::gam_code($unit), 'data-adghost-name' => (string) ($unit['name'] ?? ''), 'data-adghost-sizes' => $sizes, 'data-adghost-position' => $zone, 'data-adghost-index' => (string) (int) $index, ]; $feature = AdGhost_Helper::served_feature($unit); $formats = self::behaviour_formats(); if (isset($formats[$feature])) { $attrs['data-adghost-format'] = $formats[$feature]; if ($feature === 'float') { $corner = (string) ($unit['corner'] ?? 'bottom-right'); $attrs['data-adghost-corner'] = in_array($corner, ['bottom-right', 'bottom-left', 'top-right', 'top-left'], true) ? $corner : 'bottom-right'; } } $rides = $feature === 'sticky' || $feature === 'elevator'; $label = self::label(); if ($label !== '') { $attrs['class'] .= ' adghost-has-label'; $attrs['data-adghost-label'] = $label; } $spacing = self::spacing($unit); $pad = (int) ($spacing['padding'] ?? 0); $style = ''; $height = self::reserved_height($sizes); if ($height > 0) { $style .= 'min-height:' . ($height + ($label !== '' ? self::LABEL_HEIGHT : 0) + 2 * $pad) . 'px;'; } $phone_height = self::reserved_height($sizes, self::PHONE_WIDTH); if ($height > 0 && $phone_height !== $height) { $attrs['data-adghost-phone-h'] = '1'; $style .= '--adghost-phone-h:' . ($phone_height > 0 ? $phone_height + ($label !== '' ? self::LABEL_HEIGHT : 0) + 2 * $pad : 0) . 'px;'; } if ($spacing['padding'] !== null) { $style .= 'box-sizing:border-box;padding:' . $pad . 'px;'; } if (!$rides) { $style .= self::margin_style($spacing); } $widest = self::widest($sizes); if ($widest > 0) { $style .= '--adghost-preview-w:' . $widest . 'px;'; } if ($rides) { $attrs['class'] .= ' adghost-sticky' . (($unit['elevatorAlign'] ?? 'top') === 'center' ? ' adghost-ride-center' : ''); $style .= '--adghost-sticky-top:' . min(400, absint($unit['stickyOffset'] ?? 16)) . 'px;--adghost-ad-h:' . max(50, $height + ($label !== '' ? self::LABEL_HEIGHT : 0) + 2 * $pad) . 'px;'; } if ($style !== '') { $attrs['style'] = $style; } $attrs = (array) apply_filters('adghost_container_attributes', $attrs, $unit, $zone); if ($unit['devices'] !== '' && class_exists('AdGhost_Targeting') && AdGhost_Targeting::device_mode() === 'browser') { $attrs['data-adghost-devices'] = str_replace(',', ' ', $unit['devices']); } $html = ' $value) { $html .= ' ' . $name . '="' . esc_attr($value) . '"'; } $html .= '>'; if ($rides) { $travel = self::travel_height($unit, $height + ($label !== '' ? self::LABEL_HEIGHT : 0) + 2 * $pad); $width = self::widest($sizes); $html = '
' . $html . '
'; } return $html; } const PHONE_WIDTH = 479; const SPACING_MAX = 200; public static function spacing(array $unit) { $read = function ($key) use ($unit) { if (!isset($unit[$key]) || $unit[$key] === '' || $unit[$key] === null || !is_numeric($unit[$key])) { return null; } return (int) min(self::SPACING_MAX, max(0, (int) $unit[$key])); }; return ['above' => $read('spaceAbove'), 'below' => $read('spaceBelow'), 'padding' => $read('innerPadding')]; } public static function margin_style(array $spacing) { return ($spacing['above'] !== null ? 'margin-top:' . $spacing['above'] . 'px;' : '') . ($spacing['below'] !== null ? 'margin-bottom:' . $spacing['below'] . 'px;' : ''); } const LABEL_HEIGHT = 18; const BOX_LABEL_HEIGHT = 0; public static function widest($sizes) { $width = 0; foreach (preg_split('/[;,]/', (string) $sizes) as $size) { if (preg_match('/^\s*(\d+)\s*x\s*(\d+)\s*$/i', $size, $m) && (int) $m[1] > 1) { $width = max($width, (int) $m[1]); } } return $width; } const TRAVEL_DEFAULT = 600; public static function travel_height(array $unit, $ad_height) { $travel = absint($unit['travelHeight'] ?? 0) ?: self::TRAVEL_DEFAULT; return (int) min(3000, max($travel, (int) $ad_height + 150)); } public static function behaviour_formats() { return (array) apply_filters('adghost_behaviour_formats', self::FORMAT_OF_BEHAVIOUR); } public static function reserved_height($sizes, $max_width = 0) { $mode = AdGhost_Helper::cls_mode(); if ($mode === 'off') { return 0; } $heights = []; foreach (preg_split('/[;,]/', (string) $sizes) as $size) { if (preg_match('/^\s*(\d+)\s*x\s*(\d+)\s*$/i', $size, $m) && (int) $m[1] > 1 && ($max_width <= 0 || (int) $m[1] <= $max_width)) { $heights[] = (int) $m[2]; } } if (!$heights) { return 0; } return $mode === 'min' ? min($heights) : max($heights); } public static function label() { $type = get_option('adghost_ad_label_type', 'default'); if ($type === 'hidden') { return ''; } if ($type === 'custom') { $custom = trim((string) get_option('adghost_ad_label_custom', '')); return $custom !== '' ? $custom : 'Advertisement'; } return 'Advertisement'; } }