xref: /template/strap/ComboStrap/PageImageTag.php (revision 70bbd7f1f72440223cc13f3495efdcb2b0a11514)
104fd306cSNickeau<?php
204fd306cSNickeau
304fd306cSNickeaunamespace ComboStrap;
404fd306cSNickeau
504fd306cSNickeauuse ComboStrap\Meta\Field\AncestorImage;
604fd306cSNickeauuse ComboStrap\Meta\Field\FeaturedImage;
704fd306cSNickeauuse ComboStrap\TagAttribute\StyleAttribute;
804fd306cSNickeauuse syntax_plugin_combo_iterator;
904fd306cSNickeau
1004fd306cSNickeau
1104fd306cSNickeauclass PageImageTag
1204fd306cSNickeau{
1304fd306cSNickeau
1404fd306cSNickeau    public const CANONICAL = PageImageTag::TAG;
1504fd306cSNickeau    public const VIGNETTE_TYPE = "vignette";
1604fd306cSNickeau    public const DEFAULT_ATTRIBUTE = "default";
1704fd306cSNickeau    public const MARKUP = "page-image";
1804fd306cSNickeau    public const LOGO_TYPE = "logo";
1904fd306cSNickeau    public const DEFAULT_ORDER = [
2004fd306cSNickeau        PageImageTag::FEATURED,
2104fd306cSNickeau        PageImageTag::FIRST_TYPE,
2204fd306cSNickeau        PageImageTag::ANCESTOR_TYPE,
2304fd306cSNickeau        PageImageTag::ICON_TYPE,
2404fd306cSNickeau        PageImageTag::VIGNETTE_TYPE,
2504fd306cSNickeau        PageImageTag::LOGO_TYPE
2604fd306cSNickeau    ];
2704fd306cSNickeau    public const ANCESTOR_TYPE = "ancestor";
2804fd306cSNickeau    public const TAG = "pageimage";
2904fd306cSNickeau    public const FEATURED = "featured";
3004fd306cSNickeau    public const ICON_TYPE = "icon";
3104fd306cSNickeau    public const NONE_TYPE = "none";
3204fd306cSNickeau    public const FIRST_TYPE = "first";
3304fd306cSNickeau
3404fd306cSNickeau    public const TYPES = [
3504fd306cSNickeau        PageImageTag::FEATURED,
3604fd306cSNickeau        PageImageTag::FIRST_TYPE,
3704fd306cSNickeau        PageImageTag::VIGNETTE_TYPE,
3804fd306cSNickeau        PageImageTag::ANCESTOR_TYPE,
3904fd306cSNickeau        PageImageTag::LOGO_TYPE,
4004fd306cSNickeau        PageImageTag::ICON_TYPE
4104fd306cSNickeau    ];
4204fd306cSNickeau    const DEFAULT_ZOOM = -4;
4304fd306cSNickeau
4404fd306cSNickeau
4504fd306cSNickeau    /**
4604fd306cSNickeau     * Because the pageimage can also be used
4704fd306cSNickeau     * in a template
4804fd306cSNickeau     *
4904fd306cSNickeau     * The calculation are done in the {@link syntax_plugin_combo_pageimage::render render function}
5004fd306cSNickeau     *
5104fd306cSNickeau     */
5204fd306cSNickeau    public static function handle($tagAttributes, $handler): array
5304fd306cSNickeau    {
5404fd306cSNickeau
5504fd306cSNickeau        /**
5604fd306cSNickeau         * Context
5704fd306cSNickeau         */
5804fd306cSNickeau        $callStack = CallStack::createFromHandler($handler);
5904fd306cSNickeau        $context = PageImageTag::TAG;
6004fd306cSNickeau        $parent = $callStack->moveToParent();
6104fd306cSNickeau        if ($parent !== false) {
6204fd306cSNickeau            $context = $parent->getTagName();
6304fd306cSNickeau        }
6404fd306cSNickeau
6504fd306cSNickeau        return array(
6604fd306cSNickeau            PluginUtility::ATTRIBUTES => $tagAttributes->toCallStackArray(),
6704fd306cSNickeau            PluginUtility::CONTEXT => $context
6804fd306cSNickeau        );
6904fd306cSNickeau    }
7004fd306cSNickeau
7104fd306cSNickeau    public static function render(TagAttributes $tagAttributes, array $data)
7204fd306cSNickeau    {
7304fd306cSNickeau
7404fd306cSNickeau
7504fd306cSNickeau        /**
7604fd306cSNickeau         * Image selection
7704fd306cSNickeau         */
7804fd306cSNickeau        $path = syntax_plugin_combo_iterator::getContextPathForComponentThatMayBeInFragment($tagAttributes);
7904fd306cSNickeau        $contextPage = MarkupPath::createPageFromPathObject($path);
8004fd306cSNickeau
8104fd306cSNickeau        /**
8204fd306cSNickeau         * Zoom applied only to icon
8304fd306cSNickeau         * but we get and **delete** it
8404fd306cSNickeau         * because it's not a standard html attribute
8504fd306cSNickeau         */
8604fd306cSNickeau        $zoom = $tagAttributes->getValueAndRemoveIfPresent(Dimension::ZOOM_ATTRIBUTE, self::DEFAULT_ZOOM);
8704fd306cSNickeau
8804fd306cSNickeau        /**
8904fd306cSNickeau         * Image Order of precedence
9004fd306cSNickeau         */
9104fd306cSNickeau        $order = self::getOrderOfPreference($tagAttributes);
9204fd306cSNickeau        $imageFetcher = null;
9304fd306cSNickeau        foreach ($order as $pageImageProcessing) {
9404fd306cSNickeau            switch ($pageImageProcessing) {
9504fd306cSNickeau                case PageImageTag::FEATURED:
9604fd306cSNickeau                    try {
9704fd306cSNickeau                        $imagePath = FeaturedImage::createFromResourcePage($contextPage)->getValue();
9804fd306cSNickeau                    } catch (ExceptionNotFound $e) {
9904fd306cSNickeau                        // ok
10004fd306cSNickeau                        continue 2;
10104fd306cSNickeau                    }
10204fd306cSNickeau                    try {
10304fd306cSNickeau                        $imageFetcher = IFetcherLocalImage::createImageFetchFromPath($imagePath);
10404fd306cSNickeau                    } catch (ExceptionNotExists|ExceptionBadArgument|ExceptionBadSyntax $e) {
10504fd306cSNickeau                        LogUtility::warning("Error while creating the fetcher for the feature image ($imagePath) and the page ($contextPage). Error: {$e->getMessage()}", self::CANONICAL, $e);
10604fd306cSNickeau                    }
10704fd306cSNickeau                    break;
10804fd306cSNickeau                case PageImageTag::ANCESTOR_TYPE:
10904fd306cSNickeau                case "parent": // old
11004fd306cSNickeau                    try {
11104fd306cSNickeau                        $ancestor = AncestorImage::createFromResourcePage($contextPage)->getValue();
11204fd306cSNickeau                    } catch (ExceptionNotFound $e) {
11304fd306cSNickeau                        continue 2;
11404fd306cSNickeau                    }
11504fd306cSNickeau                    try {
11604fd306cSNickeau                        $imageFetcher = IFetcherLocalImage::createImageFetchFromPath($ancestor);
11704fd306cSNickeau                    } catch (ExceptionBadArgument|ExceptionBadSyntax|ExceptionNotExists $e) {
11804fd306cSNickeau                        LogUtility::warning("Error while creating the ancestor image handler for the image ($ancestor) and the page ($contextPage). Error: {$e->getMessage()}", self::CANONICAL, $e);
11904fd306cSNickeau                    }
12004fd306cSNickeau                    break;
12104fd306cSNickeau                case PageImageTag::ICON_TYPE:
12204fd306cSNickeau                    try {
12304fd306cSNickeau                        $icon = FeaturedIcon::createForPage($contextPage)->getValueOrDefault();
12404fd306cSNickeau                    } catch (ExceptionNotFound $e) {
12504fd306cSNickeau                        continue 2;
12604fd306cSNickeau                    }
12704fd306cSNickeau
12804fd306cSNickeau                    $width = $tagAttributes->getValueAndRemoveIfPresent(Dimension::WIDTH_KEY);
12904fd306cSNickeau                    $height = $tagAttributes->getValueAndRemoveIfPresent(Dimension::HEIGHT_KEY);
13004fd306cSNickeau                    $ratio = $tagAttributes->getValueAndRemoveIfPresent(Dimension::RATIO_ATTRIBUTE);
13104fd306cSNickeau                    if ($width === null && $height !== null && $ratio === null) {
13204fd306cSNickeau                        $width = $height;
13304fd306cSNickeau                    }
13404fd306cSNickeau                    if ($width !== null && $height !== null && $ratio === null) {
13504fd306cSNickeau                        $height = $width;
13604fd306cSNickeau                    }
13704fd306cSNickeau                    $imageFetcher = FetcherSvg::createSvgFromPath($icon)
13804fd306cSNickeau                        ->setRequestedZoom($zoom);
13904fd306cSNickeau
14004fd306cSNickeau                    if ($ratio !== null) {
14104fd306cSNickeau                        try {
14204fd306cSNickeau                            $imageFetcher->setRequestedAspectRatio($ratio);
14304fd306cSNickeau                        } catch (ExceptionBadSyntax $e) {
14404fd306cSNickeau                            LogUtility::error("The ratio value ($ratio) is not a valid ratio for the icon image ($icon)");
14504fd306cSNickeau                        }
14604fd306cSNickeau                    }
14704fd306cSNickeau                    if ($width !== null) {
148*70bbd7f1Sgerardnico                        try {
149*70bbd7f1Sgerardnico                            $width = ConditionalLength::createFromString($width)->toPixelNumber();
15004fd306cSNickeau                            $imageFetcher->setRequestedWidth($width);
151*70bbd7f1Sgerardnico                        } catch (ExceptionBadArgument $e) {
152*70bbd7f1Sgerardnico                            LogUtility::warning("The width ($width) is not a valid length and was discarded", self::CANONICAL, $e);
153*70bbd7f1Sgerardnico                        }
15404fd306cSNickeau                    }
15504fd306cSNickeau                    if ($height !== null) {
156*70bbd7f1Sgerardnico                        try {
157*70bbd7f1Sgerardnico                            $height = ConditionalLength::createFromString($height)->toPixelNumber();
15804fd306cSNickeau                            $imageFetcher->setRequestedHeight($height);
159*70bbd7f1Sgerardnico                        } catch (ExceptionBadArgument $e) {
160*70bbd7f1Sgerardnico                            LogUtility::warning("The height ($height) is not a valid length and was discarded", self::CANONICAL, $e);
161*70bbd7f1Sgerardnico                        }
16204fd306cSNickeau                    }
16304fd306cSNickeau
16404fd306cSNickeau                    break;
16504fd306cSNickeau                case PageImageTag::FIRST_TYPE:
16604fd306cSNickeau
16704fd306cSNickeau                    try {
16804fd306cSNickeau                        $firstImagePath = FirstImage::createForPage($contextPage)->getValue();
16904fd306cSNickeau                    } catch (ExceptionNotFound $e) {
17004fd306cSNickeau                        continue 2;
17104fd306cSNickeau                    }
17204fd306cSNickeau
17304fd306cSNickeau                    try {
17404fd306cSNickeau                        $imageFetcher = IFetcherLocalImage::createImageFetchFromPath($firstImagePath);
17504fd306cSNickeau                    } catch (ExceptionBadArgument|ExceptionBadSyntax|ExceptionNotExists $e) {
17604fd306cSNickeau                        LogUtility::warning("Error while creating the first image handler for the image ($firstImagePath) and the page ($contextPage). Error: {$e->getMessage()}", self::CANONICAL, $e);
17704fd306cSNickeau                    }
17804fd306cSNickeau                    break;
17904fd306cSNickeau                case PageImageTag::VIGNETTE_TYPE:
18004fd306cSNickeau                    try {
18104fd306cSNickeau                        $imageFetcher = FetcherVignette::createForPage($contextPage);
18204fd306cSNickeau                    } catch (ExceptionNotFound|ExceptionBadArgument $e) {
18304fd306cSNickeau                        LogUtility::warning("Error while creating the vignette for the page ($contextPage). Error: {$e->getMessage()}", self::CANONICAL, $e);
18404fd306cSNickeau                    }
18504fd306cSNickeau                    break;
18604fd306cSNickeau                case PageImageTag::LOGO_TYPE:
18704fd306cSNickeau                    try {
18804fd306cSNickeau                        $imageFetcher = FetcherSvg::createSvgFromPath(Site::getLogoAsSvgImage());
18904fd306cSNickeau                    } catch (ExceptionNotFound $e) {
19004fd306cSNickeau                        LogUtility::info("No page image could be find for the page ($path)", PageImageTag::CANONICAL);
19104fd306cSNickeau                    }
19204fd306cSNickeau                    break;
19304fd306cSNickeau                case PageImageTag::NONE_TYPE:
19404fd306cSNickeau                    return false;
19504fd306cSNickeau                default:
19604fd306cSNickeau                    LogUtility::error("The image ($pageImageProcessing) is an unknown page image type", PageImageTag::CANONICAL);
19704fd306cSNickeau                    continue 2;
19804fd306cSNickeau            }
19904fd306cSNickeau            if ($imageFetcher !== null) {
20004fd306cSNickeau                $tagAttributes->addClassName(StyleAttribute::addComboStrapSuffix($pageImageProcessing));
20104fd306cSNickeau                break;
20204fd306cSNickeau            }
20304fd306cSNickeau        }
20404fd306cSNickeau
20504fd306cSNickeau        if ($imageFetcher === null) {
20604fd306cSNickeau            return false;
20704fd306cSNickeau        }
20804fd306cSNickeau
20904fd306cSNickeau        /**
21004fd306cSNickeau         * Final building
21104fd306cSNickeau         */
21204fd306cSNickeau        try {
21304fd306cSNickeau            $imageFetcher->buildFromTagAttributes($tagAttributes);
21404fd306cSNickeau        } catch (ExceptionBadArgument|ExceptionBadSyntax|ExceptionCompile $e) {
21504fd306cSNickeau            LogUtility::error("The image could not be build. Error: {$e->getMessage()}", PageImageTag::CANONICAL, $e);
21604fd306cSNickeau        }
21704fd306cSNickeau
21804fd306cSNickeau        /**
21904fd306cSNickeau         * Svg
22004fd306cSNickeau         */
22104fd306cSNickeau        if ($imageFetcher instanceof FetcherSvg) {
22204fd306cSNickeau
22304fd306cSNickeau            /**
22404fd306cSNickeau             * This is an illustration image
22504fd306cSNickeau             * Used by svg to color by default with the primary color for instance
22604fd306cSNickeau             *
22704fd306cSNickeau             * (Note that because we use icon as page-image type,
22804fd306cSNickeau             * the buildFromTagAttributes would have set it to icon)
22904fd306cSNickeau             */
23004fd306cSNickeau            $imageFetcher->setRequestedType(FetcherSvg::ILLUSTRATION_TYPE);
23104fd306cSNickeau
23204fd306cSNickeau            /**
23304fd306cSNickeau             * When the width requested is small, no zoom out
23404fd306cSNickeau             */
23504fd306cSNickeau            try {
23604fd306cSNickeau                $requestedWidth = $imageFetcher->getRequestedWidth();
23704fd306cSNickeau                try {
23804fd306cSNickeau                    $pixelWidth = ConditionalLength::createFromString($requestedWidth)->toPixelNumber();
23904fd306cSNickeau                    if ($pixelWidth < 30) {
24004fd306cSNickeau                        /**
24104fd306cSNickeau                         * Icon rendering
24204fd306cSNickeau                         */
24304fd306cSNickeau                        $imageFetcher
24404fd306cSNickeau                            ->setRequestedZoom(1)
24504fd306cSNickeau                            ->setRequestedType(FetcherSvg::ICON_TYPE);
24604fd306cSNickeau
24704fd306cSNickeau                    }
24804fd306cSNickeau                } catch (ExceptionCompile $e) {
24904fd306cSNickeau                    LogUtility::msg("The width value ($requestedWidth) could not be translated in pixel value. Error: {$e->getMessage()}");
25004fd306cSNickeau                }
25104fd306cSNickeau            } catch (ExceptionNotFound $e) {
25204fd306cSNickeau                // no width
25304fd306cSNickeau            }
25404fd306cSNickeau
25504fd306cSNickeau        }
25604fd306cSNickeau
25704fd306cSNickeau
25804fd306cSNickeau        /**
25904fd306cSNickeau         * Img/Svg Tag
26004fd306cSNickeau         *
26104fd306cSNickeau         * Used as an illustration in a card
26204fd306cSNickeau         * If the image is too small, we allow that it will stretch
26304fd306cSNickeau         * to take the whole space
26404fd306cSNickeau         */
26504fd306cSNickeau        if ($data[PluginUtility::CONTEXT] === CardTag::CARD_TAG) {
26604fd306cSNickeau            $tagAttributes->addStyleDeclarationIfNotSet("max-width", "100%");
26704fd306cSNickeau            $tagAttributes->addStyleDeclarationIfNotSet("max-height", "unset");
26804fd306cSNickeau        }
26904fd306cSNickeau
27004fd306cSNickeau
27104fd306cSNickeau        $tagAttributes->setType(self::MARKUP);
27204fd306cSNickeau
27304fd306cSNickeau        try {
27404fd306cSNickeau            return MediaMarkup::createFromFetcher($imageFetcher)
27504fd306cSNickeau                ->buildFromTagAttributes($tagAttributes)
27604fd306cSNickeau                ->toHtml();
27704fd306cSNickeau        } catch (ExceptionCompile $e) {
27804fd306cSNickeau            $message = "Error while rendering the page image: {$e->getMessage()}";
27904fd306cSNickeau            LogUtility::error($message, self::CANONICAL, $e);
28004fd306cSNickeau            return $message;
28104fd306cSNickeau        }
28204fd306cSNickeau
28304fd306cSNickeau    }
28404fd306cSNickeau
28504fd306cSNickeau    public static function getDefaultAttributes(): array
28604fd306cSNickeau    {
28704fd306cSNickeau        return [
28804fd306cSNickeau            MediaMarkup::LINKING_KEY => MediaMarkup::LINKING_NOLINK_VALUE,
28904fd306cSNickeau            TagAttributes::TYPE_KEY => self::FEATURED
29004fd306cSNickeau        ];
29104fd306cSNickeau    }
29204fd306cSNickeau
29304fd306cSNickeau    private static function getOrderOfPreference(TagAttributes $tagAttributes): array
29404fd306cSNickeau    {
29504fd306cSNickeau        // the type is first
29604fd306cSNickeau        $type = $tagAttributes->getType();
29704fd306cSNickeau        $orderOfPreference[] = $type;
29804fd306cSNickeau        // then the default one
29904fd306cSNickeau        $default = $tagAttributes->getValueAndRemoveIfPresent(PageImageTag::DEFAULT_ATTRIBUTE);
30004fd306cSNickeau        if ($default === null) {
30104fd306cSNickeau            $defaultOrderOfPreference = PageImageTag::DEFAULT_ORDER;
30204fd306cSNickeau        } else {
30304fd306cSNickeau            $defaultOrderOfPreference = explode("|", $default);
30404fd306cSNickeau        }
30504fd306cSNickeau        foreach ($defaultOrderOfPreference as $defaultImageOrder) {
30604fd306cSNickeau            if ($defaultImageOrder === $type) {
30704fd306cSNickeau                continue;
30804fd306cSNickeau            }
30904fd306cSNickeau            $orderOfPreference[] = $defaultImageOrder;
31004fd306cSNickeau        }
31104fd306cSNickeau        return $orderOfPreference;
31204fd306cSNickeau    }
31304fd306cSNickeau
31404fd306cSNickeau}
315