1*37748cd8SNickeau<?php 2*37748cd8SNickeau/** 3*37748cd8SNickeau * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved. 4*37748cd8SNickeau * 5*37748cd8SNickeau * This source code is licensed under the GPL license found in the 6*37748cd8SNickeau * COPYING file in the root directory of this source tree. 7*37748cd8SNickeau * 8*37748cd8SNickeau * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 9*37748cd8SNickeau * @author ComboStrap <support@combostrap.com> 10*37748cd8SNickeau * 11*37748cd8SNickeau */ 12*37748cd8SNickeau 13*37748cd8SNickeaunamespace ComboStrap; 14*37748cd8SNickeau 15*37748cd8SNickeaurequire_once(__DIR__ . '/MediaLink.php'); 16*37748cd8SNickeaurequire_once(__DIR__ . '/LazyLoad.php'); 17*37748cd8SNickeaurequire_once(__DIR__ . '/PluginUtility.php'); 18*37748cd8SNickeau 19*37748cd8SNickeau/** 20*37748cd8SNickeau * Image 21*37748cd8SNickeau * This is the class that handles the 22*37748cd8SNickeau * raster image type of the dokuwiki {@link MediaLink} 23*37748cd8SNickeau * 24*37748cd8SNickeau * The real documentation can be found on the image page 25*37748cd8SNickeau * @link https://www.dokuwiki.org/images 26*37748cd8SNickeau * 27*37748cd8SNickeau * Doc: 28*37748cd8SNickeau * https://web.dev/optimize-cls/#images-without-dimensions 29*37748cd8SNickeau * https://web.dev/cls/ 30*37748cd8SNickeau */ 31*37748cd8SNickeauclass RasterImageLink extends MediaLink 32*37748cd8SNickeau{ 33*37748cd8SNickeau 34*37748cd8SNickeau const CANONICAL = "raster"; 35*37748cd8SNickeau const CONF_LAZY_LOADING_ENABLE = "rasterImageLazyLoadingEnable"; 36*37748cd8SNickeau 37*37748cd8SNickeau const RESPONSIVE_CLASS = "img-fluid"; 38*37748cd8SNickeau 39*37748cd8SNickeau const CONF_RESPONSIVE_IMAGE_MARGIN = "responsiveImageMargin"; 40*37748cd8SNickeau const CONF_RETINA_SUPPORT_ENABLED = "retinaRasterImageEnable"; 41*37748cd8SNickeau const LAZY_CLASS = "lazy-raster-combo"; 42*37748cd8SNickeau 43*37748cd8SNickeau const BREAKPOINTS = 44*37748cd8SNickeau array( 45*37748cd8SNickeau "xs" => 375, 46*37748cd8SNickeau "sm" => 576, 47*37748cd8SNickeau "md" => 768, 48*37748cd8SNickeau "lg" => 992 49*37748cd8SNickeau ); 50*37748cd8SNickeau 51*37748cd8SNickeau 52*37748cd8SNickeau private $imageWidth = null; 53*37748cd8SNickeau /** 54*37748cd8SNickeau * @var int 55*37748cd8SNickeau */ 56*37748cd8SNickeau private $imageWeight = null; 57*37748cd8SNickeau /** 58*37748cd8SNickeau * See {@link image_type_to_mime_type} 59*37748cd8SNickeau * @var int 60*37748cd8SNickeau */ 61*37748cd8SNickeau private $imageType; 62*37748cd8SNickeau private $wasAnalyzed = false; 63*37748cd8SNickeau 64*37748cd8SNickeau /** 65*37748cd8SNickeau * @var bool 66*37748cd8SNickeau */ 67*37748cd8SNickeau private $analyzable = false; 68*37748cd8SNickeau 69*37748cd8SNickeau /** 70*37748cd8SNickeau * @var mixed - the mime from the {@link RasterImageLink::analyzeImageIfNeeded()} 71*37748cd8SNickeau */ 72*37748cd8SNickeau private $mime; 73*37748cd8SNickeau 74*37748cd8SNickeau /** 75*37748cd8SNickeau * RasterImageLink constructor. 76*37748cd8SNickeau * @param $ref 77*37748cd8SNickeau * @param TagAttributes $tagAttributes 78*37748cd8SNickeau */ 79*37748cd8SNickeau public function __construct($ref, $tagAttributes = null) 80*37748cd8SNickeau { 81*37748cd8SNickeau parent::__construct($ref, $tagAttributes); 82*37748cd8SNickeau $this->getTagAttributes()->setLogicalTag(self::CANONICAL); 83*37748cd8SNickeau 84*37748cd8SNickeau } 85*37748cd8SNickeau 86*37748cd8SNickeau 87*37748cd8SNickeau /** 88*37748cd8SNickeau * @param string $ampersand 89*37748cd8SNickeau * @param null $localWidth - the asked width - use for responsive image 90*37748cd8SNickeau * @return string|null 91*37748cd8SNickeau */ 92*37748cd8SNickeau public function getUrl($ampersand = DokuwikiUrl::URL_ENCODED_AND, $localWidth = null) 93*37748cd8SNickeau { 94*37748cd8SNickeau 95*37748cd8SNickeau if ($this->exists()) { 96*37748cd8SNickeau 97*37748cd8SNickeau /** 98*37748cd8SNickeau * Link attribute 99*37748cd8SNickeau */ 100*37748cd8SNickeau $att = array(); 101*37748cd8SNickeau 102*37748cd8SNickeau // Width is driving the computation 103*37748cd8SNickeau if ($localWidth != null && $localWidth != $this->getMediaWidth()) { 104*37748cd8SNickeau 105*37748cd8SNickeau $att['w'] = $localWidth; 106*37748cd8SNickeau 107*37748cd8SNickeau // Height 108*37748cd8SNickeau $height = $this->getImgTagHeightValue($localWidth); 109*37748cd8SNickeau if (!empty($height)) { 110*37748cd8SNickeau $att['h'] = $height; 111*37748cd8SNickeau $this->checkWidthAndHeightRatioAndReturnTheGoodValue($localWidth, $height); 112*37748cd8SNickeau } 113*37748cd8SNickeau 114*37748cd8SNickeau 115*37748cd8SNickeau } 116*37748cd8SNickeau 117*37748cd8SNickeau if ($this->getCache()) { 118*37748cd8SNickeau $att[CacheMedia::CACHE_KEY] = $this->getCache(); 119*37748cd8SNickeau } 120*37748cd8SNickeau $direct = true; 121*37748cd8SNickeau 122*37748cd8SNickeau return ml($this->getId(), $att, $direct, $ampersand, true); 123*37748cd8SNickeau 124*37748cd8SNickeau } else { 125*37748cd8SNickeau 126*37748cd8SNickeau return false; 127*37748cd8SNickeau 128*37748cd8SNickeau } 129*37748cd8SNickeau } 130*37748cd8SNickeau 131*37748cd8SNickeau public function getAbsoluteUrl() 132*37748cd8SNickeau { 133*37748cd8SNickeau 134*37748cd8SNickeau return $this->getUrl(); 135*37748cd8SNickeau 136*37748cd8SNickeau } 137*37748cd8SNickeau 138*37748cd8SNickeau 139*37748cd8SNickeau /** 140*37748cd8SNickeau * Render a link 141*37748cd8SNickeau * Snippet derived from {@link \Doku_Renderer_xhtml::internalmedia()} 142*37748cd8SNickeau * A media can be a video also (Use 143*37748cd8SNickeau * @return string 144*37748cd8SNickeau */ 145*37748cd8SNickeau public function renderMediaTag() 146*37748cd8SNickeau { 147*37748cd8SNickeau 148*37748cd8SNickeau 149*37748cd8SNickeau if ($this->exists()) { 150*37748cd8SNickeau 151*37748cd8SNickeau 152*37748cd8SNickeau /** 153*37748cd8SNickeau * No dokuwiki type attribute 154*37748cd8SNickeau */ 155*37748cd8SNickeau $this->tagAttributes->removeComponentAttributeIfPresent(MediaLink::MEDIA_DOKUWIKI_TYPE); 156*37748cd8SNickeau $this->tagAttributes->removeComponentAttributeIfPresent(MediaLink::DOKUWIKI_SRC); 157*37748cd8SNickeau 158*37748cd8SNickeau /** 159*37748cd8SNickeau * Responsive image 160*37748cd8SNickeau * https://getbootstrap.com/docs/5.0/content/images/ 161*37748cd8SNickeau * to apply max-width: 100%; and height: auto; 162*37748cd8SNickeau * 163*37748cd8SNickeau * Even if the resizing is requested by height, 164*37748cd8SNickeau * the height: auto on styling is needed to conserve the ratio 165*37748cd8SNickeau * while scaling down the screen 166*37748cd8SNickeau */ 167*37748cd8SNickeau $this->tagAttributes->addClassName(self::RESPONSIVE_CLASS); 168*37748cd8SNickeau 169*37748cd8SNickeau 170*37748cd8SNickeau /** 171*37748cd8SNickeau * width and height to give the dimension ratio 172*37748cd8SNickeau * They have an effect on the space reservation 173*37748cd8SNickeau * but not on responsive image at all 174*37748cd8SNickeau * To allow responsive height, the height style property is set at auto 175*37748cd8SNickeau * (ie img-fluid in bootstrap) 176*37748cd8SNickeau */ 177*37748cd8SNickeau // The unit is not mandatory in HTML, this is expected to be CSS pixel 178*37748cd8SNickeau // https://html.spec.whatwg.org/multipage/embedded-content-other.html#attr-dim-height 179*37748cd8SNickeau // The HTML validator does not expect an unit otherwise it send an error 180*37748cd8SNickeau // https://validator.w3.org/ 181*37748cd8SNickeau $htmlLengthUnit = ""; 182*37748cd8SNickeau 183*37748cd8SNickeau /** 184*37748cd8SNickeau * Height 185*37748cd8SNickeau * The logical height that the image should take on the page 186*37748cd8SNickeau * 187*37748cd8SNickeau * Note: The style is also set in {@link Dimension::processWidthAndHeight()} 188*37748cd8SNickeau * 189*37748cd8SNickeau * The doc is {@link https://www.dokuwiki.org/images#resizing} 190*37748cd8SNickeau * See the ''0x20'' 191*37748cd8SNickeau */ 192*37748cd8SNickeau $imgTagHeight = $this->getImgTagHeightValue(); 193*37748cd8SNickeau if (!empty($imgTagHeight)) { 194*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("height", $imgTagHeight . $htmlLengthUnit); 195*37748cd8SNickeau } 196*37748cd8SNickeau 197*37748cd8SNickeau 198*37748cd8SNickeau /** 199*37748cd8SNickeau * Width 200*37748cd8SNickeau * 201*37748cd8SNickeau * We create a series of URL 202*37748cd8SNickeau * for different width and let the browser 203*37748cd8SNickeau * download the best one for: 204*37748cd8SNickeau * * the actual container width 205*37748cd8SNickeau * * the actual of screen resolution 206*37748cd8SNickeau * * and the connection speed. 207*37748cd8SNickeau * 208*37748cd8SNickeau * The max-width value is set 209*37748cd8SNickeau */ 210*37748cd8SNickeau $mediaWidthValue = $this->getMediaWidth(); 211*37748cd8SNickeau $srcValue = $this->getUrl(); 212*37748cd8SNickeau 213*37748cd8SNickeau /** 214*37748cd8SNickeau * Responsive image src set building 215*37748cd8SNickeau * We have chosen 216*37748cd8SNickeau * * 375: Iphone6 217*37748cd8SNickeau * * 768: Ipad 218*37748cd8SNickeau * * 1024: Ipad Pro 219*37748cd8SNickeau * 220*37748cd8SNickeau */ 221*37748cd8SNickeau // The image margin applied 222*37748cd8SNickeau $imageMargin = PluginUtility::getConfValue(self::CONF_RESPONSIVE_IMAGE_MARGIN, "20px"); 223*37748cd8SNickeau 224*37748cd8SNickeau 225*37748cd8SNickeau /** 226*37748cd8SNickeau * Srcset and sizes for responsive image 227*37748cd8SNickeau * Width is mandatory for responsive image 228*37748cd8SNickeau * Ref https://developers.google.com/search/docs/advanced/guidelines/google-images#responsive-images 229*37748cd8SNickeau */ 230*37748cd8SNickeau if (!empty($mediaWidthValue)) { 231*37748cd8SNickeau 232*37748cd8SNickeau /** 233*37748cd8SNickeau * The internal intrinsic value of the image 234*37748cd8SNickeau */ 235*37748cd8SNickeau $imgTagWidth = $this->getImgTagWidthValue(); 236*37748cd8SNickeau if (!empty($imgTagWidth)) { 237*37748cd8SNickeau 238*37748cd8SNickeau if (!empty($imgTagHeight)) { 239*37748cd8SNickeau $imgTagWidth = $this->checkWidthAndHeightRatioAndReturnTheGoodValue($imgTagWidth, $imgTagHeight); 240*37748cd8SNickeau } 241*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("width", $imgTagWidth . $htmlLengthUnit); 242*37748cd8SNickeau } 243*37748cd8SNickeau 244*37748cd8SNickeau /** 245*37748cd8SNickeau * Continue 246*37748cd8SNickeau */ 247*37748cd8SNickeau $srcSet = ""; 248*37748cd8SNickeau $sizes = ""; 249*37748cd8SNickeau 250*37748cd8SNickeau /** 251*37748cd8SNickeau * Add smaller sizes 252*37748cd8SNickeau */ 253*37748cd8SNickeau foreach (self::BREAKPOINTS as $breakpointWidth) { 254*37748cd8SNickeau 255*37748cd8SNickeau if ($imgTagWidth > $breakpointWidth) { 256*37748cd8SNickeau 257*37748cd8SNickeau if (!empty($srcSet)) { 258*37748cd8SNickeau $srcSet .= ", "; 259*37748cd8SNickeau $sizes .= ", "; 260*37748cd8SNickeau } 261*37748cd8SNickeau $breakpointWidthMinusMargin = $breakpointWidth - $imageMargin; 262*37748cd8SNickeau $xsmUrl = $this->getUrl(DokuwikiUrl::URL_ENCODED_AND, $breakpointWidthMinusMargin); 263*37748cd8SNickeau $srcSet .= "$xsmUrl {$breakpointWidthMinusMargin}w"; 264*37748cd8SNickeau $sizes .= $this->getSizes($breakpointWidth, $breakpointWidthMinusMargin); 265*37748cd8SNickeau 266*37748cd8SNickeau } 267*37748cd8SNickeau 268*37748cd8SNickeau } 269*37748cd8SNickeau 270*37748cd8SNickeau /** 271*37748cd8SNickeau * Add the last size 272*37748cd8SNickeau * If the image is really small, srcset and sizes are empty 273*37748cd8SNickeau */ 274*37748cd8SNickeau if (!empty($srcSet)) { 275*37748cd8SNickeau $srcSet .= ", "; 276*37748cd8SNickeau $sizes .= ", "; 277*37748cd8SNickeau $srcUrl = $this->getUrl(DokuwikiUrl::URL_ENCODED_AND, $imgTagWidth); 278*37748cd8SNickeau $srcSet .= "$srcUrl {$imgTagWidth}w"; 279*37748cd8SNickeau $sizes .= "{$imgTagWidth}px"; 280*37748cd8SNickeau } 281*37748cd8SNickeau 282*37748cd8SNickeau /** 283*37748cd8SNickeau * Lazy load 284*37748cd8SNickeau */ 285*37748cd8SNickeau $lazyLoad = $this->getLazyLoad(); 286*37748cd8SNickeau if ($lazyLoad) { 287*37748cd8SNickeau 288*37748cd8SNickeau /** 289*37748cd8SNickeau * Snippet Lazy loading 290*37748cd8SNickeau */ 291*37748cd8SNickeau LazyLoad::addLozadSnippet(); 292*37748cd8SNickeau PluginUtility::getSnippetManager()->attachJavascriptSnippetForBar("lozad-raster"); 293*37748cd8SNickeau $this->tagAttributes->addClassName(self::LAZY_CLASS); 294*37748cd8SNickeau $this->tagAttributes->addClassName(LazyLoad::LAZY_CLASS); 295*37748cd8SNickeau 296*37748cd8SNickeau /** 297*37748cd8SNickeau * A small image has no srcset 298*37748cd8SNickeau * 299*37748cd8SNickeau */ 300*37748cd8SNickeau if (!empty($srcSet)) { 301*37748cd8SNickeau 302*37748cd8SNickeau /** 303*37748cd8SNickeau * !!!!! DON'T FOLLOW THIS ADVICE !!!!!!!!! 304*37748cd8SNickeau * https://github.com/aFarkas/lazysizes/#modern-transparent-srcset-pattern 305*37748cd8SNickeau * The transparent image has a fix dimension aspect ratio of 1x1 making 306*37748cd8SNickeau * a bad reserved space for the image 307*37748cd8SNickeau * We use a svg instead 308*37748cd8SNickeau */ 309*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("src", $srcValue); 310*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("srcset", LazyLoad::getPlaceholder($imgTagWidth,$imgTagHeight)); 311*37748cd8SNickeau /** 312*37748cd8SNickeau * We use `data-sizes` and not `sizes` 313*37748cd8SNickeau * because `sizes` without `srcset` 314*37748cd8SNickeau * shows the broken image symbol 315*37748cd8SNickeau * Javascript changes them at the same time 316*37748cd8SNickeau */ 317*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("data-sizes", $sizes); 318*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("data-srcset", $srcSet); 319*37748cd8SNickeau 320*37748cd8SNickeau } else { 321*37748cd8SNickeau 322*37748cd8SNickeau /** 323*37748cd8SNickeau * Small image but there is no little improvement 324*37748cd8SNickeau */ 325*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("data-src", $srcValue); 326*37748cd8SNickeau 327*37748cd8SNickeau } 328*37748cd8SNickeau 329*37748cd8SNickeau LazyLoad::addPlaceholderBackground($this->tagAttributes); 330*37748cd8SNickeau 331*37748cd8SNickeau 332*37748cd8SNickeau } else { 333*37748cd8SNickeau 334*37748cd8SNickeau if (!empty($srcSet)) { 335*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("srcset", $srcSet); 336*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("sizes", $sizes); 337*37748cd8SNickeau } else { 338*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("src", $srcValue); 339*37748cd8SNickeau } 340*37748cd8SNickeau 341*37748cd8SNickeau } 342*37748cd8SNickeau 343*37748cd8SNickeau } else { 344*37748cd8SNickeau 345*37748cd8SNickeau // No width, no responsive possibility 346*37748cd8SNickeau $lazyLoad = $this->getLazyLoad(); 347*37748cd8SNickeau if ($lazyLoad) { 348*37748cd8SNickeau 349*37748cd8SNickeau LazyLoad::addPlaceholderBackground($this->tagAttributes); 350*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("src", LazyLoad::getPlaceholder()); 351*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValue("data-src", $srcValue); 352*37748cd8SNickeau 353*37748cd8SNickeau } 354*37748cd8SNickeau 355*37748cd8SNickeau } 356*37748cd8SNickeau 357*37748cd8SNickeau 358*37748cd8SNickeau /** 359*37748cd8SNickeau * Title (ie alt) 360*37748cd8SNickeau */ 361*37748cd8SNickeau if ($this->tagAttributes->hasComponentAttribute(TagAttributes::TITLE_KEY)) { 362*37748cd8SNickeau $title = $this->tagAttributes->getValueAndRemove(TagAttributes::TITLE_KEY); 363*37748cd8SNickeau $this->tagAttributes->addHtmlAttributeValueIfNotEmpty("alt", $title); 364*37748cd8SNickeau } 365*37748cd8SNickeau 366*37748cd8SNickeau /** 367*37748cd8SNickeau * Create the img element 368*37748cd8SNickeau */ 369*37748cd8SNickeau $htmlAttributes = $this->tagAttributes->toHTMLAttributeString(); 370*37748cd8SNickeau $imgHTML = '<img ' . $htmlAttributes . '/>'; 371*37748cd8SNickeau 372*37748cd8SNickeau } else { 373*37748cd8SNickeau 374*37748cd8SNickeau $imgHTML = "<span class=\"text-danger\">The image ($this) does not exist</span>"; 375*37748cd8SNickeau 376*37748cd8SNickeau } 377*37748cd8SNickeau 378*37748cd8SNickeau return $imgHTML; 379*37748cd8SNickeau } 380*37748cd8SNickeau 381*37748cd8SNickeau /** 382*37748cd8SNickeau * @return int - the width of the image from the file 383*37748cd8SNickeau */ 384*37748cd8SNickeau public 385*37748cd8SNickeau function getMediaWidth() 386*37748cd8SNickeau { 387*37748cd8SNickeau $this->analyzeImageIfNeeded(); 388*37748cd8SNickeau return $this->imageWidth; 389*37748cd8SNickeau } 390*37748cd8SNickeau 391*37748cd8SNickeau /** 392*37748cd8SNickeau * @return int - the height of the image from the file 393*37748cd8SNickeau */ 394*37748cd8SNickeau public 395*37748cd8SNickeau function getMediaHeight() 396*37748cd8SNickeau { 397*37748cd8SNickeau $this->analyzeImageIfNeeded(); 398*37748cd8SNickeau return $this->imageWeight; 399*37748cd8SNickeau } 400*37748cd8SNickeau 401*37748cd8SNickeau private 402*37748cd8SNickeau function analyzeImageIfNeeded() 403*37748cd8SNickeau { 404*37748cd8SNickeau 405*37748cd8SNickeau if (!$this->wasAnalyzed) { 406*37748cd8SNickeau 407*37748cd8SNickeau if ($this->exists()) { 408*37748cd8SNickeau 409*37748cd8SNickeau /** 410*37748cd8SNickeau * Based on {@link media_image_preview_size()} 411*37748cd8SNickeau * $dimensions = media_image_preview_size($this->id, '', false); 412*37748cd8SNickeau */ 413*37748cd8SNickeau $imageInfo = array(); 414*37748cd8SNickeau $imageSize = getimagesize($this->getFileSystemPath(), $imageInfo); 415*37748cd8SNickeau if ($imageSize === false) { 416*37748cd8SNickeau $this->analyzable = false; 417*37748cd8SNickeau LogUtility::msg("We couldn't retrieve the type and dimensions of the image ($this). The image format seems to be not supported.", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 418*37748cd8SNickeau } else { 419*37748cd8SNickeau $this->analyzable = true; 420*37748cd8SNickeau $this->imageWidth = (int)$imageSize[0]; 421*37748cd8SNickeau if (empty($this->imageWidth)) { 422*37748cd8SNickeau $this->analyzable = false; 423*37748cd8SNickeau } 424*37748cd8SNickeau $this->imageWeight = (int)$imageSize[1]; 425*37748cd8SNickeau if (empty($this->imageWeight)) { 426*37748cd8SNickeau $this->analyzable = false; 427*37748cd8SNickeau } 428*37748cd8SNickeau $this->imageType = (int)$imageSize[2]; 429*37748cd8SNickeau $this->mime = $imageSize[3]; 430*37748cd8SNickeau } 431*37748cd8SNickeau } 432*37748cd8SNickeau } 433*37748cd8SNickeau $this->wasAnalyzed = true; 434*37748cd8SNickeau } 435*37748cd8SNickeau 436*37748cd8SNickeau 437*37748cd8SNickeau /** 438*37748cd8SNickeau * 439*37748cd8SNickeau * @return bool true if we could extract the dimensions 440*37748cd8SNickeau */ 441*37748cd8SNickeau public 442*37748cd8SNickeau function isAnalyzable() 443*37748cd8SNickeau { 444*37748cd8SNickeau $this->analyzeImageIfNeeded(); 445*37748cd8SNickeau return $this->analyzable; 446*37748cd8SNickeau 447*37748cd8SNickeau } 448*37748cd8SNickeau 449*37748cd8SNickeau 450*37748cd8SNickeau public function getRequestedHeight() 451*37748cd8SNickeau { 452*37748cd8SNickeau $requestedHeight = parent::getRequestedHeight(); 453*37748cd8SNickeau if (!empty($requestedHeight)) { 454*37748cd8SNickeau // it should not be bigger than the media Height 455*37748cd8SNickeau $mediaHeight = $this->getMediaHeight(); 456*37748cd8SNickeau if (!empty($mediaHeight)) { 457*37748cd8SNickeau if ($requestedHeight > $mediaHeight) { 458*37748cd8SNickeau LogUtility::msg("For the image ($this), the requested height of ($requestedHeight) can not be bigger than the intrinsic height of ($mediaHeight). The height was then set to its natural height ($mediaHeight)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 459*37748cd8SNickeau $requestedHeight = $mediaHeight; 460*37748cd8SNickeau } 461*37748cd8SNickeau } 462*37748cd8SNickeau } 463*37748cd8SNickeau return $requestedHeight; 464*37748cd8SNickeau } 465*37748cd8SNickeau 466*37748cd8SNickeau public function getRequestedWidth() 467*37748cd8SNickeau { 468*37748cd8SNickeau $requestedWidth = parent::getRequestedWidth(); 469*37748cd8SNickeau if (!empty($requestedWidth)) { 470*37748cd8SNickeau // it should not be bigger than the media Height 471*37748cd8SNickeau $mediaWidth = $this->getMediaWidth(); 472*37748cd8SNickeau if (!empty($mediaWidth)) { 473*37748cd8SNickeau if ($requestedWidth > $mediaWidth) { 474*37748cd8SNickeau global $ID; 475*37748cd8SNickeau if ($ID != "wiki:syntax") { 476*37748cd8SNickeau // There is a bug in the wiki syntax page 477*37748cd8SNickeau // {{wiki:dokuwiki-128.png?200x50}} 478*37748cd8SNickeau // https://forum.dokuwiki.org/d/19313-bugtypo-how-to-make-a-request-to-change-the-syntax-page-on-dokuwikii 479*37748cd8SNickeau LogUtility::msg("For the image ($this), the requested width of ($requestedWidth) can not be bigger than the intrinsic width of ($mediaWidth). The width was then set to its natural width ($mediaWidth)", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 480*37748cd8SNickeau } 481*37748cd8SNickeau $requestedWidth = $mediaWidth; 482*37748cd8SNickeau } 483*37748cd8SNickeau } 484*37748cd8SNickeau } 485*37748cd8SNickeau return $requestedWidth; 486*37748cd8SNickeau } 487*37748cd8SNickeau 488*37748cd8SNickeau 489*37748cd8SNickeau public 490*37748cd8SNickeau function getLazyLoad() 491*37748cd8SNickeau { 492*37748cd8SNickeau $lazyLoad = parent::getLazyLoad(); 493*37748cd8SNickeau if ($lazyLoad !== null) { 494*37748cd8SNickeau return $lazyLoad; 495*37748cd8SNickeau } else { 496*37748cd8SNickeau return PluginUtility::getConfValue(RasterImageLink::CONF_LAZY_LOADING_ENABLE); 497*37748cd8SNickeau } 498*37748cd8SNickeau } 499*37748cd8SNickeau 500*37748cd8SNickeau /** 501*37748cd8SNickeau * @param $screenWidth 502*37748cd8SNickeau * @param $imageWidth 503*37748cd8SNickeau * @return string sizes with a dpi correction if 504*37748cd8SNickeau */ 505*37748cd8SNickeau private 506*37748cd8SNickeau function getSizes($screenWidth, $imageWidth) 507*37748cd8SNickeau { 508*37748cd8SNickeau 509*37748cd8SNickeau if ($this->getWithDpiCorrection()) { 510*37748cd8SNickeau $dpiBase = 96; 511*37748cd8SNickeau $sizes = "(max-width: {$screenWidth}px) and (min-resolution:" . (3 * $dpiBase) . "dpi) " . intval($imageWidth / 3) . "px"; 512*37748cd8SNickeau $sizes .= ", (max-width: {$screenWidth}px) and (min-resolution:" . (2 * $dpiBase) . "dpi) " . intval($imageWidth / 2) . "px"; 513*37748cd8SNickeau $sizes .= ", (max-width: {$screenWidth}px) and (min-resolution:" . (1 * $dpiBase) . "dpi) {$imageWidth}px"; 514*37748cd8SNickeau } else { 515*37748cd8SNickeau $sizes = "(max-width: {$screenWidth}px) {$imageWidth}px"; 516*37748cd8SNickeau } 517*37748cd8SNickeau return $sizes; 518*37748cd8SNickeau } 519*37748cd8SNickeau 520*37748cd8SNickeau /** 521*37748cd8SNickeau * Return if the DPI correction is enabled or not for responsive image 522*37748cd8SNickeau * 523*37748cd8SNickeau * Mobile have a higher DPI and can then fit a bigger image on a smaller size. 524*37748cd8SNickeau * 525*37748cd8SNickeau * This can be disturbing when debugging responsive sizing image 526*37748cd8SNickeau * If you want also to use less bandwidth, this is also useful. 527*37748cd8SNickeau * 528*37748cd8SNickeau * @return bool 529*37748cd8SNickeau */ 530*37748cd8SNickeau private 531*37748cd8SNickeau function getWithDpiCorrection() 532*37748cd8SNickeau { 533*37748cd8SNickeau /** 534*37748cd8SNickeau * Support for retina means no DPI correction 535*37748cd8SNickeau */ 536*37748cd8SNickeau $retinaEnabled = PluginUtility::getConfValue(self::CONF_RETINA_SUPPORT_ENABLED, 0); 537*37748cd8SNickeau return !$retinaEnabled; 538*37748cd8SNickeau } 539*37748cd8SNickeau 540*37748cd8SNickeau 541*37748cd8SNickeau} 542