1*37748cd8SNickeau<?php 2*37748cd8SNickeau/** 3*37748cd8SNickeau * Copyright (c) 2021. 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*37748cd8SNickeau 16*37748cd8SNickeauclass Snippet 17*37748cd8SNickeau{ 18*37748cd8SNickeau /** 19*37748cd8SNickeau * The head in css format 20*37748cd8SNickeau * We need to add the style node 21*37748cd8SNickeau */ 22*37748cd8SNickeau const TYPE_CSS = "css"; 23*37748cd8SNickeau 24*37748cd8SNickeau /** 25*37748cd8SNickeau * The snippet is attached to a bar (main, sidebar, ...) or to the page (request) 26*37748cd8SNickeau */ 27*37748cd8SNickeau const SCOPE_BAR = "bar"; 28*37748cd8SNickeau const SCOPE_PAGE = "page"; 29*37748cd8SNickeau /** 30*37748cd8SNickeau * The head in javascript 31*37748cd8SNickeau * We need to wrap it in a script node 32*37748cd8SNickeau */ 33*37748cd8SNickeau const TYPE_JS = "js"; 34*37748cd8SNickeau /** 35*37748cd8SNickeau * A tag head in array format 36*37748cd8SNickeau * No need 37*37748cd8SNickeau */ 38*37748cd8SNickeau const TAG_TYPE = "tag"; 39*37748cd8SNickeau 40*37748cd8SNickeau private $snippetId; 41*37748cd8SNickeau private $scope; 42*37748cd8SNickeau private $type; 43*37748cd8SNickeau 44*37748cd8SNickeau /** 45*37748cd8SNickeau * @var bool 46*37748cd8SNickeau */ 47*37748cd8SNickeau private $critical = false; 48*37748cd8SNickeau 49*37748cd8SNickeau /** 50*37748cd8SNickeau * @var string the text script / style (may be null if it's an external resources) 51*37748cd8SNickeau */ 52*37748cd8SNickeau private $content; 53*37748cd8SNickeau /** 54*37748cd8SNickeau * @var array 55*37748cd8SNickeau */ 56*37748cd8SNickeau private $headsTags; 57*37748cd8SNickeau 58*37748cd8SNickeau /** 59*37748cd8SNickeau * Snippet constructor. 60*37748cd8SNickeau */ 61*37748cd8SNickeau public function __construct($snippetId, $snippetType) 62*37748cd8SNickeau { 63*37748cd8SNickeau $this->snippetId = $snippetId; 64*37748cd8SNickeau $this->type = $snippetType; 65*37748cd8SNickeau if ($this->type == self::TYPE_CSS) { 66*37748cd8SNickeau // All CSS should be loaded first 67*37748cd8SNickeau // The CSS animation / background can set this to false 68*37748cd8SNickeau $this->critical = true; 69*37748cd8SNickeau } 70*37748cd8SNickeau } 71*37748cd8SNickeau 72*37748cd8SNickeau public static function createJavascriptSnippet($snippetId) 73*37748cd8SNickeau { 74*37748cd8SNickeau return new Snippet($snippetId,self::TYPE_JS); 75*37748cd8SNickeau } 76*37748cd8SNickeau 77*37748cd8SNickeau public static function createCssSnippet($snippetId) 78*37748cd8SNickeau { 79*37748cd8SNickeau return new Snippet($snippetId,self::TYPE_CSS); 80*37748cd8SNickeau } 81*37748cd8SNickeau 82*37748cd8SNickeau /** 83*37748cd8SNickeau * @deprecated You should create a snippet with a known type, this constructor was created for refactoring 84*37748cd8SNickeau * @param $snippetId 85*37748cd8SNickeau * @return Snippet 86*37748cd8SNickeau */ 87*37748cd8SNickeau public static function createUnknownSnippet($snippetId) 88*37748cd8SNickeau { 89*37748cd8SNickeau return new Snippet($snippetId,"unknwon"); 90*37748cd8SNickeau } 91*37748cd8SNickeau 92*37748cd8SNickeau 93*37748cd8SNickeau /** 94*37748cd8SNickeau * @param $bool - if the snippet is critical, it would not be deferred or preloaded 95*37748cd8SNickeau * @return Snippet for chaining 96*37748cd8SNickeau * All css that are for animation or background for instance 97*37748cd8SNickeau * should not be set as critical as they are not needed to paint 98*37748cd8SNickeau * exactly the page 99*37748cd8SNickeau */ 100*37748cd8SNickeau public function setCritical($bool) 101*37748cd8SNickeau { 102*37748cd8SNickeau $this->critical = $bool; 103*37748cd8SNickeau return $this; 104*37748cd8SNickeau } 105*37748cd8SNickeau 106*37748cd8SNickeau /** 107*37748cd8SNickeau * @param $content - Set an inline content for a script or stylesheet 108*37748cd8SNickeau * @return Snippet for chaining 109*37748cd8SNickeau */ 110*37748cd8SNickeau public function setContent($content) 111*37748cd8SNickeau { 112*37748cd8SNickeau $this->content = $content; 113*37748cd8SNickeau return $this; 114*37748cd8SNickeau } 115*37748cd8SNickeau 116*37748cd8SNickeau /** 117*37748cd8SNickeau * @return string 118*37748cd8SNickeau */ 119*37748cd8SNickeau public function getContent() 120*37748cd8SNickeau { 121*37748cd8SNickeau if ($this->content == null) { 122*37748cd8SNickeau switch ($this->type) { 123*37748cd8SNickeau case self::TYPE_CSS: 124*37748cd8SNickeau $this->content = $this->getCssRulesFromFile($this->snippetId); 125*37748cd8SNickeau break; 126*37748cd8SNickeau case self::TYPE_JS: 127*37748cd8SNickeau $this->content = $this->getJavascriptContentFromFile($this->snippetId); 128*37748cd8SNickeau break; 129*37748cd8SNickeau default: 130*37748cd8SNickeau LogUtility::msg("The snippet ($this) has no content", LogUtility::LVL_MSG_ERROR, "support"); 131*37748cd8SNickeau } 132*37748cd8SNickeau } 133*37748cd8SNickeau return $this->content; 134*37748cd8SNickeau } 135*37748cd8SNickeau 136*37748cd8SNickeau /** 137*37748cd8SNickeau * @param $tagName 138*37748cd8SNickeau * @return false|string - the css content of the css file 139*37748cd8SNickeau */ 140*37748cd8SNickeau private function getCssRulesFromFile($tagName) 141*37748cd8SNickeau { 142*37748cd8SNickeau 143*37748cd8SNickeau $path = Resources::getSnippetResourceDirectory() . "/style/" . strtolower($tagName) . ".css"; 144*37748cd8SNickeau if (file_exists($path)) { 145*37748cd8SNickeau return file_get_contents($path); 146*37748cd8SNickeau } else { 147*37748cd8SNickeau LogUtility::msg("The css file ($path) was not found", LogUtility::LVL_MSG_WARNING, $tagName); 148*37748cd8SNickeau return ""; 149*37748cd8SNickeau } 150*37748cd8SNickeau 151*37748cd8SNickeau } 152*37748cd8SNickeau 153*37748cd8SNickeau /** 154*37748cd8SNickeau * @param $tagName - the tag name 155*37748cd8SNickeau * @return false|string - the specific javascript content for the tag 156*37748cd8SNickeau */ 157*37748cd8SNickeau private function getJavascriptContentFromFile($tagName) 158*37748cd8SNickeau { 159*37748cd8SNickeau 160*37748cd8SNickeau $path = Resources::getSnippetResourceDirectory() . "/js/" . strtolower($tagName) . ".js"; 161*37748cd8SNickeau if (file_exists($path)) { 162*37748cd8SNickeau return file_get_contents($path); 163*37748cd8SNickeau } else { 164*37748cd8SNickeau LogUtility::msg("The javascript file ($path) was not found", LogUtility::LVL_MSG_WARNING, $tagName); 165*37748cd8SNickeau return ""; 166*37748cd8SNickeau } 167*37748cd8SNickeau 168*37748cd8SNickeau } 169*37748cd8SNickeau 170*37748cd8SNickeau public function __toString() 171*37748cd8SNickeau { 172*37748cd8SNickeau return $this->snippetId."-".$this->type; 173*37748cd8SNickeau } 174*37748cd8SNickeau 175*37748cd8SNickeau /** 176*37748cd8SNickeau * Set all tags at once. 177*37748cd8SNickeau * @param array $tags 178*37748cd8SNickeau * @return Snippet 179*37748cd8SNickeau */ 180*37748cd8SNickeau public function setTags(array $tags) 181*37748cd8SNickeau { 182*37748cd8SNickeau $this->headsTags = $tags; 183*37748cd8SNickeau return $this; 184*37748cd8SNickeau } 185*37748cd8SNickeau 186*37748cd8SNickeau public function getTags() 187*37748cd8SNickeau { 188*37748cd8SNickeau return $this->headsTags; 189*37748cd8SNickeau } 190*37748cd8SNickeau 191*37748cd8SNickeau public function getCritical() 192*37748cd8SNickeau { 193*37748cd8SNickeau return $this->critical; 194*37748cd8SNickeau } 195*37748cd8SNickeau 196*37748cd8SNickeau public function getClass() 197*37748cd8SNickeau { 198*37748cd8SNickeau /** 199*37748cd8SNickeau * The class for the snippet is just to be able to identify them 200*37748cd8SNickeau * 201*37748cd8SNickeau * The `snippet` prefix was added to be sure that the class 202*37748cd8SNickeau * name will not conflict with a css class 203*37748cd8SNickeau * Example: if you set the class to `combo-list` 204*37748cd8SNickeau * and that you use it in a inline `style` tag with 205*37748cd8SNickeau * the same class name, the inline `style` tag is not applied 206*37748cd8SNickeau * 207*37748cd8SNickeau */ 208*37748cd8SNickeau return "snippet-" . $this->snippetId . "-" . SnippetManager::COMBO_CLASS_SUFFIX; 209*37748cd8SNickeau 210*37748cd8SNickeau } 211*37748cd8SNickeau 212*37748cd8SNickeau /** 213*37748cd8SNickeau * @return string the HTML of the tag (works for now only with CSS content) 214*37748cd8SNickeau */ 215*37748cd8SNickeau public function getHtmlStyleTag() 216*37748cd8SNickeau { 217*37748cd8SNickeau $content = $this->getContent(); 218*37748cd8SNickeau $class = $this->getClass(); 219*37748cd8SNickeau return <<<EOF 220*37748cd8SNickeau<style class="$class"> 221*37748cd8SNickeau$content 222*37748cd8SNickeau</style> 223*37748cd8SNickeauEOF; 224*37748cd8SNickeau 225*37748cd8SNickeau } 226*37748cd8SNickeau 227*37748cd8SNickeau public function getId() 228*37748cd8SNickeau { 229*37748cd8SNickeau return $this->snippetId; 230*37748cd8SNickeau } 231*37748cd8SNickeau 232*37748cd8SNickeau 233*37748cd8SNickeau} 234