self::PHONE_MAX;
}));
$ranges = self::device_ranges($unit);
$ads = '';
if ($phone && $wide) {
$split = max(array_column($wide, 0));
$ads .= self::element($network, $code, $phone, self::media(self::intersect($ranges, [[0, $split - 1]])));
$ads .= self::element($network, $code, $wide, self::media(self::intersect($ranges, [[$split, PHP_INT_MAX]])));
} else {
$ads .= self::element($network, $code, $phone ?: $wide, self::media($ranges));
}
if ($ads === '') {
return '';
}
$label = AdGhost_Ad_Container::label();
return '
' . $ads . '
';
}
private static function element($network, $code, array $list, $media) {
if ($media === null) {
return '';
}
$best = 0;
$best_fits = -1;
foreach ($list as $i => $size) {
$fits = count(array_filter($list, function ($other) use ($size) {
return $other[0] <= $size[0] && $other[1] <= $size[1];
}));
if ($fits > $best_fits) {
$best = $i;
$best_fits = $fits;
}
}
$primary = $list[$best];
unset($list[$best]);
$list = array_values(array_filter($list, function ($size) use ($primary) {
return $size[0] <= $primary[0] && $size[1] <= $primary[1];
}));
$attrs = [
'width' => (string) $primary[0],
'height' => (string) $primary[1],
'type' => 'doubleclick',
'layout' => 'fixed',
'data-slot' => '/' . $network . '/' . $code,
];
if ($media !== '') {
$attrs['media'] = $media;
}
$json = class_exists('AdGhost_Key_Values') ? AdGhost_Key_Values::amp_json() : null;
if ($json !== null) {
$attrs['json'] = $json;
}
if ($list) {
$attrs['data-multi-size'] = implode(',', array_map(function ($size) {
return $size[0] . 'x' . $size[1];
}, $list));
$attrs['data-multi-size-validation'] = 'false';
}
$html = ' $value) {
$html .= ' ' . $name . '="' . esc_attr($value) . '"';
}
return $html . '>';
}
private static function device_ranges($unit) {
$devices = (string) ($unit['devices'] ?? '');
if ($devices === '' || (class_exists('AdGhost_Targeting') && AdGhost_Targeting::device_mode() === 'server')) {
return [[0, PHP_INT_MAX]];
}
$bounds = ['mobile' => [0, 767], 'tablet' => [768, 1024], 'desktop' => [1025, PHP_INT_MAX]];
$ranges = [];
foreach ($bounds as $device => $range) {
if (!in_array($device, explode(',', $devices), true)) {
continue;
}
$last = count($ranges) - 1;
if ($last >= 0 && $ranges[$last][1] + 1 === $range[0]) {
$ranges[$last][1] = $range[1];
} else {
$ranges[] = $range;
}
}
return $ranges;
}
private static function intersect(array $ranges, array $with) {
$out = [];
foreach ($ranges as $a) {
foreach ($with as $b) {
$lo = max($a[0], $b[0]);
$hi = min($a[1], $b[1]);
if ($lo <= $hi) {
$out[] = [$lo, $hi];
}
}
}
return $out;
}
private static function media(array $ranges) {
if (!$ranges) {
return null;
}
$queries = [];
foreach ($ranges as [$lo, $hi]) {
$parts = [];
if ($lo > 0) {
$parts[] = '(min-width: ' . $lo . 'px)';
}
if ($hi !== PHP_INT_MAX) {
$parts[] = '(max-width: ' . $hi . 'px)';
}
if (!$parts) {
return '';
}
$queries[] = implode(' and ', $parts);
}
return implode(', ', $queries);
}
private static function sticky_ad($network, $code, $sizes) {
if (self::$anchor_done) {
return '';
}
self::$anchor_done = true;
$json = class_exists('AdGhost_Key_Values') ? AdGhost_Key_Values::amp_json() : null;
$list = array_values(array_filter(self::sizes($sizes), function ($size) {
return $size[0] <= 480 && $size[1] <= 120;
}));
$first = $list ? $list[0] : [320, 50];
return '';
}
private static function sizes($sizes) {
$out = [];
foreach (preg_split('/[;,]/', (string) $sizes) as $size) {
if (preg_match('/^\s*(\d{1,4})x(\d{1,4})\s*$/', $size, $m) && (int) $m[1] > 1 && (int) $m[2] > 1) {
$out[] = [(int) $m[1], (int) $m[2]];
}
}
usort($out, function ($a, $b) {
return ($b[0] * $b[1]) <=> ($a[0] * $a[1]);
});
return $out;
}
}