137748cd8SNickeau<?php 237748cd8SNickeau/** 337748cd8SNickeau * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved. 437748cd8SNickeau * 537748cd8SNickeau * This source code is licensed under the GPL license found in the 637748cd8SNickeau * COPYING file in the root directory of this source tree. 737748cd8SNickeau * 837748cd8SNickeau * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 937748cd8SNickeau * @author ComboStrap <support@combostrap.com> 1037748cd8SNickeau * 1137748cd8SNickeau */ 1237748cd8SNickeau 1337748cd8SNickeaunamespace ComboStrap; 1437748cd8SNickeau 1537748cd8SNickeau 16c3437056SNickeauuse JsonSerializable; 17c3437056SNickeau 18*4cadd4f8SNickeau/** 19*4cadd4f8SNickeau * Class Snippet 20*4cadd4f8SNickeau * @package ComboStrap 21*4cadd4f8SNickeau * A HTML tag: 22*4cadd4f8SNickeau * * CSS: link for href or style with content 23*4cadd4f8SNickeau * * Javascript: script 24*4cadd4f8SNickeau * 25*4cadd4f8SNickeau * A component to manage the extra HTML that 26*4cadd4f8SNickeau * comes from components and that should come in the head HTML node 27*4cadd4f8SNickeau * 28*4cadd4f8SNickeau */ 29c3437056SNickeauclass Snippet implements JsonSerializable 3037748cd8SNickeau{ 3137748cd8SNickeau /** 3237748cd8SNickeau * The head in css format 3337748cd8SNickeau * We need to add the style node 3437748cd8SNickeau */ 35*4cadd4f8SNickeau const EXTENSION_CSS = "css"; 3637748cd8SNickeau /** 3737748cd8SNickeau * The head in javascript 3837748cd8SNickeau * We need to wrap it in a script node 3937748cd8SNickeau */ 40*4cadd4f8SNickeau const EXTENSION_JS = "js"; 41*4cadd4f8SNickeau 4237748cd8SNickeau /** 43*4cadd4f8SNickeau * Properties of the JSON array 4437748cd8SNickeau */ 45*4cadd4f8SNickeau const JSON_TYPE_PROPERTY = "type"; // mandatory 46*4cadd4f8SNickeau const JSON_COMPONENT_PROPERTY = "component"; // mandatory 47*4cadd4f8SNickeau const JSON_EXTENSION_PROPERTY = "extension"; // mandatory 48*4cadd4f8SNickeau const JSON_URL_PROPERTY = "url"; // mandatory if external 49c3437056SNickeau const JSON_CRITICAL_PROPERTY = "critical"; 50*4cadd4f8SNickeau const JSON_ASYNC_PROPERTY = "async"; 51c3437056SNickeau const JSON_CONTENT_PROPERTY = "content"; 52*4cadd4f8SNickeau const JSON_INTEGRITY_PROPERTY = "integrity"; 53*4cadd4f8SNickeau const JSON_HTML_ATTRIBUTES_PROPERTY = "attributes"; 54*4cadd4f8SNickeau 55*4cadd4f8SNickeau /** 56*4cadd4f8SNickeau * The type identifier for a script snippet 57*4cadd4f8SNickeau * (ie inline javascript or style) 58*4cadd4f8SNickeau * 59*4cadd4f8SNickeau * To make the difference with library 60*4cadd4f8SNickeau * that have already an identifier with the url value 61*4cadd4f8SNickeau * (ie external) 62*4cadd4f8SNickeau */ 63*4cadd4f8SNickeau const INTERNAL_TYPE = "internal"; 64*4cadd4f8SNickeau const EXTERNAL_TYPE = "external"; 65*4cadd4f8SNickeau 66*4cadd4f8SNickeau /** 67*4cadd4f8SNickeau * When a snippet is scoped to the request 68*4cadd4f8SNickeau * (ie not saved with a slot) 69*4cadd4f8SNickeau * 70*4cadd4f8SNickeau * They are unique on a request scope 71*4cadd4f8SNickeau * 72*4cadd4f8SNickeau * TlDR: The snippet does not depends to a slot and cannot therefore be cached along. 73*4cadd4f8SNickeau * 74*4cadd4f8SNickeau * The code that adds this snippet is not created by the parsing of content 75*4cadd4f8SNickeau * or depends on the page. 76*4cadd4f8SNickeau * 77*4cadd4f8SNickeau * It's always called and add the snippet whatsoever. 78*4cadd4f8SNickeau * Generally, this is an action plugin with a `TPL_METAHEADER_OUTPUT` hook 79*4cadd4f8SNickeau * such as {@link Bootstrap}, {@link HistoricalBreadcrumbMenuItem}, 80*4cadd4f8SNickeau * ,... 81*4cadd4f8SNickeau */ 82*4cadd4f8SNickeau const REQUEST_SLOT = "request"; 83*4cadd4f8SNickeau 84*4cadd4f8SNickeau 85*4cadd4f8SNickeau protected static $globalSnippets; 8637748cd8SNickeau 8737748cd8SNickeau private $snippetId; 88*4cadd4f8SNickeau private $extension; 8937748cd8SNickeau 9037748cd8SNickeau /** 9137748cd8SNickeau * @var bool 9237748cd8SNickeau */ 93c3437056SNickeau private $critical; 9437748cd8SNickeau 9537748cd8SNickeau /** 9637748cd8SNickeau * @var string the text script / style (may be null if it's an external resources) 9737748cd8SNickeau */ 98*4cadd4f8SNickeau private $inlineContent; 99*4cadd4f8SNickeau 10037748cd8SNickeau /** 101*4cadd4f8SNickeau * @var string 10237748cd8SNickeau */ 103*4cadd4f8SNickeau private $url; 104*4cadd4f8SNickeau /** 105*4cadd4f8SNickeau * @var string 106*4cadd4f8SNickeau */ 107*4cadd4f8SNickeau private $integrity; 108*4cadd4f8SNickeau /** 109*4cadd4f8SNickeau * @var array Extra html attributes if needed 110*4cadd4f8SNickeau */ 111*4cadd4f8SNickeau private $htmlAttributes; 112*4cadd4f8SNickeau 113*4cadd4f8SNickeau /** 114*4cadd4f8SNickeau * @var string ie internal or external 115*4cadd4f8SNickeau */ 116*4cadd4f8SNickeau private $type; 117*4cadd4f8SNickeau /** 118*4cadd4f8SNickeau * @var string The name of the component (used for internal style sheet to retrieve the file) 119*4cadd4f8SNickeau */ 120*4cadd4f8SNickeau private $componentName; 121*4cadd4f8SNickeau 122*4cadd4f8SNickeau /** 123*4cadd4f8SNickeau * @var array - the slots that needs this snippet (as key to get only one snippet by scope) 124*4cadd4f8SNickeau * A special slot exists for {@link Snippet::REQUEST_SLOT} 125*4cadd4f8SNickeau * where a snippet is for the whole requested page 126*4cadd4f8SNickeau * 127*4cadd4f8SNickeau * It's also used in the cache because not all bars 128*4cadd4f8SNickeau * may render at the same time due to the other been cached. 129*4cadd4f8SNickeau * 130*4cadd4f8SNickeau * There is two scope: 131*4cadd4f8SNickeau * * a slot - cached along the HTML 132*4cadd4f8SNickeau * * or {@link Snippet::REQUEST_SLOT} - never cached 133*4cadd4f8SNickeau */ 134*4cadd4f8SNickeau private $slots; 135*4cadd4f8SNickeau /** 136*4cadd4f8SNickeau * @var bool run as soon as possible 137*4cadd4f8SNickeau */ 138*4cadd4f8SNickeau private $async; 13937748cd8SNickeau 14037748cd8SNickeau /** 14137748cd8SNickeau * Snippet constructor. 14237748cd8SNickeau */ 143*4cadd4f8SNickeau public function __construct($snippetId, $mime, $type, $url, $componentId) 14437748cd8SNickeau { 14537748cd8SNickeau $this->snippetId = $snippetId; 146*4cadd4f8SNickeau $this->extension = $mime; 147*4cadd4f8SNickeau $this->type = $type; 148*4cadd4f8SNickeau $this->url = $url; 149*4cadd4f8SNickeau $this->componentName = $componentId; 15037748cd8SNickeau } 15137748cd8SNickeau 152*4cadd4f8SNickeau 153*4cadd4f8SNickeau public static function createInternalCssSnippet($componentId): Snippet 15437748cd8SNickeau { 155*4cadd4f8SNickeau return self::getOrCreateSnippet(self::INTERNAL_TYPE, self::EXTENSION_CSS, $componentId); 15637748cd8SNickeau } 15737748cd8SNickeau 15837748cd8SNickeau 15937748cd8SNickeau /** 160*4cadd4f8SNickeau * @param $componentId 16137748cd8SNickeau * @return Snippet 162c3437056SNickeau * @deprecated You should create a snippet with a known type, this constructor was created for refactoring 16337748cd8SNickeau */ 164*4cadd4f8SNickeau public static function createUnknownSnippet($componentId): Snippet 16537748cd8SNickeau { 166*4cadd4f8SNickeau return new Snippet("unknown", "unknwon", "unknwon", "unknwon", $componentId); 167*4cadd4f8SNickeau } 168*4cadd4f8SNickeau 169*4cadd4f8SNickeau public static function &getOrCreateSnippet(string $identifier, string $extension, string $componentId): Snippet 170*4cadd4f8SNickeau { 171*4cadd4f8SNickeau 172*4cadd4f8SNickeau /** 173*4cadd4f8SNickeau * The snippet id is the url for external resources (ie external javascript / stylesheet) 174*4cadd4f8SNickeau * otherwise if it's internal, it's the component id and it's type 175*4cadd4f8SNickeau * @param string $componentId 176*4cadd4f8SNickeau * @param string $identifier 177*4cadd4f8SNickeau * @return string 178*4cadd4f8SNickeau */ 179*4cadd4f8SNickeau if ($identifier === Snippet::INTERNAL_TYPE) { 180*4cadd4f8SNickeau $snippetId = $identifier . "-" . $extension . "-" . $componentId; 181*4cadd4f8SNickeau $type = self::INTERNAL_TYPE; 182*4cadd4f8SNickeau $url = null; 183*4cadd4f8SNickeau } else { 184*4cadd4f8SNickeau $type = self::EXTERNAL_TYPE; 185*4cadd4f8SNickeau $snippetId = $identifier; 186*4cadd4f8SNickeau $url = $identifier; 187*4cadd4f8SNickeau } 188*4cadd4f8SNickeau $requestedPageId = PluginUtility::getRequestedWikiId(); 189*4cadd4f8SNickeau if ($requestedPageId === null) { 190*4cadd4f8SNickeau if (PluginUtility::isTest()) { 191*4cadd4f8SNickeau $requestedPageId = "test-id"; 192*4cadd4f8SNickeau } else { 193*4cadd4f8SNickeau $requestedPageId = "unknown"; 194*4cadd4f8SNickeau LogUtility::msg("The requested id is unknown. We couldn't scope the snippets."); 195*4cadd4f8SNickeau } 196*4cadd4f8SNickeau } 197*4cadd4f8SNickeau $snippets = &self::$globalSnippets[$requestedPageId]; 198*4cadd4f8SNickeau if ($snippets === null) { 199*4cadd4f8SNickeau self::$globalSnippets = null; 200*4cadd4f8SNickeau self::$globalSnippets[$requestedPageId] = []; 201*4cadd4f8SNickeau $snippets = &self::$globalSnippets[$requestedPageId]; 202*4cadd4f8SNickeau } 203*4cadd4f8SNickeau $snippet = &$snippets[$snippetId]; 204*4cadd4f8SNickeau if ($snippet === null) { 205*4cadd4f8SNickeau $snippets[$snippetId] = new Snippet($snippetId, $extension, $type, $url, $componentId); 206*4cadd4f8SNickeau $snippet = &$snippets[$snippetId]; 207*4cadd4f8SNickeau } 208*4cadd4f8SNickeau return $snippet; 209*4cadd4f8SNickeau 210*4cadd4f8SNickeau } 211*4cadd4f8SNickeau 212*4cadd4f8SNickeau public static function reset() 213*4cadd4f8SNickeau { 214*4cadd4f8SNickeau self::$globalSnippets = null; 215*4cadd4f8SNickeau } 216*4cadd4f8SNickeau 217*4cadd4f8SNickeau /** 218*4cadd4f8SNickeau * @return Snippet[]|null 219*4cadd4f8SNickeau */ 220*4cadd4f8SNickeau public static function getSnippets(): ?array 221*4cadd4f8SNickeau { 222*4cadd4f8SNickeau if (self::$globalSnippets === null) { 223*4cadd4f8SNickeau return null; 224*4cadd4f8SNickeau } 225*4cadd4f8SNickeau $keys = array_keys(self::$globalSnippets); 226*4cadd4f8SNickeau return self::$globalSnippets[$keys[0]]; 22737748cd8SNickeau } 22837748cd8SNickeau 22937748cd8SNickeau 23037748cd8SNickeau /** 23137748cd8SNickeau * @param $bool - if the snippet is critical, it would not be deferred or preloaded 23237748cd8SNickeau * @return Snippet for chaining 23337748cd8SNickeau * All css that are for animation or background for instance 23437748cd8SNickeau * should not be set as critical as they are not needed to paint 23537748cd8SNickeau * exactly the page 236*4cadd4f8SNickeau * 237*4cadd4f8SNickeau * If a snippet is critical, it should not be deferred 238*4cadd4f8SNickeau * 239*4cadd4f8SNickeau * By default: 240*4cadd4f8SNickeau * * all css are critical (except animation or background stylesheet) 241*4cadd4f8SNickeau * * all javascript are not critical 242*4cadd4f8SNickeau * 243*4cadd4f8SNickeau * This attribute is passed in the dokuwiki array 244*4cadd4f8SNickeau * The value is stored in the {@link Snippet::getCritical()} 24537748cd8SNickeau */ 246c3437056SNickeau public function setCritical($bool): Snippet 24737748cd8SNickeau { 24837748cd8SNickeau $this->critical = $bool; 24937748cd8SNickeau return $this; 25037748cd8SNickeau } 25137748cd8SNickeau 25237748cd8SNickeau /** 253*4cadd4f8SNickeau * If the library does not manipulate the DOM, 254*4cadd4f8SNickeau * it can be ran as soon as possible (ie async) 255*4cadd4f8SNickeau * @param $bool 256*4cadd4f8SNickeau * @return $this 257*4cadd4f8SNickeau */ 258*4cadd4f8SNickeau public function setDoesManipulateTheDomOnRun($bool): Snippet 259*4cadd4f8SNickeau { 260*4cadd4f8SNickeau $this->async = !$bool; 261*4cadd4f8SNickeau return $this; 262*4cadd4f8SNickeau } 263*4cadd4f8SNickeau 264*4cadd4f8SNickeau /** 265*4cadd4f8SNickeau * @param $inlineContent - Set an inline content for a script or stylesheet 26637748cd8SNickeau * @return Snippet for chaining 26737748cd8SNickeau */ 268*4cadd4f8SNickeau public function setInlineContent($inlineContent): Snippet 26937748cd8SNickeau { 270*4cadd4f8SNickeau $this->inlineContent = $inlineContent; 27137748cd8SNickeau return $this; 27237748cd8SNickeau } 27337748cd8SNickeau 27437748cd8SNickeau /** 27537748cd8SNickeau * @return string 27637748cd8SNickeau */ 277*4cadd4f8SNickeau public function getInternalDynamicContent(): ?string 27837748cd8SNickeau { 279*4cadd4f8SNickeau return $this->inlineContent; 280*4cadd4f8SNickeau } 281*4cadd4f8SNickeau 282*4cadd4f8SNickeau /** 283*4cadd4f8SNickeau * @return string|null 284*4cadd4f8SNickeau */ 285*4cadd4f8SNickeau public function getInternalFileContent(): ?string 286*4cadd4f8SNickeau { 287*4cadd4f8SNickeau $path = $this->getInternalFile(); 288*4cadd4f8SNickeau if (!FileSystems::exists($path)) { 289*4cadd4f8SNickeau return null; 290*4cadd4f8SNickeau } 291*4cadd4f8SNickeau return FileSystems::getContent($path); 292*4cadd4f8SNickeau } 293*4cadd4f8SNickeau 294*4cadd4f8SNickeau public function getInternalFile(): ?LocalPath 295*4cadd4f8SNickeau { 296*4cadd4f8SNickeau switch ($this->extension) { 297*4cadd4f8SNickeau case self::EXTENSION_CSS: 298*4cadd4f8SNickeau $extension = "css"; 299*4cadd4f8SNickeau $subDirectory = "style"; 30037748cd8SNickeau break; 301*4cadd4f8SNickeau case self::EXTENSION_JS: 302*4cadd4f8SNickeau $extension = "js"; 303*4cadd4f8SNickeau $subDirectory = "js"; 30437748cd8SNickeau break; 30537748cd8SNickeau default: 306*4cadd4f8SNickeau $message = "Unknown snippet type ($this->extension)"; 307*4cadd4f8SNickeau if (PluginUtility::isDevOrTest()) { 308*4cadd4f8SNickeau throw new ExceptionComboRuntime($message); 30937748cd8SNickeau } else { 310*4cadd4f8SNickeau LogUtility::msg($message); 311*4cadd4f8SNickeau } 312*4cadd4f8SNickeau return null; 313*4cadd4f8SNickeau } 314*4cadd4f8SNickeau return Site::getComboResourceSnippetDirectory() 315*4cadd4f8SNickeau ->resolve($subDirectory) 316*4cadd4f8SNickeau ->resolve(strtolower($this->componentName) . ".$extension"); 31737748cd8SNickeau } 31837748cd8SNickeau 319*4cadd4f8SNickeau public function hasSlot($slot): bool 32037748cd8SNickeau { 321*4cadd4f8SNickeau if ($this->slots === null) { 322*4cadd4f8SNickeau return false; 32337748cd8SNickeau } 324*4cadd4f8SNickeau return key_exists($slot, $this->slots); 32537748cd8SNickeau } 32637748cd8SNickeau 32737748cd8SNickeau public function __toString() 32837748cd8SNickeau { 329*4cadd4f8SNickeau return $this->snippetId . "-" . $this->extension; 33037748cd8SNickeau } 33137748cd8SNickeau 332c3437056SNickeau public function getCritical(): bool 33337748cd8SNickeau { 334c3437056SNickeau if ($this->critical === null) { 335*4cadd4f8SNickeau if ($this->extension == self::EXTENSION_CSS) { 336c3437056SNickeau // All CSS should be loaded first 337c3437056SNickeau // The CSS animation / background can set this to false 338c3437056SNickeau return true; 339c3437056SNickeau } 340c3437056SNickeau return false; 341c3437056SNickeau } 34237748cd8SNickeau return $this->critical; 34337748cd8SNickeau } 34437748cd8SNickeau 345c3437056SNickeau public function getClass(): string 34637748cd8SNickeau { 34737748cd8SNickeau /** 34837748cd8SNickeau * The class for the snippet is just to be able to identify them 34937748cd8SNickeau * 35037748cd8SNickeau * The `snippet` prefix was added to be sure that the class 35137748cd8SNickeau * name will not conflict with a css class 35237748cd8SNickeau * Example: if you set the class to `combo-list` 35337748cd8SNickeau * and that you use it in a inline `style` tag with 35437748cd8SNickeau * the same class name, the inline `style` tag is not applied 35537748cd8SNickeau * 35637748cd8SNickeau */ 357*4cadd4f8SNickeau return "snippet-" . $this->componentName . "-" . SnippetManager::COMBO_CLASS_SUFFIX; 35837748cd8SNickeau 35937748cd8SNickeau } 36037748cd8SNickeau 36137748cd8SNickeau /** 36237748cd8SNickeau * @return string the HTML of the tag (works for now only with CSS content) 36337748cd8SNickeau */ 364c3437056SNickeau public function getHtmlStyleTag(): string 36537748cd8SNickeau { 366*4cadd4f8SNickeau $content = $this->getInternalInlineAndFileContent(); 36737748cd8SNickeau $class = $this->getClass(); 36837748cd8SNickeau return <<<EOF 36937748cd8SNickeau<style class="$class"> 37037748cd8SNickeau$content 37137748cd8SNickeau</style> 37237748cd8SNickeauEOF; 37337748cd8SNickeau 37437748cd8SNickeau } 37537748cd8SNickeau 37637748cd8SNickeau public function getId() 37737748cd8SNickeau { 37837748cd8SNickeau return $this->snippetId; 37937748cd8SNickeau } 38037748cd8SNickeau 38137748cd8SNickeau 382*4cadd4f8SNickeau public function toJsonArray(): array 383c3437056SNickeau { 384*4cadd4f8SNickeau return $this->jsonSerialize(); 385c3437056SNickeau 386c3437056SNickeau } 387c3437056SNickeau 388c3437056SNickeau /** 389c3437056SNickeau * @throws ExceptionCombo 390c3437056SNickeau */ 391c3437056SNickeau public static function createFromJson($array): Snippet 392c3437056SNickeau { 393*4cadd4f8SNickeau $snippetType = $array[self::JSON_TYPE_PROPERTY]; 394*4cadd4f8SNickeau if ($snippetType === null) { 395c3437056SNickeau throw new ExceptionCombo("The snippet type property was not found in the json array"); 396c3437056SNickeau } 397*4cadd4f8SNickeau switch ($snippetType) { 398*4cadd4f8SNickeau case Snippet::INTERNAL_TYPE: 399*4cadd4f8SNickeau $identifier = Snippet::INTERNAL_TYPE; 400*4cadd4f8SNickeau break; 401*4cadd4f8SNickeau case Snippet::EXTERNAL_TYPE: 402*4cadd4f8SNickeau $identifier = $array[self::JSON_URL_PROPERTY]; 403*4cadd4f8SNickeau break; 404*4cadd4f8SNickeau default: 405*4cadd4f8SNickeau throw new ExceptionCombo("snippet type unknown ($snippetType"); 406*4cadd4f8SNickeau } 407*4cadd4f8SNickeau $extension = $array[self::JSON_EXTENSION_PROPERTY]; 408*4cadd4f8SNickeau if ($extension === null) { 409*4cadd4f8SNickeau throw new ExceptionCombo("The snippet extension property was not found in the json array"); 410*4cadd4f8SNickeau } 411*4cadd4f8SNickeau $componentName = $array[self::JSON_COMPONENT_PROPERTY]; 412*4cadd4f8SNickeau if ($componentName === null) { 413*4cadd4f8SNickeau throw new ExceptionCombo("The snippet component name property was not found in the json array"); 414*4cadd4f8SNickeau } 415*4cadd4f8SNickeau $snippet = Snippet::getOrCreateSnippet($identifier, $extension, $componentName); 416*4cadd4f8SNickeau 417*4cadd4f8SNickeau 418c3437056SNickeau $critical = $array[self::JSON_CRITICAL_PROPERTY]; 419c3437056SNickeau if ($critical !== null) { 420c3437056SNickeau $snippet->setCritical($critical); 421c3437056SNickeau } 422c3437056SNickeau 423*4cadd4f8SNickeau $async = $array[self::JSON_ASYNC_PROPERTY]; 424*4cadd4f8SNickeau if ($async !== null) { 425*4cadd4f8SNickeau $snippet->setDoesManipulateTheDomOnRun($async); 426*4cadd4f8SNickeau } 427*4cadd4f8SNickeau 428c3437056SNickeau $content = $array[self::JSON_CONTENT_PROPERTY]; 429c3437056SNickeau if ($content !== null) { 430*4cadd4f8SNickeau $snippet->setInlineContent($content); 431c3437056SNickeau } 432c3437056SNickeau 433*4cadd4f8SNickeau $attributes = $array[self::JSON_HTML_ATTRIBUTES_PROPERTY]; 434*4cadd4f8SNickeau if ($attributes !== null) { 435*4cadd4f8SNickeau foreach ($attributes as $name => $value) { 436*4cadd4f8SNickeau $snippet->addHtmlAttribute($name, $value); 437c3437056SNickeau } 438*4cadd4f8SNickeau } 439*4cadd4f8SNickeau 440*4cadd4f8SNickeau $integrity = $array[self::JSON_INTEGRITY_PROPERTY]; 441*4cadd4f8SNickeau if ($integrity !== null) { 442*4cadd4f8SNickeau $snippet->setIntegrity($integrity); 443*4cadd4f8SNickeau } 444*4cadd4f8SNickeau 445c3437056SNickeau return $snippet; 446c3437056SNickeau 447c3437056SNickeau } 448*4cadd4f8SNickeau 449*4cadd4f8SNickeau public function getExtension() 450*4cadd4f8SNickeau { 451*4cadd4f8SNickeau return $this->extension; 452*4cadd4f8SNickeau } 453*4cadd4f8SNickeau 454*4cadd4f8SNickeau public function setIntegrity(?string $integrity): Snippet 455*4cadd4f8SNickeau { 456*4cadd4f8SNickeau $this->integrity = $integrity; 457*4cadd4f8SNickeau return $this; 458*4cadd4f8SNickeau } 459*4cadd4f8SNickeau 460*4cadd4f8SNickeau public function addHtmlAttribute(string $name, string $value): Snippet 461*4cadd4f8SNickeau { 462*4cadd4f8SNickeau $this->htmlAttributes[$name] = $value; 463*4cadd4f8SNickeau return $this; 464*4cadd4f8SNickeau } 465*4cadd4f8SNickeau 466*4cadd4f8SNickeau public function addSlot(string $slot): Snippet 467*4cadd4f8SNickeau { 468*4cadd4f8SNickeau $this->slots[$slot] = 1; 469*4cadd4f8SNickeau return $this; 470*4cadd4f8SNickeau } 471*4cadd4f8SNickeau 472*4cadd4f8SNickeau public function getType(): string 473*4cadd4f8SNickeau { 474*4cadd4f8SNickeau return $this->type; 475*4cadd4f8SNickeau } 476*4cadd4f8SNickeau 477*4cadd4f8SNickeau public function getUrl(): string 478*4cadd4f8SNickeau { 479*4cadd4f8SNickeau return $this->url; 480*4cadd4f8SNickeau } 481*4cadd4f8SNickeau 482*4cadd4f8SNickeau public function getIntegrity(): ?string 483*4cadd4f8SNickeau { 484*4cadd4f8SNickeau return $this->integrity; 485*4cadd4f8SNickeau } 486*4cadd4f8SNickeau 487*4cadd4f8SNickeau public function getHtmlAttributes(): ?array 488*4cadd4f8SNickeau { 489*4cadd4f8SNickeau return $this->htmlAttributes; 490*4cadd4f8SNickeau } 491*4cadd4f8SNickeau 492*4cadd4f8SNickeau public function getInternalInlineAndFileContent(): ?string 493*4cadd4f8SNickeau { 494*4cadd4f8SNickeau $totalContent = null; 495*4cadd4f8SNickeau $internalFileContent = $this->getInternalFileContent(); 496*4cadd4f8SNickeau if ($internalFileContent !== null) { 497*4cadd4f8SNickeau $totalContent = $internalFileContent; 498*4cadd4f8SNickeau } 499*4cadd4f8SNickeau 500*4cadd4f8SNickeau $content = $this->getInternalDynamicContent(); 501*4cadd4f8SNickeau if ($content !== null) { 502*4cadd4f8SNickeau if ($totalContent === null) { 503*4cadd4f8SNickeau $totalContent = $content; 504*4cadd4f8SNickeau } else { 505*4cadd4f8SNickeau $totalContent .= $content; 506*4cadd4f8SNickeau } 507*4cadd4f8SNickeau } 508*4cadd4f8SNickeau return $totalContent; 509*4cadd4f8SNickeau 510*4cadd4f8SNickeau } 511*4cadd4f8SNickeau 512*4cadd4f8SNickeau 513*4cadd4f8SNickeau public function jsonSerialize(): array 514*4cadd4f8SNickeau { 515*4cadd4f8SNickeau $dataToSerialize = [ 516*4cadd4f8SNickeau self::JSON_COMPONENT_PROPERTY => $this->componentName, 517*4cadd4f8SNickeau self::JSON_EXTENSION_PROPERTY => $this->extension, 518*4cadd4f8SNickeau self::JSON_TYPE_PROPERTY => $this->type 519*4cadd4f8SNickeau ]; 520*4cadd4f8SNickeau if ($this->url !== null) { 521*4cadd4f8SNickeau $dataToSerialize[self::JSON_URL_PROPERTY] = $this->url; 522*4cadd4f8SNickeau } 523*4cadd4f8SNickeau if ($this->integrity !== null) { 524*4cadd4f8SNickeau $dataToSerialize[self::JSON_INTEGRITY_PROPERTY] = $this->integrity; 525*4cadd4f8SNickeau } 526*4cadd4f8SNickeau if ($this->critical !== null) { 527*4cadd4f8SNickeau $dataToSerialize[self::JSON_CRITICAL_PROPERTY] = $this->critical; 528*4cadd4f8SNickeau } 529*4cadd4f8SNickeau if ($this->async !== null) { 530*4cadd4f8SNickeau $dataToSerialize[self::JSON_ASYNC_PROPERTY] = $this->async; 531*4cadd4f8SNickeau } 532*4cadd4f8SNickeau if ($this->inlineContent !== null) { 533*4cadd4f8SNickeau $dataToSerialize[self::JSON_CONTENT_PROPERTY] = $this->inlineContent; 534*4cadd4f8SNickeau } 535*4cadd4f8SNickeau if ($this->htmlAttributes !== null) { 536*4cadd4f8SNickeau $dataToSerialize[self::JSON_HTML_ATTRIBUTES_PROPERTY] = $this->htmlAttributes; 537*4cadd4f8SNickeau } 538*4cadd4f8SNickeau return $dataToSerialize; 539*4cadd4f8SNickeau } 54037748cd8SNickeau} 541