1da933f89SLORTET<?php 2da933f89SLORTETif (!defined('DOKU_INC')) die(); 3da933f89SLORTET 4da933f89SLORTETclass helper_plugin_pagesicon extends DokuWiki_Plugin 5da933f89SLORTET{ 6*b603bbe1SLORTET private const BUNDLED_DEFAULT_IMAGE_RELATIVE_PATH = 'lib/plugins/pagesicon/images/default_image.png'; 7*b603bbe1SLORTET 8*b603bbe1SLORTET private function getBundledDefaultImagePath(): string { 9*b603bbe1SLORTET return DOKU_INC . self::BUNDLED_DEFAULT_IMAGE_RELATIVE_PATH; 1074a9e763SLORTET } 1174a9e763SLORTET 12*b603bbe1SLORTET private function getBundledDefaultImageUrl(): string { 1374a9e763SLORTET $path = $this->getBundledDefaultImagePath(); 1474a9e763SLORTET if (!@file_exists($path)) return ''; 1574a9e763SLORTET 1674a9e763SLORTET $base = rtrim((string)DOKU_BASE, '/'); 17*b603bbe1SLORTET $url = $base . '/' . self::BUNDLED_DEFAULT_IMAGE_RELATIVE_PATH; 1874a9e763SLORTET $mtime = @filemtime($path); 1974a9e763SLORTET return $this->appendVersionToUrl($url, $mtime ? (int)$mtime : 0); 2074a9e763SLORTET } 2174a9e763SLORTET 22*b603bbe1SLORTET private function getConfiguredDefaultImageMediaID() { 2374a9e763SLORTET $mediaID = cleanID((string)$this->getConf('default_image')); 2474a9e763SLORTET if ($mediaID === '') return false; 2574a9e763SLORTET if (!@file_exists(mediaFN($mediaID))) return false; 2674a9e763SLORTET return $mediaID; 2774a9e763SLORTET } 2874a9e763SLORTET 29*b603bbe1SLORTET private function getMediaMTime(string $mediaID): int { 30da933f89SLORTET $mediaID = cleanID($mediaID); 31da933f89SLORTET if ($mediaID === '') return 0; 32da933f89SLORTET $file = mediaFN($mediaID); 33da933f89SLORTET if (!@file_exists($file)) return 0; 34da933f89SLORTET $mtime = @filemtime($file); 35da933f89SLORTET return $mtime ? (int)$mtime : 0; 36da933f89SLORTET } 37da933f89SLORTET 38*b603bbe1SLORTET private function appendVersionToUrl(string $url, int $mtime): string { 39da933f89SLORTET if ($url === '' || $mtime <= 0) return $url; 40da933f89SLORTET $sep = strpos($url, '?') === false ? '?' : '&'; 41da933f89SLORTET return $url . $sep . 'pi_ts=' . $mtime; 42da933f89SLORTET } 43da933f89SLORTET 44*b603bbe1SLORTET /** 45*b603bbe1SLORTET * Added in version 2026-03-06. 46*b603bbe1SLORTET * Notifies consumers that an icon changed and triggers cache invalidation hooks. 47*b603bbe1SLORTET */ 48*b603bbe1SLORTET public function notifyIconUpdated(string $targetPage, string $action = 'update', string $mediaID = ''): void { 49da933f89SLORTET global $conf; 50da933f89SLORTET 51da933f89SLORTET @io_saveFile($conf['cachedir'] . '/purgefile', time()); 52da933f89SLORTET 53da933f89SLORTET $data = [ 54da933f89SLORTET 'target_page' => cleanID($targetPage), 55da933f89SLORTET 'action' => $action, 56da933f89SLORTET 'media_id' => cleanID($mediaID), 57da933f89SLORTET ]; 58da933f89SLORTET \dokuwiki\Extension\Event::createAndTrigger('PLUGIN_PAGESICON_UPDATED', $data); 59da933f89SLORTET } 60da933f89SLORTET 61*b603bbe1SLORTET /** 62*b603bbe1SLORTET * Added in version 2026-03-11. 63*b603bbe1SLORTET * Returns the configured filename templates for the requested icon variant. 64*b603bbe1SLORTET */ 65*b603bbe1SLORTET public function getVariantTemplates(string $variant): array { 66*b603bbe1SLORTET $confKey = $variant === 'small' ? 'icon_thumbnail_name' : 'icon_name'; 67*b603bbe1SLORTET $raw = (string)$this->getConf($confKey); 68*b603bbe1SLORTET 69*b603bbe1SLORTET if (trim($raw) === '') { 70*b603bbe1SLORTET trigger_error('pagesicon: missing required configuration "' . $confKey . '"', E_USER_WARNING); 71*b603bbe1SLORTET return []; 72*b603bbe1SLORTET } 73*b603bbe1SLORTET 74*b603bbe1SLORTET $templates = array_values(array_unique(array_filter(array_map('trim', explode(';', $raw))))); 75*b603bbe1SLORTET if (!$templates) { 76*b603bbe1SLORTET trigger_error('pagesicon: configuration "' . $confKey . '" does not contain any usable value', E_USER_WARNING); 77*b603bbe1SLORTET } 78*b603bbe1SLORTET 79*b603bbe1SLORTET return $templates; 80*b603bbe1SLORTET } 81*b603bbe1SLORTET 82*b603bbe1SLORTET /** 83*b603bbe1SLORTET * Added in version 2026-03-11. 84*b603bbe1SLORTET * Normalizes an icon filename candidate to its base media name without namespace or extension. 85*b603bbe1SLORTET */ 86*b603bbe1SLORTET public function normalizeIconBaseName(string $name): string { 87*b603bbe1SLORTET $name = trim($name); 88*b603bbe1SLORTET if ($name === '') return ''; 89*b603bbe1SLORTET $name = noNS($name); 90*b603bbe1SLORTET $name = preg_replace('/\.[a-z0-9]+$/i', '', $name); 91*b603bbe1SLORTET $name = cleanID($name); 92*b603bbe1SLORTET return str_replace(':', '', $name); 93*b603bbe1SLORTET } 94*b603bbe1SLORTET 95*b603bbe1SLORTET /** 96*b603bbe1SLORTET * Added in version 2026-03-11. 97*b603bbe1SLORTET * Returns the allowed target base names for an upload, indexed by their normalized value. 98*b603bbe1SLORTET */ 99*b603bbe1SLORTET public function getUploadNameChoices(string $targetPage, string $variant): array { 100*b603bbe1SLORTET $pageID = noNS($targetPage); 101*b603bbe1SLORTET $choices = []; 102*b603bbe1SLORTET 103*b603bbe1SLORTET foreach ($this->getVariantTemplates($variant) as $tpl) { 104*b603bbe1SLORTET $resolved = str_replace('~pagename~', $pageID, $tpl); 105*b603bbe1SLORTET $base = $this->normalizeIconBaseName($resolved); 106*b603bbe1SLORTET if ($base === '') continue; 107*b603bbe1SLORTET $choices[$base] = $base . '.ext'; 108*b603bbe1SLORTET } 109*b603bbe1SLORTET 110*b603bbe1SLORTET return $choices; 111*b603bbe1SLORTET } 112*b603bbe1SLORTET 113*b603bbe1SLORTET private function buildConfiguredCandidatesFromRaw(string $raw, string $namespace, string $pageID): array { 114da933f89SLORTET $configured = []; 115da933f89SLORTET $entries = array_filter(array_map('trim', explode(';', $raw))); 116da933f89SLORTET 117da933f89SLORTET foreach ($entries as $entry) { 118da933f89SLORTET $name = str_replace('~pagename~', $pageID, $entry); 119da933f89SLORTET if ($name === '') continue; 120da933f89SLORTET 121da933f89SLORTET if (strpos($name, ':') === false && $namespace !== '') { 122da933f89SLORTET $configured[] = $namespace . ':' . $name; 123da933f89SLORTET } else { 124da933f89SLORTET $configured[] = ltrim($name, ':'); 125da933f89SLORTET } 126da933f89SLORTET } 127da933f89SLORTET 128da933f89SLORTET return array_values(array_unique($configured)); 129da933f89SLORTET } 130da933f89SLORTET 131*b603bbe1SLORTET private function buildConfiguredCandidates(string $namespace, string $pageID, string $sizeMode): array { 132da933f89SLORTET $bigRaw = trim((string)$this->getConf('icon_name')); 133da933f89SLORTET $smallRaw = trim((string)$this->getConf('icon_thumbnail_name')); 134da933f89SLORTET 135da933f89SLORTET $big = $this->buildConfiguredCandidatesFromRaw($bigRaw, $namespace, $pageID); 136da933f89SLORTET $small = $this->buildConfiguredCandidatesFromRaw($smallRaw, $namespace, $pageID); 137da933f89SLORTET 138da933f89SLORTET if ($sizeMode === 'big') return $big; 139da933f89SLORTET if ($sizeMode === 'small') return $small; 140da933f89SLORTET if ($sizeMode === 'smallorbig') return array_values(array_unique(array_merge($small, $big))); 141da933f89SLORTET 142da933f89SLORTET // Default: bigorsmall 143da933f89SLORTET return array_values(array_unique(array_merge($big, $small))); 144da933f89SLORTET } 145da933f89SLORTET 146*b603bbe1SLORTET private function normalizeSizeMode(string $size): string { 147da933f89SLORTET $size = strtolower(trim($size)); 148da933f89SLORTET $allowed = ['big', 'small', 'bigorsmall', 'smallorbig']; 149da933f89SLORTET if (in_array($size, $allowed, true)) return $size; 150da933f89SLORTET return 'bigorsmall'; 151da933f89SLORTET } 152da933f89SLORTET 153*b603bbe1SLORTET /** 154*b603bbe1SLORTET * Added in version 2026-03-11. 155*b603bbe1SLORTET * Returns the configured list of allowed icon file extensions. 156*b603bbe1SLORTET */ 157*b603bbe1SLORTET public function getConfiguredExtensions(): array { 158da933f89SLORTET $raw = trim((string)$this->getConf('extensions')); 159*b603bbe1SLORTET if ($raw === '') { 160*b603bbe1SLORTET trigger_error('pagesicon: missing required configuration "extensions"', E_USER_WARNING); 161*b603bbe1SLORTET return []; 162*b603bbe1SLORTET } 163da933f89SLORTET 164da933f89SLORTET $extensions = array_values(array_unique(array_filter(array_map(function ($ext) { 165da933f89SLORTET return strtolower(ltrim(trim((string)$ext), '.')); 166da933f89SLORTET }, explode(';', $raw))))); 167da933f89SLORTET 168*b603bbe1SLORTET if (!$extensions) { 169*b603bbe1SLORTET trigger_error('pagesicon: configuration "extensions" does not contain any usable value', E_USER_WARNING); 170da933f89SLORTET } 171da933f89SLORTET 172*b603bbe1SLORTET return $extensions; 173*b603bbe1SLORTET } 174*b603bbe1SLORTET 175*b603bbe1SLORTET private function hasKnownExtension(string $name, array $extensions): bool { 176da933f89SLORTET $fileExt = strtolower((string)pathinfo($name, PATHINFO_EXTENSION)); 177da933f89SLORTET return $fileExt !== '' && in_array($fileExt, $extensions, true); 178da933f89SLORTET } 179da933f89SLORTET 180*b603bbe1SLORTET /** 181*b603bbe1SLORTET * Added in version 2026-03-09. 182*b603bbe1SLORTET * Resolves the icon media ID for a page, or false when no icon matches. 183*b603bbe1SLORTET * Replaces the older getPageImage() name. 184*b603bbe1SLORTET */ 18574a9e763SLORTET public function getPageIconId( 18674a9e763SLORTET string $namespace, 18774a9e763SLORTET string $pageID, 18874a9e763SLORTET string $size = 'bigorsmall' 18974a9e763SLORTET ) 190da933f89SLORTET { 191da933f89SLORTET $sizeMode = $this->normalizeSizeMode($size); 192*b603bbe1SLORTET $extensions = $this->getConfiguredExtensions(); 193da933f89SLORTET $namespace = $namespace ?: ''; 194da933f89SLORTET $pageBase = $namespace ? ($namespace . ':' . $pageID) : $pageID; 195da933f89SLORTET $nsBase = $namespace ? ($namespace . ':') : ''; 196da933f89SLORTET 197da933f89SLORTET $genericBig = [ 198da933f89SLORTET $pageBase, 199da933f89SLORTET $pageBase . ':logo', 200da933f89SLORTET $nsBase . 'logo', 201da933f89SLORTET ]; 202da933f89SLORTET $genericSmall = [ 203da933f89SLORTET $pageBase . ':thumbnail', 204da933f89SLORTET $nsBase . 'thumbnail', 205da933f89SLORTET ]; 206da933f89SLORTET 207da933f89SLORTET if ($sizeMode === 'big') { 208da933f89SLORTET $generic = $genericBig; 209da933f89SLORTET } elseif ($sizeMode === 'small') { 210da933f89SLORTET $generic = $genericSmall; 211da933f89SLORTET } elseif ($sizeMode === 'smallorbig') { 212da933f89SLORTET $generic = array_merge($genericSmall, $genericBig); 213da933f89SLORTET } else { 214da933f89SLORTET $generic = array_merge($genericBig, $genericSmall); 215da933f89SLORTET } 216da933f89SLORTET 217da933f89SLORTET $imageNames = array_merge($this->buildConfiguredCandidates($namespace, $pageID, $sizeMode), $generic); 218da933f89SLORTET 219da933f89SLORTET foreach ($imageNames as $name) { 220da933f89SLORTET if ($this->hasKnownExtension($name, $extensions)) { 221da933f89SLORTET if (@file_exists(mediaFN($name))) return $name; 222da933f89SLORTET continue; 223da933f89SLORTET } 224da933f89SLORTET 225da933f89SLORTET foreach ($extensions as $ext) { 226da933f89SLORTET $path = $name . '.' . $ext; 227da933f89SLORTET if (@file_exists(mediaFN($path))) return $path; 228da933f89SLORTET } 229da933f89SLORTET } 230da933f89SLORTET 231da933f89SLORTET return false; 232da933f89SLORTET } 233da933f89SLORTET 234*b603bbe1SLORTET /** 235*b603bbe1SLORTET * Added in version 2026-03-06. 236*b603bbe1SLORTET * Deprecated since version 2026-03-09, kept for backward compatibility. 237*b603bbe1SLORTET * Use getPageIconId() instead. 238*b603bbe1SLORTET */ 23974a9e763SLORTET public function getPageImage( 24074a9e763SLORTET string $namespace, 24174a9e763SLORTET string $pageID, 24274a9e763SLORTET string $size = 'bigorsmall', 24374a9e763SLORTET bool $withDefault = false 24474a9e763SLORTET ) { 24574a9e763SLORTET return $this->getPageIconId($namespace, $pageID, $size); 24674a9e763SLORTET } 24774a9e763SLORTET 248*b603bbe1SLORTET /** 249*b603bbe1SLORTET * Added in version 2026-03-06. 250*b603bbe1SLORTET * Returns the icon management URL for a page, or null when upload is not allowed. 251*b603bbe1SLORTET */ 252*b603bbe1SLORTET public function getUploadIconPage(string $targetPage = '') { 253da933f89SLORTET global $ID; 254da933f89SLORTET 255da933f89SLORTET $targetPage = cleanID($targetPage); 256da933f89SLORTET if ($targetPage === '') { 257da933f89SLORTET $targetPage = cleanID(getNS((string)$ID)); 258da933f89SLORTET } 259da933f89SLORTET if ($targetPage === '') { 260da933f89SLORTET $targetPage = cleanID((string)$ID); 261da933f89SLORTET } 262da933f89SLORTET if ($targetPage === '') return null; 263da933f89SLORTET 264da933f89SLORTET if (auth_quickaclcheck($targetPage) < AUTH_UPLOAD) { 265da933f89SLORTET return null; 266da933f89SLORTET } 267da933f89SLORTET 268da933f89SLORTET return wl($targetPage, ['do' => 'pagesicon']); 269da933f89SLORTET } 270da933f89SLORTET 271*b603bbe1SLORTET /** 272*b603bbe1SLORTET * Added in version 2026-03-09. 273*b603bbe1SLORTET * Resolves the icon media ID associated with a media file, or false when none matches. 274*b603bbe1SLORTET * Replaces the older getMediaImage() name. 275*b603bbe1SLORTET */ 276*b603bbe1SLORTET public function getMediaIconId(string $mediaID, string $size = 'bigorsmall') { 277da933f89SLORTET $mediaID = cleanID($mediaID); 278da933f89SLORTET if ($mediaID === '') return false; 279da933f89SLORTET 280da933f89SLORTET $namespace = getNS($mediaID); 281da933f89SLORTET $filename = noNS($mediaID); 282da933f89SLORTET $base = (string)pathinfo($filename, PATHINFO_FILENAME); 283da933f89SLORTET $pageID = cleanID($base); 284da933f89SLORTET if ($pageID === '') return false; 285da933f89SLORTET 28674a9e763SLORTET return $this->getPageIconId($namespace, $pageID, $size); 287da933f89SLORTET } 288da933f89SLORTET 289*b603bbe1SLORTET /** 290*b603bbe1SLORTET * Added in version 2026-03-06. 291*b603bbe1SLORTET * Deprecated since version 2026-03-09, kept for backward compatibility. 292*b603bbe1SLORTET * Use getMediaIconId() instead. 293*b603bbe1SLORTET */ 294*b603bbe1SLORTET public function getMediaImage(string $mediaID, string $size = 'bigorsmall', bool $withDefault = false) { 29574a9e763SLORTET return $this->getMediaIconId($mediaID, $size); 29674a9e763SLORTET } 29774a9e763SLORTET 298*b603bbe1SLORTET private function matchesPageIconVariant(string $mediaID, string $namespace, string $pageID): bool { 299*b603bbe1SLORTET $bigIconID = $this->getPageIconId($namespace, $pageID, 'big'); 300*b603bbe1SLORTET if ($bigIconID && cleanID((string)$bigIconID) === $mediaID) return true; 301*b603bbe1SLORTET 302*b603bbe1SLORTET $smallIconID = $this->getPageIconId($namespace, $pageID, 'small'); 303*b603bbe1SLORTET if ($smallIconID && cleanID((string)$smallIconID) === $mediaID) return true; 304*b603bbe1SLORTET 305*b603bbe1SLORTET return false; 306*b603bbe1SLORTET } 307*b603bbe1SLORTET 308*b603bbe1SLORTET /** 309*b603bbe1SLORTET * Added in version 2026-03-11. 310*b603bbe1SLORTET * Checks whether a media ID should be considered a page icon managed by the pagesicon plugin. 311*b603bbe1SLORTET */ 312*b603bbe1SLORTET public function isPageIconMedia(string $mediaID): bool { 313*b603bbe1SLORTET global $conf; 314*b603bbe1SLORTET 315*b603bbe1SLORTET $mediaID = cleanID($mediaID); 316*b603bbe1SLORTET if ($mediaID === '') return false; 317*b603bbe1SLORTET 318*b603bbe1SLORTET $namespace = getNS($mediaID); 319*b603bbe1SLORTET $filename = noNS($mediaID); 320*b603bbe1SLORTET $basename = cleanID((string)pathinfo($filename, PATHINFO_FILENAME)); 321*b603bbe1SLORTET if ($basename === '') return false; 322*b603bbe1SLORTET 323*b603bbe1SLORTET // Case 1: this media is the big or small icon selected for a page with the same base name. 324*b603bbe1SLORTET $sameNamePageID = $namespace !== '' ? ($namespace . ':' . $basename) : $basename; 325*b603bbe1SLORTET if (page_exists($sameNamePageID)) { 326*b603bbe1SLORTET if ($this->matchesPageIconVariant($mediaID, $namespace, $basename)) return true; 327*b603bbe1SLORTET } 328*b603bbe1SLORTET 329*b603bbe1SLORTET // Case 2: this media is the big or small icon selected for a page whose ID matches the namespace. 330*b603bbe1SLORTET if ($namespace !== '' && page_exists($namespace)) { 331*b603bbe1SLORTET $parentNamespace = getNS($namespace); 332*b603bbe1SLORTET $pageID = noNS($namespace); 333*b603bbe1SLORTET if ($this->matchesPageIconVariant($mediaID, $parentNamespace, $pageID)) return true; 334*b603bbe1SLORTET } 335*b603bbe1SLORTET 336*b603bbe1SLORTET // Case 3: this media is the big or small icon selected for a page whose ID 337*b603bbe1SLORTET // matches the namespace leaf, for example "...:playground:playground". 338*b603bbe1SLORTET if ($namespace !== '') { 339*b603bbe1SLORTET $namespaceLeaf = noNS($namespace); 340*b603bbe1SLORTET $leafPageID = cleanID($namespace . ':' . $namespaceLeaf); 341*b603bbe1SLORTET if ($leafPageID !== '' && page_exists($leafPageID)) { 342*b603bbe1SLORTET if ($this->matchesPageIconVariant($mediaID, $namespace, $namespaceLeaf)) return true; 343*b603bbe1SLORTET } 344*b603bbe1SLORTET } 345*b603bbe1SLORTET 346*b603bbe1SLORTET // Case 4: this media is the big or small icon selected for the namespace start page 347*b603bbe1SLORTET // (for example "...:start"), which often carries the visible page content. 348*b603bbe1SLORTET if ($namespace !== '' && isset($conf['start'])) { 349*b603bbe1SLORTET $startId = cleanID((string)$conf['start']); 350*b603bbe1SLORTET $startPage = $startId !== '' ? cleanID($namespace . ':' . $startId) : ''; 351*b603bbe1SLORTET if ($startPage !== '' && page_exists($startPage)) { 352*b603bbe1SLORTET if ($this->matchesPageIconVariant($mediaID, $namespace, noNS($startPage))) return true; 353*b603bbe1SLORTET } 354*b603bbe1SLORTET } 355*b603bbe1SLORTET 356*b603bbe1SLORTET return false; 357*b603bbe1SLORTET } 358*b603bbe1SLORTET 359*b603bbe1SLORTET /** 360*b603bbe1SLORTET * Added in version 2026-03-09. 361*b603bbe1SLORTET * Returns the configured default icon URL, or the bundled fallback image when available. 362*b603bbe1SLORTET */ 363*b603bbe1SLORTET public function getDefaultIconUrl(array $params = ['width' => 55], ?int &$mtime = null) { 36474a9e763SLORTET $mediaID = $this->getConfiguredDefaultImageMediaID(); 36574a9e763SLORTET if ($mediaID) { 36674a9e763SLORTET $mtime = $this->getMediaMTime((string)$mediaID); 36774a9e763SLORTET $url = (string)ml((string)$mediaID, $params); 36874a9e763SLORTET if ($url === '') return false; 36974a9e763SLORTET return $this->appendVersionToUrl($url, $mtime); 37074a9e763SLORTET } 37174a9e763SLORTET 37274a9e763SLORTET $mtime = 0; 37374a9e763SLORTET $bundled = $this->getBundledDefaultImageUrl(); 37474a9e763SLORTET if ($bundled !== '') return $bundled; 37574a9e763SLORTET 37674a9e763SLORTET return false; 37774a9e763SLORTET } 37874a9e763SLORTET 379*b603bbe1SLORTET /** 380*b603bbe1SLORTET * Added in version 2026-03-09. 381*b603bbe1SLORTET * Deprecated since version 2026-03-09, kept for backward compatibility. 382*b603bbe1SLORTET * Use getDefaultIconUrl() instead. 383*b603bbe1SLORTET */ 384*b603bbe1SLORTET public function getDefaultImageIcon(array $params = ['width' => 55], ?int &$mtime = null) { 38574a9e763SLORTET return $this->getDefaultIconUrl($params, $mtime); 38674a9e763SLORTET } 38774a9e763SLORTET 388*b603bbe1SLORTET /** 389*b603bbe1SLORTET * Added in version 2026-03-09. 390*b603bbe1SLORTET * Returns a versioned icon URL for a page, or false when no icon matches. 391*b603bbe1SLORTET * Replaces the older getImageIcon() name. 392*b603bbe1SLORTET */ 39374a9e763SLORTET public function getPageIconUrl( 394da933f89SLORTET string $namespace, 395da933f89SLORTET string $pageID, 396da933f89SLORTET string $size = 'bigorsmall', 397da933f89SLORTET array $params = ['width' => 55], 39874a9e763SLORTET ?int &$mtime = null, 39974a9e763SLORTET bool $withDefault = false 400da933f89SLORTET ) { 40174a9e763SLORTET $mediaID = $this->getPageIconId($namespace, $pageID, $size); 402da933f89SLORTET if (!$mediaID) { 40374a9e763SLORTET if ($withDefault) { 40474a9e763SLORTET return $this->getDefaultIconUrl($params, $mtime); 40574a9e763SLORTET } 406da933f89SLORTET $mtime = 0; 407da933f89SLORTET return false; 408da933f89SLORTET } 409da933f89SLORTET 410da933f89SLORTET $mtime = $this->getMediaMTime((string)$mediaID); 411da933f89SLORTET $url = (string)ml((string)$mediaID, $params); 412da933f89SLORTET if ($url === '') return false; 413da933f89SLORTET return $this->appendVersionToUrl($url, $mtime); 414da933f89SLORTET } 415da933f89SLORTET 416*b603bbe1SLORTET /** 417*b603bbe1SLORTET * Added in version 2026-03-06. 418*b603bbe1SLORTET * Deprecated since version 2026-03-09, kept for backward compatibility. 419*b603bbe1SLORTET * Use getPageIconUrl() instead. 420*b603bbe1SLORTET */ 42174a9e763SLORTET public function getImageIcon( 42274a9e763SLORTET string $namespace, 42374a9e763SLORTET string $pageID, 42474a9e763SLORTET string $size = 'bigorsmall', 42574a9e763SLORTET array $params = ['width' => 55], 42674a9e763SLORTET ?int &$mtime = null, 42774a9e763SLORTET bool $withDefault = false 42874a9e763SLORTET ) { 42974a9e763SLORTET return $this->getPageIconUrl($namespace, $pageID, $size, $params, $mtime, $withDefault); 43074a9e763SLORTET } 43174a9e763SLORTET 432*b603bbe1SLORTET /** 433*b603bbe1SLORTET * Added in version 2026-03-09. 434*b603bbe1SLORTET * Returns a versioned icon URL for a media file, or false when no icon matches. 435*b603bbe1SLORTET * Replaces the older getMediaIcon() name. 436*b603bbe1SLORTET */ 43774a9e763SLORTET public function getMediaIconUrl( 438da933f89SLORTET string $mediaID, 439da933f89SLORTET string $size = 'bigorsmall', 440da933f89SLORTET array $params = ['width' => 55], 44174a9e763SLORTET ?int &$mtime = null, 44274a9e763SLORTET bool $withDefault = false 443da933f89SLORTET ) { 44474a9e763SLORTET $iconMediaID = $this->getMediaIconId($mediaID, $size); 445da933f89SLORTET if (!$iconMediaID) { 44674a9e763SLORTET if ($withDefault) { 44774a9e763SLORTET return $this->getDefaultIconUrl($params, $mtime); 44874a9e763SLORTET } 449da933f89SLORTET $mtime = 0; 450da933f89SLORTET return false; 451da933f89SLORTET } 452da933f89SLORTET 453da933f89SLORTET $mtime = $this->getMediaMTime((string)$iconMediaID); 454da933f89SLORTET $url = (string)ml((string)$iconMediaID, $params); 455da933f89SLORTET if ($url === '') return false; 456da933f89SLORTET return $this->appendVersionToUrl($url, $mtime); 457da933f89SLORTET } 458da933f89SLORTET 459*b603bbe1SLORTET /** 460*b603bbe1SLORTET * Added in version 2026-03-06. 461*b603bbe1SLORTET * Deprecated since version 2026-03-09, kept for backward compatibility. 462*b603bbe1SLORTET * Use getMediaIconUrl() instead. 463*b603bbe1SLORTET */ 46474a9e763SLORTET public function getMediaIcon( 46574a9e763SLORTET string $mediaID, 46674a9e763SLORTET string $size = 'bigorsmall', 46774a9e763SLORTET array $params = ['width' => 55], 46874a9e763SLORTET ?int &$mtime = null, 46974a9e763SLORTET bool $withDefault = false 47074a9e763SLORTET ) { 47174a9e763SLORTET return $this->getMediaIconUrl($mediaID, $size, $params, $mtime, $withDefault); 47274a9e763SLORTET } 47374a9e763SLORTET 474*b603bbe1SLORTET /** 475*b603bbe1SLORTET * Added in version 2026-03-06. 476*b603bbe1SLORTET * Returns the icon management URL associated with a media file, or null when unavailable. 477*b603bbe1SLORTET */ 478*b603bbe1SLORTET public function getUploadMediaIconPage(string $mediaID = '') { 479da933f89SLORTET $mediaID = cleanID($mediaID); 480da933f89SLORTET if ($mediaID === '') return null; 481da933f89SLORTET 482da933f89SLORTET $namespace = getNS($mediaID); 483da933f89SLORTET $filename = noNS($mediaID); 484da933f89SLORTET $base = (string)pathinfo($filename, PATHINFO_FILENAME); 485da933f89SLORTET $targetPage = cleanID($namespace !== '' ? ($namespace . ':' . $base) : $base); 486da933f89SLORTET if ($targetPage === '') return null; 487da933f89SLORTET 488da933f89SLORTET return $this->getUploadIconPage($targetPage); 489da933f89SLORTET } 490da933f89SLORTET} 491