1<?php 2 3 4namespace ComboStrap; 5 6 7/** 8 * Class Template 9 * @package ComboStrap 10 * https://stackoverflow.com/questions/17869964/replacing-string-within-php-file 11 */ 12class Template 13{ 14 15 public const DOLLAR_VARIABLE_PREFIX = "$"; 16 17 public const DOLLAR_ESCAPE = '\\'; 18 19 public const CAPTURE_PATTERN_SHORT = Template::DOLLAR_ESCAPE . Template::DOLLAR_VARIABLE_PREFIX . self::VARIABLE_NAME_EXPRESSION; 20 public const CAPTURE_PATTERN_LONG = Template::DOLLAR_ESCAPE . Template::LONG_PREFIX . "[^}\r\n]+" . self::LONG_EXIT; 21 22 23 const CANONICAL = "variable-template"; 24 public const LONG_PREFIX = self::DOLLAR_VARIABLE_PREFIX . self::LONG_ENTER; 25 public const LONG_EXIT = '}'; 26 const LONG_ENTER = '{'; 27 const VARIABLE_NAME_EXPRESSION = "[A-Za-z0-9_]+"; 28 const LONG_VARIABLE_NAME_CAPTURE_EXPRESSION = self::DOLLAR_ESCAPE . self::LONG_PREFIX . '\s*(' . self::VARIABLE_NAME_EXPRESSION . ')[^\r\n]*' . self::LONG_EXIT; 29 30 31 protected string $_string; 32 protected array $_data = array(); 33 34 public function __construct($string = null) 35 { 36 $this->_string = $string; 37 } 38 39 /** 40 * @param $string 41 * @return Template 42 */ 43 public static function create($string): Template 44 { 45 return new Template($string); 46 } 47 48 public static function toValidVariableName(string $name) 49 { 50 return str_replace("-", "", $name); 51 } 52 53 public function setProperty($key, $value): Template 54 { 55 $this->_data[$key] = $value; 56 return $this; 57 } 58 59 public function render(): string 60 { 61 62 $pattern = '/' . 63 '(' . self::DOLLAR_ESCAPE . self::DOLLAR_VARIABLE_PREFIX . self::VARIABLE_NAME_EXPRESSION . ')' . 64 '|' . 65 '(' . self::DOLLAR_ESCAPE . self::LONG_PREFIX . '\s*' . self::VARIABLE_NAME_EXPRESSION . '[^\r\n]*' . self::LONG_EXIT . ')' . 66 '/im'; 67 $splits = preg_split($pattern, $this->_string, -1, PREG_SPLIT_DELIM_CAPTURE); 68 $rendered = ""; 69 foreach ($splits as $part) { 70 if (substr($part, 0, 1) === self::DOLLAR_VARIABLE_PREFIX) { 71 if (substr($part, 1, 1) === self::LONG_ENTER) { 72 $matches = []; 73 preg_match('/' . self::LONG_VARIABLE_NAME_CAPTURE_EXPRESSION . '/im', $part, $matches); 74 $variable = $matches[1]; 75 } else { 76 $variable = trim(substr($part, 1)); 77 } 78 if (array_key_exists($variable, $this->_data)) { 79 $value = $this->_data[$variable]; 80 } else { 81 LogUtility::warning("The variable ($variable) was not found in the data and has not been replaced", self::CANONICAL); 82 $value = $variable; 83 } 84 } else { 85 $value = $part; 86 } 87 $rendered .= $value; 88 } 89 return $rendered; 90 91 } 92 93 /** 94 * 95 * @return false|string 96 * @deprecated Just for demo, don't use because the input is not validated 97 * 98 */ 99 public function renderViaEval() 100 { 101 extract($this->_data); 102 ob_start(); 103 eval("echo $this->_string ;"); 104 return ob_get_clean(); 105 } 106 107 /** 108 * @return array - an array of variable name 109 */ 110 public function getVariablesDetected(): array 111 { 112 /** @noinspection RegExpUnnecessaryNonCapturingGroup */ 113 $pattern = '/' . 114 '(?:' . self::DOLLAR_ESCAPE . self::DOLLAR_VARIABLE_PREFIX . '(' . self::VARIABLE_NAME_EXPRESSION . '))' . 115 '|' . 116 '(?:' . self::LONG_VARIABLE_NAME_CAPTURE_EXPRESSION . ')' . 117 '/im'; 118 $result = preg_match_all($pattern, $this->_string, $matches); 119 if ($result >= 1) { 120 $returnedMatch = []; 121 $firstExpressionMatches = $matches[1]; 122 $secondExpressionMatches = $matches[2]; 123 foreach ($firstExpressionMatches as $key => $match) { 124 if (empty($match)) { 125 $returnedMatch[] = $secondExpressionMatches[$key]; 126 continue; 127 } 128 $returnedMatch[] = $match; 129 } 130 return $returnedMatch; 131 } else { 132 return []; 133 } 134 135 } 136 137 public function setProperties(array $properties): Template 138 { 139 foreach ($properties as $key => $val) { 140 $this->setProperty($key, $val); 141 } 142 return $this; 143 144 } 145 146} 147