xref: /template/strap/ComboStrap/FetcherVignette.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php /** @noinspection PhpComposerExtensionStubsInspection */
2*04fd306cSNickeau
3*04fd306cSNickeaunamespace ComboStrap;
4*04fd306cSNickeau
5*04fd306cSNickeauuse ComboStrap\Web\Url;
6*04fd306cSNickeauuse ComboStrap\Web\UrlRewrite;
7*04fd306cSNickeau
8*04fd306cSNickeau/**
9*04fd306cSNickeau *
10*04fd306cSNickeau * Vignette:
11*04fd306cSNickeau * http://host/lib/exe/fetch.php?media=id:of:page.png&drive=page-vignette
12*04fd306cSNickeau * where:
13*04fd306cSNickeau *   * 'id:of:page' is the page wiki id
14*04fd306cSNickeau *   * 'png' is the format (may be jpeg or webp)
15*04fd306cSNickeau *
16*04fd306cSNickeau * Example when running on Combo
17*04fd306cSNickeau * http://combo.nico.lan/lib/exe/fetch.php?media=howto:getting_started:getting_started.png&drive=page-vignette
18*04fd306cSNickeau * http://combo.nico.lan/lib/exe/fetch.php?media=howto:howto.webp&drive=page-vignette
19*04fd306cSNickeau *
20*04fd306cSNickeau *
21*04fd306cSNickeau * Example/Inspiration in the real world:
22*04fd306cSNickeau * https://lofi.limo/blog/images/write-html-right.png
23*04fd306cSNickeau * https://opengraph.githubassets.com/6b85042cdc8e98725bd85a0e7b159c99104644fbf97402fded205ee4d2036ab9/ComboStrap/combo
24*04fd306cSNickeau */
25*04fd306cSNickeauclass FetcherVignette extends FetcherImage
26*04fd306cSNickeau{
27*04fd306cSNickeau
28*04fd306cSNickeau
29*04fd306cSNickeau    const CANONICAL = self::VIGNETTE_FETCHER_NAME;
30*04fd306cSNickeau
31*04fd306cSNickeau    /**
32*04fd306cSNickeau     * For {@link UrlRewrite}, the property id
33*04fd306cSNickeau     * should be called media
34*04fd306cSNickeau     */
35*04fd306cSNickeau    const MEDIA_NAME_URL_ATTRIBUTE = "media";
36*04fd306cSNickeau    const PNG_EXTENSION = "png";
37*04fd306cSNickeau    const JPG_EXTENSION = "jpg";
38*04fd306cSNickeau    const JPEG_EXTENSION = "jpeg";
39*04fd306cSNickeau    const WEBP_EXTENSION = "webp";
40*04fd306cSNickeau
41*04fd306cSNickeau    const VIGNETTE_FETCHER_NAME = "vignette";
42*04fd306cSNickeau
43*04fd306cSNickeau
44*04fd306cSNickeau    private ?MarkupPath $page = null;
45*04fd306cSNickeau
46*04fd306cSNickeau    private Mime $mime;
47*04fd306cSNickeau
48*04fd306cSNickeau
49*04fd306cSNickeau    private string $buster;
50*04fd306cSNickeau
51*04fd306cSNickeau    private WikiPath $pagePath;
52*04fd306cSNickeau
53*04fd306cSNickeau
54*04fd306cSNickeau    /**
55*04fd306cSNickeau     * @throws ExceptionNotFound - if the page does not exists
56*04fd306cSNickeau     * @throws ExceptionBadArgument - if the mime is not supported or the path of the page is not a wiki path
57*04fd306cSNickeau     */
58*04fd306cSNickeau    public static function createForPage(MarkupPath $page, Mime $mime = null): FetcherVignette
59*04fd306cSNickeau    {
60*04fd306cSNickeau        $fetcherVignette = new FetcherVignette();
61*04fd306cSNickeau        $fetcherVignette->setPage($page);
62*04fd306cSNickeau        if ($mime === null) {
63*04fd306cSNickeau            $mime = Mime::create(Mime::WEBP);
64*04fd306cSNickeau        }
65*04fd306cSNickeau        $fetcherVignette->setMime($mime);
66*04fd306cSNickeau        return $fetcherVignette;
67*04fd306cSNickeau
68*04fd306cSNickeau    }
69*04fd306cSNickeau
70*04fd306cSNickeau    /**
71*04fd306cSNickeau     *
72*04fd306cSNickeau     * @throws ExceptionBadArgument
73*04fd306cSNickeau     */
74*04fd306cSNickeau    public function getFetchPath(): LocalPath
75*04fd306cSNickeau    {
76*04fd306cSNickeau
77*04fd306cSNickeau        $extension = $this->mime->getExtension();
78*04fd306cSNickeau        $cache = new FetcherCache($this);
79*04fd306cSNickeau
80*04fd306cSNickeau        /**
81*04fd306cSNickeau         * Building the cache dependencies
82*04fd306cSNickeau         */
83*04fd306cSNickeau        try {
84*04fd306cSNickeau            $cache->addFileDependency($this->page->getPathObject())
85*04fd306cSNickeau                ->addFileDependency(ClassUtility::getClassPath($this));
86*04fd306cSNickeau        } catch (\ReflectionException $e) {
87*04fd306cSNickeau            // It should not happen but yeah
88*04fd306cSNickeau            LogUtility::internalError("The path of the actual class cannot be determined", self::CANONICAL);
89*04fd306cSNickeau        }
90*04fd306cSNickeau
91*04fd306cSNickeau        /**
92*04fd306cSNickeau         * Can we use the cache ?
93*04fd306cSNickeau         */
94*04fd306cSNickeau        if ($cache->isCacheUsable()) {
95*04fd306cSNickeau            return LocalPath::createFromPathObject($cache->getFile());
96*04fd306cSNickeau        }
97*04fd306cSNickeau
98*04fd306cSNickeau        $width = $this->getIntrinsicWidth();
99*04fd306cSNickeau        $height = $this->getIntrinsicHeight();
100*04fd306cSNickeau
101*04fd306cSNickeau        /**
102*04fd306cSNickeau         * Don't use {@link imagecreate()} otherwise
103*04fd306cSNickeau         * we get color problem while importing the logo
104*04fd306cSNickeau         */
105*04fd306cSNickeau        $vignetteImageHandler = imagecreatetruecolor($width, $height);
106*04fd306cSNickeau        try {
107*04fd306cSNickeau
108*04fd306cSNickeau            /**
109*04fd306cSNickeau             * Background
110*04fd306cSNickeau             * The first call to  {@link imagecolorallocate} fills the background color in palette-based images
111*04fd306cSNickeau             */
112*04fd306cSNickeau            $whiteGdColor = imagecolorallocate($vignetteImageHandler, 255, 255, 255);
113*04fd306cSNickeau            imagefill($vignetteImageHandler, 0, 0, $whiteGdColor);
114*04fd306cSNickeau
115*04fd306cSNickeau            /**
116*04fd306cSNickeau             * Common variable
117*04fd306cSNickeau             */
118*04fd306cSNickeau            $margin = 80;
119*04fd306cSNickeau            $x = $margin;
120*04fd306cSNickeau            $normalFont = Font::getLiberationSansFontRegularPath()->toAbsoluteId();
121*04fd306cSNickeau            $boldFont = Font::getLiberationSansFontBoldPath()->toAbsoluteId();
122*04fd306cSNickeau            try {
123*04fd306cSNickeau                $mutedRgb = ColorRgb::createFromString("gray");
124*04fd306cSNickeau                $blackGdColor = imagecolorallocate($vignetteImageHandler, 0, 0, 0);
125*04fd306cSNickeau                $mutedGdColor = imagecolorallocate($vignetteImageHandler, $mutedRgb->getRed(), $mutedRgb->getGreen(), $mutedRgb->getBlue());
126*04fd306cSNickeau            } catch (ExceptionCompile $e) {
127*04fd306cSNickeau                // internal error, should not happen
128*04fd306cSNickeau                throw new ExceptionBadArgument("Error while getting the muted color. Error: {$e->getMessage()}", self::CANONICAL);
129*04fd306cSNickeau            }
130*04fd306cSNickeau
131*04fd306cSNickeau            /**
132*04fd306cSNickeau             * Category
133*04fd306cSNickeau             */
134*04fd306cSNickeau            try {
135*04fd306cSNickeau                $parentPage = $this->page->getParent();
136*04fd306cSNickeau                $yCategory = 120;
137*04fd306cSNickeau                $categoryFontSize = 40;
138*04fd306cSNickeau                $lineToPrint = $parentPage->getNameOrDefault();
139*04fd306cSNickeau                imagettftext($vignetteImageHandler, $categoryFontSize, 0, $x, $yCategory, $mutedGdColor, $normalFont, $lineToPrint);
140*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
141*04fd306cSNickeau                // No parent
142*04fd306cSNickeau            }
143*04fd306cSNickeau
144*04fd306cSNickeau
145*04fd306cSNickeau            /**
146*04fd306cSNickeau             * Title
147*04fd306cSNickeau             */
148*04fd306cSNickeau            $title = trim($this->page->getTitleOrDefault());
149*04fd306cSNickeau            $titleFontSize = 55;
150*04fd306cSNickeau            $yTitleStart = 210;
151*04fd306cSNickeau            $yTitleActual = $yTitleStart;
152*04fd306cSNickeau            $lineSpace = 25;
153*04fd306cSNickeau            $words = explode(" ", $title);
154*04fd306cSNickeau            $maxCharacterByLine = 20;
155*04fd306cSNickeau            $actualLine = "";
156*04fd306cSNickeau            $lineCount = 0;
157*04fd306cSNickeau            $maxNumberOfLines = 3;
158*04fd306cSNickeau            $break = false;
159*04fd306cSNickeau            foreach ($words as $word) {
160*04fd306cSNickeau                $actualLength = strlen($actualLine);
161*04fd306cSNickeau                if ($actualLength + strlen($word) > $maxCharacterByLine) {
162*04fd306cSNickeau                    $lineCount = $lineCount + 1;
163*04fd306cSNickeau                    $lineToPrint = $actualLine;
164*04fd306cSNickeau                    if ($lineCount >= $maxNumberOfLines) {
165*04fd306cSNickeau                        $lineToPrint = $actualLine . "...";
166*04fd306cSNickeau                        $actualLine = "";
167*04fd306cSNickeau                        $break = true;
168*04fd306cSNickeau                    } else {
169*04fd306cSNickeau                        $actualLine = $word;
170*04fd306cSNickeau                    }
171*04fd306cSNickeau                    imagettftext($vignetteImageHandler, $titleFontSize, 0, $x, $yTitleActual, $blackGdColor, $boldFont, $lineToPrint);
172*04fd306cSNickeau                    $yTitleActual = $yTitleActual + $titleFontSize + $lineSpace;
173*04fd306cSNickeau                    if ($break) {
174*04fd306cSNickeau                        break;
175*04fd306cSNickeau                    }
176*04fd306cSNickeau                } else {
177*04fd306cSNickeau                    if ($actualLine === "") {
178*04fd306cSNickeau                        $actualLine = $word;
179*04fd306cSNickeau                    } else {
180*04fd306cSNickeau                        $actualLine = "$actualLine $word";
181*04fd306cSNickeau                    }
182*04fd306cSNickeau                }
183*04fd306cSNickeau            }
184*04fd306cSNickeau            if ($actualLine !== "") {
185*04fd306cSNickeau                imagettftext($vignetteImageHandler, $titleFontSize, 0, $x, $yTitleActual, $blackGdColor, $boldFont, $actualLine);
186*04fd306cSNickeau            }
187*04fd306cSNickeau
188*04fd306cSNickeau            /**
189*04fd306cSNickeau             * Date
190*04fd306cSNickeau             */
191*04fd306cSNickeau            $yDate = $yTitleStart + 3 * ($titleFontSize + $lineSpace) + 2 * $lineSpace;
192*04fd306cSNickeau            $dateFontSize = 30;
193*04fd306cSNickeau            $mutedGdColor = imagecolorallocate($vignetteImageHandler, $mutedRgb->getRed(), $mutedRgb->getGreen(), $mutedRgb->getBlue());
194*04fd306cSNickeau            $locale = Locale::createForPage($this->page)->getValueOrDefault();
195*04fd306cSNickeau            try {
196*04fd306cSNickeau                $modifiedTimeOrDefault = $this->page->getModifiedTimeOrDefault();
197*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
198*04fd306cSNickeau                LogUtility::errorIfDevOrTest("Error while getting the modified date. Error: {$e->getMessage()}", self::CANONICAL);
199*04fd306cSNickeau                $modifiedTimeOrDefault = new \DateTime();
200*04fd306cSNickeau            }
201*04fd306cSNickeau            try {
202*04fd306cSNickeau                $lineToPrint = Iso8601Date::createFromDateTime($modifiedTimeOrDefault)->formatLocale(null, $locale);
203*04fd306cSNickeau            } catch (ExceptionBadSyntax $e) {
204*04fd306cSNickeau                // should not happen
205*04fd306cSNickeau                LogUtility::errorIfDevOrTest("Error while formatting the modified date. Error: {$e->getMessage()}", self::CANONICAL);
206*04fd306cSNickeau                $lineToPrint = $modifiedTimeOrDefault->format('Y-m-d H:i:s');
207*04fd306cSNickeau            }
208*04fd306cSNickeau            imagettftext($vignetteImageHandler, $dateFontSize, 0, $x, $yDate, $mutedGdColor, $normalFont, $lineToPrint);
209*04fd306cSNickeau
210*04fd306cSNickeau            /**
211*04fd306cSNickeau             * Logo
212*04fd306cSNickeau             */
213*04fd306cSNickeau            try {
214*04fd306cSNickeau
215*04fd306cSNickeau                $imagePath = Site::getLogoAsRasterImage()->getSourcePath();
216*04fd306cSNickeau                $gdOriginalLogo = $this->getGdImageHandler($imagePath);
217*04fd306cSNickeau                $targetLogoWidth = 120;
218*04fd306cSNickeau                $targetLogoHandler = imagescale($gdOriginalLogo, $targetLogoWidth);
219*04fd306cSNickeau                imagecopy($vignetteImageHandler, $targetLogoHandler, 950, 130, 0, 0, $targetLogoWidth, imagesy($targetLogoHandler));
220*04fd306cSNickeau
221*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
222*04fd306cSNickeau                // no logo installed, mime not found, extension not supported
223*04fd306cSNickeau                LogUtility::warning("The vignette could not be created with your logo because of the following error: {$e->getMessage()}");
224*04fd306cSNickeau            }
225*04fd306cSNickeau
226*04fd306cSNickeau            /**
227*04fd306cSNickeau             * Store
228*04fd306cSNickeau             */
229*04fd306cSNickeau            $fileStringPath = $cache->getFile()->toAbsolutePath()->toAbsoluteId();
230*04fd306cSNickeau            switch ($extension) {
231*04fd306cSNickeau                case self::PNG_EXTENSION:
232*04fd306cSNickeau                    imagetruecolortopalette($vignetteImageHandler, false, 255);
233*04fd306cSNickeau                    imagepng($vignetteImageHandler, $fileStringPath);
234*04fd306cSNickeau                    break;
235*04fd306cSNickeau                case self::JPG_EXTENSION:
236*04fd306cSNickeau                case self::JPEG_EXTENSION:
237*04fd306cSNickeau                    imagejpeg($vignetteImageHandler, $fileStringPath);
238*04fd306cSNickeau                    break;
239*04fd306cSNickeau                case self::WEBP_EXTENSION:
240*04fd306cSNickeau                    /**
241*04fd306cSNickeau                     * To True Color to avoid:
242*04fd306cSNickeau                     * `
243*04fd306cSNickeau                     * Fatal error: Palette image not supported by webp
244*04fd306cSNickeau                     * `
245*04fd306cSNickeau                     */
246*04fd306cSNickeau                    imagewebp($vignetteImageHandler, $fileStringPath);
247*04fd306cSNickeau                    break;
248*04fd306cSNickeau                default:
249*04fd306cSNickeau                    LogUtility::internalError("The possible mime error should have been caught in the setter");
250*04fd306cSNickeau            }
251*04fd306cSNickeau
252*04fd306cSNickeau        } finally {
253*04fd306cSNickeau            imagedestroy($vignetteImageHandler);
254*04fd306cSNickeau        }
255*04fd306cSNickeau
256*04fd306cSNickeau
257*04fd306cSNickeau        return $cache->getFile();
258*04fd306cSNickeau    }
259*04fd306cSNickeau
260*04fd306cSNickeau    public function setUseCache(bool $false): FetcherVignette
261*04fd306cSNickeau    {
262*04fd306cSNickeau        $this->useCache = $false;
263*04fd306cSNickeau        return $this;
264*04fd306cSNickeau    }
265*04fd306cSNickeau
266*04fd306cSNickeau    public function getIntrinsicWidth(): int
267*04fd306cSNickeau    {
268*04fd306cSNickeau        return 1200;
269*04fd306cSNickeau    }
270*04fd306cSNickeau
271*04fd306cSNickeau    public function getIntrinsicHeight(): int
272*04fd306cSNickeau    {
273*04fd306cSNickeau        return 600;
274*04fd306cSNickeau    }
275*04fd306cSNickeau
276*04fd306cSNickeau
277*04fd306cSNickeau    /**
278*04fd306cSNickeau     * @throws ExceptionNotFound - unknown mime or unknown extension
279*04fd306cSNickeau     */
280*04fd306cSNickeau    private function getGdImageHandler(WikiPath $imagePath)
281*04fd306cSNickeau    {
282*04fd306cSNickeau        // the gd function needs a local path, not a wiki path
283*04fd306cSNickeau        $imagePath = $imagePath->toLocalPath();
284*04fd306cSNickeau        $extension = FileSystems::getMime($imagePath)->getExtension();
285*04fd306cSNickeau
286*04fd306cSNickeau        switch ($extension) {
287*04fd306cSNickeau            case self::PNG_EXTENSION:
288*04fd306cSNickeau                return imagecreatefrompng($imagePath->toAbsoluteId());
289*04fd306cSNickeau            case self::JPG_EXTENSION:
290*04fd306cSNickeau            case self::JPEG_EXTENSION:
291*04fd306cSNickeau                return imagecreatefromjpeg($imagePath->toAbsoluteId());
292*04fd306cSNickeau            case self::WEBP_EXTENSION:
293*04fd306cSNickeau                return imagecreatefromwebp($imagePath->toAbsoluteId());
294*04fd306cSNickeau            default:
295*04fd306cSNickeau                throw new ExceptionNotFound("Bad mime should have been caught by the setter");
296*04fd306cSNickeau        }
297*04fd306cSNickeau
298*04fd306cSNickeau    }
299*04fd306cSNickeau
300*04fd306cSNickeau
301*04fd306cSNickeau    function getFetchUrl(Url $url = null): Url
302*04fd306cSNickeau    {
303*04fd306cSNickeau
304*04fd306cSNickeau        $vignetteNameValue = $this->pagePath->getWikiId() . "." . $this->mime->getExtension();
305*04fd306cSNickeau        return parent::getFetchUrl($url)
306*04fd306cSNickeau            ->addQueryParameter(self::MEDIA_NAME_URL_ATTRIBUTE, $vignetteNameValue);
307*04fd306cSNickeau
308*04fd306cSNickeau    }
309*04fd306cSNickeau
310*04fd306cSNickeau
311*04fd306cSNickeau    function getBuster(): string
312*04fd306cSNickeau    {
313*04fd306cSNickeau        return $this->buster;
314*04fd306cSNickeau    }
315*04fd306cSNickeau
316*04fd306cSNickeau
317*04fd306cSNickeau    public function getMime(): Mime
318*04fd306cSNickeau    {
319*04fd306cSNickeau        return $this->mime;
320*04fd306cSNickeau    }
321*04fd306cSNickeau
322*04fd306cSNickeau    /**
323*04fd306cSNickeau     * @throws ExceptionBadArgument
324*04fd306cSNickeau     * @throws ExceptionNotFound
325*04fd306cSNickeau     */
326*04fd306cSNickeau    public function buildFromTagAttributes(TagAttributes $tagAttributes): FetcherVignette
327*04fd306cSNickeau    {
328*04fd306cSNickeau
329*04fd306cSNickeau        $vignette = $tagAttributes->getValueAndRemove(self::MEDIA_NAME_URL_ATTRIBUTE);
330*04fd306cSNickeau        if ($vignette === null && $this->page === null) {
331*04fd306cSNickeau            throw new ExceptionBadArgument("The vignette query property is mandatory when the vignette was created without page.");
332*04fd306cSNickeau        }
333*04fd306cSNickeau
334*04fd306cSNickeau        if ($vignette !== null) {
335*04fd306cSNickeau            $lastPoint = strrpos($vignette, ".");
336*04fd306cSNickeau            $extension = substr($vignette, $lastPoint + 1);
337*04fd306cSNickeau            $wikiId = substr($vignette, 0, $lastPoint);
338*04fd306cSNickeau            $this->setPage(MarkupPath::createMarkupFromId($wikiId));
339*04fd306cSNickeau            if (!FileSystems::exists($this->page->getPathObject())) {
340*04fd306cSNickeau                throw new ExceptionNotFound("The page does not exists");
341*04fd306cSNickeau            }
342*04fd306cSNickeau            try {
343*04fd306cSNickeau                $this->setMime(Mime::createFromExtension($extension));
344*04fd306cSNickeau            } catch (ExceptionNotFound $e) {
345*04fd306cSNickeau                throw new ExceptionBadArgument("The vignette mime is unknown. Error: {$e->getMessage()}");
346*04fd306cSNickeau            }
347*04fd306cSNickeau        }
348*04fd306cSNickeau
349*04fd306cSNickeau        parent::buildFromTagAttributes($tagAttributes);
350*04fd306cSNickeau        return $this;
351*04fd306cSNickeau
352*04fd306cSNickeau    }
353*04fd306cSNickeau
354*04fd306cSNickeau
355*04fd306cSNickeau    public function getFetcherName(): string
356*04fd306cSNickeau    {
357*04fd306cSNickeau        return self::VIGNETTE_FETCHER_NAME;
358*04fd306cSNickeau    }
359*04fd306cSNickeau
360*04fd306cSNickeau    /**
361*04fd306cSNickeau     * @throws ExceptionNotFound
362*04fd306cSNickeau     * @throws ExceptionBadArgument - if the markup path is not
363*04fd306cSNickeau     */
364*04fd306cSNickeau    public function setPage(MarkupPath $page): FetcherVignette
365*04fd306cSNickeau    {
366*04fd306cSNickeau        $this->page = $page;
367*04fd306cSNickeau        $path = $this->page->getPathObject();
368*04fd306cSNickeau        if (!($path instanceof WikiPath)) {
369*04fd306cSNickeau            if ($path instanceof LocalPath) {
370*04fd306cSNickeau                $path = $path->toWikiPath();
371*04fd306cSNickeau            } else {
372*04fd306cSNickeau                throw new ExceptionBadArgument("The path of the markup file is not a wiki path and could not be transformed.");
373*04fd306cSNickeau            }
374*04fd306cSNickeau        }
375*04fd306cSNickeau        $this->pagePath = $path;
376*04fd306cSNickeau        $this->buster = FileSystems::getCacheBuster($path);
377*04fd306cSNickeau        return $this;
378*04fd306cSNickeau    }
379*04fd306cSNickeau
380*04fd306cSNickeau    /**
381*04fd306cSNickeau     * @throws ExceptionBadArgument
382*04fd306cSNickeau     */
383*04fd306cSNickeau    public function setMime(Mime $mime): FetcherVignette
384*04fd306cSNickeau    {
385*04fd306cSNickeau        $this->mime = $mime;
386*04fd306cSNickeau        $gdInfo = gd_info();
387*04fd306cSNickeau        $extension = $mime->getExtension();
388*04fd306cSNickeau        switch ($extension) {
389*04fd306cSNickeau            case self::PNG_EXTENSION:
390*04fd306cSNickeau                if (!$gdInfo["PNG Support"]) {
391*04fd306cSNickeau                    throw new ExceptionBadArgument("The extension ($extension) is not supported by the GD library", self::CANONICAL);
392*04fd306cSNickeau                }
393*04fd306cSNickeau                break;
394*04fd306cSNickeau            case self::JPG_EXTENSION:
395*04fd306cSNickeau            case self::JPEG_EXTENSION:
396*04fd306cSNickeau                if (!$gdInfo["JPEG Support"]) {
397*04fd306cSNickeau                    throw new ExceptionBadArgument("The extension ($extension) is not supported by the GD library", self::CANONICAL);
398*04fd306cSNickeau                }
399*04fd306cSNickeau                break;
400*04fd306cSNickeau            case self::WEBP_EXTENSION:
401*04fd306cSNickeau                if (!$gdInfo["WebP Support"]) {
402*04fd306cSNickeau                    throw new ExceptionBadArgument("The extension ($extension) is not supported by the GD library", self::CANONICAL);
403*04fd306cSNickeau                }
404*04fd306cSNickeau                break;
405*04fd306cSNickeau            default:
406*04fd306cSNickeau                throw new ExceptionBadArgument("The mime ($mime) is not supported");
407*04fd306cSNickeau        }
408*04fd306cSNickeau        return $this;
409*04fd306cSNickeau    }
410*04fd306cSNickeau
411*04fd306cSNickeau    public function getLabel(): string
412*04fd306cSNickeau    {
413*04fd306cSNickeau        return ResourceName::getFromPath($this->pagePath);
414*04fd306cSNickeau    }
415*04fd306cSNickeau}
416