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