PageRenderTime 52ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/index.php

https://bitbucket.org/scottywz/portal
PHP | 2412 lines | 1659 code | 228 blank | 525 comment | 387 complexity | fe9b94ef26a93542010e351d22aa7e50 MD5 | raw file
Possible License(s): MIT

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Spyc -- A Simple PHP YAML Class
  4. * @version 0.5
  5. * @author Vlad Andersen <vlad.andersen@gmail.com>
  6. * @author Chris Wanstrath <chris@ozmm.org>
  7. * @link http://code.google.com/p/spyc/
  8. * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen
  9. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  10. * @package Spyc
  11. */
  12. if (!function_exists('spyc_load')) {
  13. /**
  14. * Parses YAML to array.
  15. * @param string $string YAML string.
  16. * @return array
  17. */
  18. function spyc_load ($string) {
  19. return Spyc::YAMLLoadString($string);
  20. }
  21. }
  22. if (!function_exists('spyc_load_file')) {
  23. /**
  24. * Parses YAML to array.
  25. * @param string $file Path to YAML file.
  26. * @return array
  27. */
  28. function spyc_load_file ($file) {
  29. return Spyc::YAMLLoad($file);
  30. }
  31. }
  32. /**
  33. * The Simple PHP YAML Class.
  34. *
  35. * This class can be used to read a YAML file and convert its contents
  36. * into a PHP array. It currently supports a very limited subsection of
  37. * the YAML spec.
  38. *
  39. * Usage:
  40. * <code>
  41. * $Spyc = new Spyc;
  42. * $array = $Spyc->load($file);
  43. * </code>
  44. * or:
  45. * <code>
  46. * $array = Spyc::YAMLLoad($file);
  47. * </code>
  48. * or:
  49. * <code>
  50. * $array = spyc_load_file($file);
  51. * </code>
  52. * @package Spyc
  53. */
  54. class Spyc {
  55. // SETTINGS
  56. const REMPTY = "\0\0\0\0\0";
  57. /**
  58. * Setting this to true will force YAMLDump to enclose any string value in
  59. * quotes. False by default.
  60. *
  61. * @var bool
  62. */
  63. public $setting_dump_force_quotes = false;
  64. /**
  65. * Setting this to true will forse YAMLLoad to use syck_load function when
  66. * possible. False by default.
  67. * @var bool
  68. */
  69. public $setting_use_syck_is_possible = false;
  70. /**#@+
  71. * @access private
  72. * @var mixed
  73. */
  74. private $_dumpIndent;
  75. private $_dumpWordWrap;
  76. private $_containsGroupAnchor = false;
  77. private $_containsGroupAlias = false;
  78. private $path;
  79. private $result;
  80. private $LiteralPlaceHolder = '___YAML_Literal_Block___';
  81. private $SavedGroups = array();
  82. private $indent;
  83. /**
  84. * Path modifier that should be applied after adding current element.
  85. * @var array
  86. */
  87. private $delayedPath = array();
  88. /**#@+
  89. * @access public
  90. * @var mixed
  91. */
  92. public $_nodeId;
  93. /**
  94. * Load a valid YAML string to Spyc.
  95. * @param string $input
  96. * @return array
  97. */
  98. public function load ($input) {
  99. return $this->__loadString($input);
  100. }
  101. /**
  102. * Load a valid YAML file to Spyc.
  103. * @param string $file
  104. * @return array
  105. */
  106. public function loadFile ($file) {
  107. return $this->__load($file);
  108. }
  109. /**
  110. * Load YAML into a PHP array statically
  111. *
  112. * The load method, when supplied with a YAML stream (string or file),
  113. * will do its best to convert YAML in a file into a PHP array. Pretty
  114. * simple.
  115. * Usage:
  116. * <code>
  117. * $array = Spyc::YAMLLoad('lucky.yaml');
  118. * print_r($array);
  119. * </code>
  120. * @access public
  121. * @return array
  122. * @param string $input Path of YAML file or string containing YAML
  123. */
  124. public static function YAMLLoad($input) {
  125. $Spyc = new Spyc;
  126. return $Spyc->__load($input);
  127. }
  128. /**
  129. * Load a string of YAML into a PHP array statically
  130. *
  131. * The load method, when supplied with a YAML string, will do its best
  132. * to convert YAML in a string into a PHP array. Pretty simple.
  133. *
  134. * Note: use this function if you don't want files from the file system
  135. * loaded and processed as YAML. This is of interest to people concerned
  136. * about security whose input is from a string.
  137. *
  138. * Usage:
  139. * <code>
  140. * $array = Spyc::YAMLLoadString("---\n0: hello world\n");
  141. * print_r($array);
  142. * </code>
  143. * @access public
  144. * @return array
  145. * @param string $input String containing YAML
  146. */
  147. public static function YAMLLoadString($input) {
  148. $Spyc = new Spyc;
  149. return $Spyc->__loadString($input);
  150. }
  151. /**
  152. * Dump YAML from PHP array statically
  153. *
  154. * The dump method, when supplied with an array, will do its best
  155. * to convert the array into friendly YAML. Pretty simple. Feel free to
  156. * save the returned string as nothing.yaml and pass it around.
  157. *
  158. * Oh, and you can decide how big the indent is and what the wordwrap
  159. * for folding is. Pretty cool -- just pass in 'false' for either if
  160. * you want to use the default.
  161. *
  162. * Indent's default is 2 spaces, wordwrap's default is 40 characters. And
  163. * you can turn off wordwrap by passing in 0.
  164. *
  165. * @access public
  166. * @return string
  167. * @param array $array PHP array
  168. * @param int $indent Pass in false to use the default, which is 2
  169. * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
  170. */
  171. public static function YAMLDump($array,$indent = false,$wordwrap = false) {
  172. $spyc = new Spyc;
  173. return $spyc->dump($array,$indent,$wordwrap);
  174. }
  175. /**
  176. * Dump PHP array to YAML
  177. *
  178. * The dump method, when supplied with an array, will do its best
  179. * to convert the array into friendly YAML. Pretty simple. Feel free to
  180. * save the returned string as tasteful.yaml and pass it around.
  181. *
  182. * Oh, and you can decide how big the indent is and what the wordwrap
  183. * for folding is. Pretty cool -- just pass in 'false' for either if
  184. * you want to use the default.
  185. *
  186. * Indent's default is 2 spaces, wordwrap's default is 40 characters. And
  187. * you can turn off wordwrap by passing in 0.
  188. *
  189. * @access public
  190. * @return string
  191. * @param array $array PHP array
  192. * @param int $indent Pass in false to use the default, which is 2
  193. * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
  194. */
  195. public function dump($array,$indent = false,$wordwrap = false) {
  196. // Dumps to some very clean YAML. We'll have to add some more features
  197. // and options soon. And better support for folding.
  198. // New features and options.
  199. if ($indent === false or !is_numeric($indent)) {
  200. $this->_dumpIndent = 2;
  201. } else {
  202. $this->_dumpIndent = $indent;
  203. }
  204. if ($wordwrap === false or !is_numeric($wordwrap)) {
  205. $this->_dumpWordWrap = 40;
  206. } else {
  207. $this->_dumpWordWrap = $wordwrap;
  208. }
  209. // New YAML document
  210. $string = "---\n";
  211. // Start at the base of the array and move through it.
  212. if ($array) {
  213. $array = (array)$array;
  214. $previous_key = -1;
  215. foreach ($array as $key => $value) {
  216. if (!isset($first_key)) $first_key = $key;
  217. $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array);
  218. $previous_key = $key;
  219. }
  220. }
  221. return $string;
  222. }
  223. /**
  224. * Attempts to convert a key / value array item to YAML
  225. * @access private
  226. * @return string
  227. * @param $key The name of the key
  228. * @param $value The value of the item
  229. * @param $indent The indent of the current node
  230. */
  231. private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) {
  232. if (is_array($value)) {
  233. if (empty ($value))
  234. return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array);
  235. // It has children. What to do?
  236. // Make it the right kind of item
  237. $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array);
  238. // Add the indent
  239. $indent += $this->_dumpIndent;
  240. // Yamlize the array
  241. $string .= $this->_yamlizeArray($value,$indent);
  242. } elseif (!is_array($value)) {
  243. // It doesn't have children. Yip.
  244. $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array);
  245. }
  246. return $string;
  247. }
  248. /**
  249. * Attempts to convert an array to YAML
  250. * @access private
  251. * @return string
  252. * @param $array The array you want to convert
  253. * @param $indent The indent of the current level
  254. */
  255. private function _yamlizeArray($array,$indent) {
  256. if (is_array($array)) {
  257. $string = '';
  258. $previous_key = -1;
  259. foreach ($array as $key => $value) {
  260. if (!isset($first_key)) $first_key = $key;
  261. $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array);
  262. $previous_key = $key;
  263. }
  264. return $string;
  265. } else {
  266. return false;
  267. }
  268. }
  269. /**
  270. * Returns YAML from a key and a value
  271. * @access private
  272. * @return string
  273. * @param $key The name of the key
  274. * @param $value The value of the item
  275. * @param $indent The indent of the current node
  276. */
  277. private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) {
  278. // do some folding here, for blocks
  279. if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false ||
  280. strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, ' ') !== false ||
  281. strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 ||
  282. substr ($value, -1, 1) == ':')
  283. ) {
  284. $value = $this->_doLiteralBlock($value,$indent);
  285. } else {
  286. $value = $this->_doFolding($value,$indent);
  287. }
  288. if ($value === array()) $value = '[ ]';
  289. if (in_array ($value, array ('true', 'TRUE', 'false', 'FALSE', 'y', 'Y', 'n', 'N', 'null', 'NULL'), true)) {
  290. $value = $this->_doLiteralBlock($value,$indent);
  291. }
  292. if (trim ($value) != $value)
  293. $value = $this->_doLiteralBlock($value,$indent);
  294. if (is_bool($value)) {
  295. $value = ($value) ? "true" : "false";
  296. }
  297. if ($value === null) $value = 'null';
  298. if ($value === "'" . self::REMPTY . "'") $value = null;
  299. $spaces = str_repeat(' ',$indent);
  300. //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) {
  301. if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) {
  302. // It's a sequence
  303. $string = $spaces.'- '.$value."\n";
  304. } else {
  305. // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"');
  306. // It's mapped
  307. if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; }
  308. $string = rtrim ($spaces.$key.': '.$value)."\n";
  309. }
  310. return $string;
  311. }
  312. /**
  313. * Creates a literal block for dumping
  314. * @access private
  315. * @return string
  316. * @param $value
  317. * @param $indent int The value of the indent
  318. */
  319. private function _doLiteralBlock($value,$indent) {
  320. if ($value === "\n") return '\n';
  321. if (strpos($value, "\n") === false && strpos($value, "'") === false) {
  322. return sprintf ("'%s'", $value);
  323. }
  324. if (strpos($value, "\n") === false && strpos($value, '"') === false) {
  325. return sprintf ('"%s"', $value);
  326. }
  327. $exploded = explode("\n",$value);
  328. $newValue = '|';
  329. $indent += $this->_dumpIndent;
  330. $spaces = str_repeat(' ',$indent);
  331. foreach ($exploded as $line) {
  332. $newValue .= "\n" . $spaces . ($line);
  333. }
  334. return $newValue;
  335. }
  336. /**
  337. * Folds a string of text, if necessary
  338. * @access private
  339. * @return string
  340. * @param $value The string you wish to fold
  341. */
  342. private function _doFolding($value,$indent) {
  343. // Don't do anything if wordwrap is set to 0
  344. if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) {
  345. $indent += $this->_dumpIndent;
  346. $indent = str_repeat(' ',$indent);
  347. $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
  348. $value = ">\n".$indent.$wrapped;
  349. } else {
  350. if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY)
  351. $value = '"' . $value . '"';
  352. }
  353. return $value;
  354. }
  355. // LOADING FUNCTIONS
  356. private function __load($input) {
  357. $Source = $this->loadFromSource($input);
  358. return $this->loadWithSource($Source);
  359. }
  360. private function __loadString($input) {
  361. $Source = $this->loadFromString($input);
  362. return $this->loadWithSource($Source);
  363. }
  364. private function loadWithSource($Source) {
  365. if (empty ($Source)) return array();
  366. if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) {
  367. $array = syck_load (implode ('', $Source));
  368. return is_array($array) ? $array : array();
  369. }
  370. $this->path = array();
  371. $this->result = array();
  372. $cnt = count($Source);
  373. for ($i = 0; $i < $cnt; $i++) {
  374. $line = $Source[$i];
  375. $this->indent = strlen($line) - strlen(ltrim($line));
  376. $tempPath = $this->getParentPathByIndent($this->indent);
  377. $line = self::stripIndent($line, $this->indent);
  378. if (self::isComment($line)) continue;
  379. if (self::isEmpty($line)) continue;
  380. $this->path = $tempPath;
  381. $literalBlockStyle = self::startsLiteralBlock($line);
  382. if ($literalBlockStyle) {
  383. $line = rtrim ($line, $literalBlockStyle . " \n");
  384. $literalBlock = '';
  385. $line .= $this->LiteralPlaceHolder;
  386. $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1]));
  387. while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) {
  388. $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent);
  389. }
  390. $i--;
  391. }
  392. while (++$i < $cnt && self::greedilyNeedNextLine($line)) {
  393. $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t");
  394. }
  395. $i--;
  396. if (strpos ($line, '#')) {
  397. if (strpos ($line, '"') === false && strpos ($line, "'") === false)
  398. $line = preg_replace('/\s+#(.+)$/','',$line);
  399. }
  400. $lineArray = $this->_parseLine($line);
  401. if ($literalBlockStyle)
  402. $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock);
  403. $this->addArray($lineArray, $this->indent);
  404. foreach ($this->delayedPath as $indent => $delayedPath)
  405. $this->path[$indent] = $delayedPath;
  406. $this->delayedPath = array();
  407. }
  408. return $this->result;
  409. }
  410. private function loadFromSource ($input) {
  411. if (!empty($input) && strpos($input, "\n") === false && file_exists($input))
  412. return file($input);
  413. return $this->loadFromString($input);
  414. }
  415. private function loadFromString ($input) {
  416. $lines = explode("\n",$input);
  417. foreach ($lines as $k => $_) {
  418. $lines[$k] = rtrim ($_, "\r");
  419. }
  420. return $lines;
  421. }
  422. /**
  423. * Parses YAML code and returns an array for a node
  424. * @access private
  425. * @return array
  426. * @param string $line A line from the YAML file
  427. */
  428. private function _parseLine($line) {
  429. if (!$line) return array();
  430. $line = trim($line);
  431. if (!$line) return array();
  432. $array = array();
  433. $group = $this->nodeContainsGroup($line);
  434. if ($group) {
  435. $this->addGroup($line, $group);
  436. $line = $this->stripGroup ($line, $group);
  437. }
  438. if ($this->startsMappedSequence($line))
  439. return $this->returnMappedSequence($line);
  440. if ($this->startsMappedValue($line))
  441. return $this->returnMappedValue($line);
  442. if ($this->isArrayElement($line))
  443. return $this->returnArrayElement($line);
  444. if ($this->isPlainArray($line))
  445. return $this->returnPlainArray($line);
  446. return $this->returnKeyValuePair($line);
  447. }
  448. /**
  449. * Finds the type of the passed value, returns the value as the new type.
  450. * @access private
  451. * @param string $value
  452. * @return mixed
  453. */
  454. private function _toType($value) {
  455. if ($value === '') return null;
  456. $first_character = $value[0];
  457. $last_character = substr($value, -1, 1);
  458. $is_quoted = false;
  459. do {
  460. if (!$value) break;
  461. if ($first_character != '"' && $first_character != "'") break;
  462. if ($last_character != '"' && $last_character != "'") break;
  463. $is_quoted = true;
  464. } while (0);
  465. if ($is_quoted)
  466. return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\''));
  467. if (strpos($value, ' #') !== false && !$is_quoted)
  468. $value = preg_replace('/\s+#(.+)$/','',$value);
  469. if (!$is_quoted) $value = str_replace('\n', "\n", $value);
  470. if ($first_character == '[' && $last_character == ']') {
  471. // Take out strings sequences and mappings
  472. $innerValue = trim(substr ($value, 1, -1));
  473. if ($innerValue === '') return array();
  474. $explode = $this->_inlineEscape($innerValue);
  475. // Propagate value array
  476. $value = array();
  477. foreach ($explode as $v) {
  478. $value[] = $this->_toType($v);
  479. }
  480. return $value;
  481. }
  482. if (strpos($value,': ')!==false && $first_character != '{') {
  483. $array = explode(': ',$value);
  484. $key = trim($array[0]);
  485. array_shift($array);
  486. $value = trim(implode(': ',$array));
  487. $value = $this->_toType($value);
  488. return array($key => $value);
  489. }
  490. if ($first_character == '{' && $last_character == '}') {
  491. $innerValue = trim(substr ($value, 1, -1));
  492. if ($innerValue === '') return array();
  493. // Inline Mapping
  494. // Take out strings sequences and mappings
  495. $explode = $this->_inlineEscape($innerValue);
  496. // Propagate value array
  497. $array = array();
  498. foreach ($explode as $v) {
  499. $SubArr = $this->_toType($v);
  500. if (empty($SubArr)) continue;
  501. if (is_array ($SubArr)) {
  502. $array[key($SubArr)] = $SubArr[key($SubArr)]; continue;
  503. }
  504. $array[] = $SubArr;
  505. }
  506. return $array;
  507. }
  508. if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') {
  509. return null;
  510. }
  511. if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){
  512. $intvalue = (int)$value;
  513. if ($intvalue != PHP_INT_MAX)
  514. $value = $intvalue;
  515. return $value;
  516. }
  517. if (in_array($value,
  518. array('true', 'on', '+', 'yes', 'y', 'True', 'TRUE', 'On', 'ON', 'YES', 'Yes', 'Y'))) {
  519. return true;
  520. }
  521. if (in_array(strtolower($value),
  522. array('false', 'off', '-', 'no', 'n'))) {
  523. return false;
  524. }
  525. if (is_numeric($value)) {
  526. if ($value === '0') return 0;
  527. if (rtrim ($value, 0) === $value)
  528. $value = (float)$value;
  529. return $value;
  530. }
  531. return $value;
  532. }
  533. /**
  534. * Used in inlines to check for more inlines or quoted strings
  535. * @access private
  536. * @return array
  537. */
  538. private function _inlineEscape($inline) {
  539. // There's gotta be a cleaner way to do this...
  540. // While pure sequences seem to be nesting just fine,
  541. // pure mappings and mappings with sequences inside can't go very
  542. // deep. This needs to be fixed.
  543. $seqs = array();
  544. $maps = array();
  545. $saved_strings = array();
  546. // Check for strings
  547. $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
  548. if (preg_match_all($regex,$inline,$strings)) {
  549. $saved_strings = $strings[0];
  550. $inline = preg_replace($regex,'YAMLString',$inline);
  551. }
  552. unset($regex);
  553. $i = 0;
  554. do {
  555. // Check for sequences
  556. while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) {
  557. $seqs[] = $matchseqs[0];
  558. $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1);
  559. }
  560. // Check for mappings
  561. while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) {
  562. $maps[] = $matchmaps[0];
  563. $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1);
  564. }
  565. if ($i++ >= 10) break;
  566. } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false);
  567. $explode = explode(', ',$inline);
  568. $stringi = 0; $i = 0;
  569. while (1) {
  570. // Re-add the sequences
  571. if (!empty($seqs)) {
  572. foreach ($explode as $key => $value) {
  573. if (strpos($value,'YAMLSeq') !== false) {
  574. foreach ($seqs as $seqk => $seq) {
  575. $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value);
  576. $value = $explode[$key];
  577. }
  578. }
  579. }
  580. }
  581. // Re-add the mappings
  582. if (!empty($maps)) {
  583. foreach ($explode as $key => $value) {
  584. if (strpos($value,'YAMLMap') !== false) {
  585. foreach ($maps as $mapk => $map) {
  586. $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value);
  587. $value = $explode[$key];
  588. }
  589. }
  590. }
  591. }
  592. // Re-add the strings
  593. if (!empty($saved_strings)) {
  594. foreach ($explode as $key => $value) {
  595. while (strpos($value,'YAMLString') !== false) {
  596. $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1);
  597. unset($saved_strings[$stringi]);
  598. ++$stringi;
  599. $value = $explode[$key];
  600. }
  601. }
  602. }
  603. $finished = true;
  604. foreach ($explode as $key => $value) {
  605. if (strpos($value,'YAMLSeq') !== false) {
  606. $finished = false; break;
  607. }
  608. if (strpos($value,'YAMLMap') !== false) {
  609. $finished = false; break;
  610. }
  611. if (strpos($value,'YAMLString') !== false) {
  612. $finished = false; break;
  613. }
  614. }
  615. if ($finished) break;
  616. $i++;
  617. if ($i > 10)
  618. break; // Prevent infinite loops.
  619. }
  620. return $explode;
  621. }
  622. private function literalBlockContinues ($line, $lineIndent) {
  623. if (!trim($line)) return true;
  624. if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true;
  625. return false;
  626. }
  627. private function referenceContentsByAlias ($alias) {
  628. do {
  629. if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; }
  630. $groupPath = $this->SavedGroups[$alias];
  631. $value = $this->result;
  632. foreach ($groupPath as $k) {
  633. $value = $value[$k];
  634. }
  635. } while (false);
  636. return $value;
  637. }
  638. private function addArrayInline ($array, $indent) {
  639. $CommonGroupPath = $this->path;
  640. if (empty ($array)) return false;
  641. foreach ($array as $k => $_) {
  642. $this->addArray(array($k => $_), $indent);
  643. $this->path = $CommonGroupPath;
  644. }
  645. return true;
  646. }
  647. private function addArray ($incoming_data, $incoming_indent) {
  648. // print_r ($incoming_data);
  649. if (count ($incoming_data) > 1)
  650. return $this->addArrayInline ($incoming_data, $incoming_indent);
  651. $key = key ($incoming_data);
  652. $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null;
  653. if ($key === '__!YAMLZero') $key = '0';
  654. if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values.
  655. if ($key || $key === '' || $key === '0') {
  656. $this->result[$key] = $value;
  657. } else {
  658. $this->result[] = $value; end ($this->result); $key = key ($this->result);
  659. }
  660. $this->path[$incoming_indent] = $key;
  661. return;
  662. }
  663. $history = array();
  664. // Unfolding inner array tree.
  665. $history[] = $_arr = $this->result;
  666. foreach ($this->path as $k) {
  667. $history[] = $_arr = $_arr[$k];
  668. }
  669. if ($this->_containsGroupAlias) {
  670. $value = $this->referenceContentsByAlias($this->_containsGroupAlias);
  671. $this->_containsGroupAlias = false;
  672. }
  673. // Adding string or numeric key to the innermost level or $this->arr.
  674. if (is_string($key) && $key == '<<') {
  675. if (!is_array ($_arr)) { $_arr = array (); }
  676. $_arr = array_merge ($_arr, $value);
  677. } else if ($key || $key === '' || $key === '0') {
  678. if (!is_array ($_arr))
  679. $_arr = array ($key=>$value);
  680. else
  681. $_arr[$key] = $value;
  682. } else {
  683. if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; }
  684. else { $_arr[] = $value; end ($_arr); $key = key ($_arr); }
  685. }
  686. $reverse_path = array_reverse($this->path);
  687. $reverse_history = array_reverse ($history);
  688. $reverse_history[0] = $_arr;
  689. $cnt = count($reverse_history) - 1;
  690. for ($i = 0; $i < $cnt; $i++) {
  691. $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i];
  692. }
  693. $this->result = $reverse_history[$cnt];
  694. $this->path[$incoming_indent] = $key;
  695. if ($this->_containsGroupAnchor) {
  696. $this->SavedGroups[$this->_containsGroupAnchor] = $this->path;
  697. if (is_array ($value)) {
  698. $k = key ($value);
  699. if (!is_int ($k)) {
  700. $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k;
  701. }
  702. }
  703. $this->_containsGroupAnchor = false;
  704. }
  705. }
  706. private static function startsLiteralBlock ($line) {
  707. $lastChar = substr (trim($line), -1);
  708. if ($lastChar != '>' && $lastChar != '|') return false;
  709. if ($lastChar == '|') return $lastChar;
  710. // HTML tags should not be counted as literal blocks.
  711. if (preg_match ('#<.*?>$#', $line)) return false;
  712. return $lastChar;
  713. }
  714. private static function greedilyNeedNextLine($line) {
  715. $line = trim ($line);
  716. if (!strlen($line)) return false;
  717. if (substr ($line, -1, 1) == ']') return false;
  718. if ($line[0] == '[') return true;
  719. if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true;
  720. return false;
  721. }
  722. private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) {
  723. $line = self::stripIndent($line, $indent);
  724. if ($literalBlockStyle !== '|') {
  725. $line = self::stripIndent($line);
  726. }
  727. $line = rtrim ($line, "\r\n\t ") . "\n";
  728. if ($literalBlockStyle == '|') {
  729. return $literalBlock . $line;
  730. }
  731. if (strlen($line) == 0)
  732. return rtrim($literalBlock, ' ') . "\n";
  733. if ($line == "\n" && $literalBlockStyle == '>') {
  734. return rtrim ($literalBlock, " \t") . "\n";
  735. }
  736. if ($line != "\n")
  737. $line = trim ($line, "\r\n ") . " ";
  738. return $literalBlock . $line;
  739. }
  740. function revertLiteralPlaceHolder ($lineArray, $literalBlock) {
  741. foreach ($lineArray as $k => $_) {
  742. if (is_array($_))
  743. $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock);
  744. else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder)
  745. $lineArray[$k] = rtrim ($literalBlock, " \r\n");
  746. }
  747. return $lineArray;
  748. }
  749. private static function stripIndent ($line, $indent = -1) {
  750. if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line));
  751. return substr ($line, $indent);
  752. }
  753. private function getParentPathByIndent ($indent) {
  754. if ($indent == 0) return array();
  755. $linePath = $this->path;
  756. do {
  757. end($linePath); $lastIndentInParentPath = key($linePath);
  758. if ($indent <= $lastIndentInParentPath) array_pop ($linePath);
  759. } while ($indent <= $lastIndentInParentPath);
  760. return $linePath;
  761. }
  762. private function clearBiggerPathValues ($indent) {
  763. if ($indent == 0) $this->path = array();
  764. if (empty ($this->path)) return true;
  765. foreach ($this->path as $k => $_) {
  766. if ($k > $indent) unset ($this->path[$k]);
  767. }
  768. return true;
  769. }
  770. private static function isComment ($line) {
  771. if (!$line) return false;
  772. if ($line[0] == '#') return true;
  773. if (trim($line, " \r\n\t") == '---') return true;
  774. return false;
  775. }
  776. private static function isEmpty ($line) {
  777. return (trim ($line) === '');
  778. }
  779. private function isArrayElement ($line) {
  780. if (!$line) return false;
  781. if ($line[0] != '-') return false;
  782. if (strlen ($line) > 3)
  783. if (substr($line,0,3) == '---') return false;
  784. return true;
  785. }
  786. private function isHashElement ($line) {
  787. return strpos($line, ':');
  788. }
  789. private function isLiteral ($line) {
  790. if ($this->isArrayElement($line)) return false;
  791. if ($this->isHashElement($line)) return false;
  792. return true;
  793. }
  794. private static function unquote ($value) {
  795. if (!$value) return $value;
  796. if (!is_string($value)) return $value;
  797. if ($value[0] == '\'') return trim ($value, '\'');
  798. if ($value[0] == '"') return trim ($value, '"');
  799. return $value;
  800. }
  801. private function startsMappedSequence ($line) {
  802. return ($line[0] == '-' && substr ($line, -1, 1) == ':');
  803. }
  804. private function returnMappedSequence ($line) {
  805. $array = array();
  806. $key = self::unquote(trim(substr($line,1,-1)));
  807. $array[$key] = array();
  808. $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key);
  809. return array($array);
  810. }
  811. private function returnMappedValue ($line) {
  812. $array = array();
  813. $key = self::unquote (trim(substr($line,0,-1)));
  814. $array[$key] = '';
  815. return $array;
  816. }
  817. private function startsMappedValue ($line) {
  818. return (substr ($line, -1, 1) == ':');
  819. }
  820. private function isPlainArray ($line) {
  821. return ($line[0] == '[' && substr ($line, -1, 1) == ']');
  822. }
  823. private function returnPlainArray ($line) {
  824. return $this->_toType($line);
  825. }
  826. private function returnKeyValuePair ($line) {
  827. $array = array();
  828. $key = '';
  829. if (strpos ($line, ':')) {
  830. // It's a key/value pair most likely
  831. // If the key is in double quotes pull it out
  832. if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
  833. $value = trim(str_replace($matches[1],'',$line));
  834. $key = $matches[2];
  835. } else {
  836. // Do some guesswork as to the key and the value
  837. $explode = explode(':',$line);
  838. $key = trim($explode[0]);
  839. array_shift($explode);
  840. $value = trim(implode(':',$explode));
  841. }
  842. // Set the type of the value. Int, string, etc
  843. $value = $this->_toType($value);
  844. if ($key === '0') $key = '__!YAMLZero';
  845. $array[$key] = $value;
  846. } else {
  847. $array = array ($line);
  848. }
  849. return $array;
  850. }
  851. private function returnArrayElement ($line) {
  852. if (strlen($line) <= 1) return array(array()); // Weird %)
  853. $array = array();
  854. $value = trim(substr($line,1));
  855. $value = $this->_toType($value);
  856. $array[] = $value;
  857. return $array;
  858. }
  859. private function nodeContainsGroup ($line) {
  860. $symbolsForReference = 'A-z0-9_\-';
  861. if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
  862. if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
  863. if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
  864. if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1];
  865. if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1];
  866. if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1];
  867. return false;
  868. }
  869. private function addGroup ($line, $group) {
  870. if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1);
  871. if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1);
  872. //print_r ($this->path);
  873. }
  874. private function stripGroup ($line, $group) {
  875. $line = trim(str_replace($group, '', $line));
  876. return $line;
  877. }
  878. }
  879. // Enable use of Spyc from command line
  880. // The syntax is the following: php spyc.php spyc.yaml
  881. define ('SPYC_FROM_COMMAND_LINE', false);
  882. do {
  883. if (!SPYC_FROM_COMMAND_LINE) break;
  884. if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break;
  885. if (empty ($_SERVER['PHP_SELF']) || $_SERVER['PHP_SELF'] != 'spyc.php') break;
  886. $file = $argv[1];
  887. printf ("Spyc loading file: %s\n", $file);
  888. print_r (spyc_load_file ($file));
  889. } while (0);
  890. /*
  891. *
  892. * The MIT License
  893. *
  894. * Copyright (c) 2009, ZX, Ferry Boender
  895. *
  896. * Permission is hereby granted, free of charge, to any person obtaining a copy
  897. * of this software and associated documentation files (the "Software"), to deal
  898. * in the Software without restriction, including without limitation the rights
  899. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  900. * copies of the Software, and to permit persons to whom the Software is
  901. * furnished to do so, subject to the following conditions:
  902. *
  903. * The above copyright notice and this permission notice shall be included in
  904. * all copies or substantial portions of the Software.
  905. *
  906. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  907. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  908. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  909. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  910. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  911. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  912. * THE SOFTWARE.
  913. *
  914. * Modified by Scott Zeid <s@srwz.us> to fix Template::templateFromString().
  915. *
  916. */
  917. define("TEMPLUM_VERSION", "0.4.0-sz-1");
  918. /**
  919. * @brief Templum errors.
  920. *
  921. * This exception is thrown by the Templum class when errors occur
  922. * during instantiation or when loading and parsing templates.
  923. */
  924. class TemplumError extends Exception {
  925. /**
  926. * @brief Create a new TemplumError instance
  927. * @param $message (string) The error message.
  928. * @param $code (int) The error code
  929. */
  930. public function TemplumError($message, $code = 0) {
  931. parent::__construct($message, $code);
  932. }
  933. }
  934. /**
  935. * @brief TemplumTemplate errors.
  936. *
  937. * This exception is thrown by the TemplumTemplate class when errors occur
  938. * during the execution of templates. PHP errors, warnings and notices that
  939. * occur during the template execution are captured by the TemplumTemplate class and
  940. * are thrown as TemplumTemplateError exceptions.
  941. */
  942. class TemplumTemplateError extends Exception {
  943. protected $template = NULL; /**< The TemplumTemplate instance causing the error. */
  944. /**
  945. * @brief Create a new TemplumTemplateError instance
  946. * @param $message (string) The error message.
  947. * @param $code (int) The error code
  948. * @param $template (TemplumTemplate) The template containing the error.
  949. */
  950. public function TemplumTemplateError($message, $code = 0, $template = NULL) {
  951. $this->template = $template;
  952. parent::__construct($message, $code);
  953. }
  954. /**
  955. * @brief Return the TemplumTemplate instance that contains the error.
  956. * @return (TemplumTemplate) The template containing the error or NULL if not available.
  957. */
  958. public function getTemplate() {
  959. return($this->template);
  960. }
  961. }
  962. /**
  963. * @brief Templum Templating Engine.
  964. *
  965. * This is the main Templum class. It takes care of retrieval, caching and
  966. * compiling of (translated) templates.
  967. */
  968. class Templum {
  969. /**
  970. * @brief Create a new Templum instance.
  971. * @param $templatePath (string) The full or relative path to the template directory.
  972. * @param $varsUniversal (array) An array of key/value pairs that will be exported to every template retrieved using this template engine instance.
  973. * @param $locale (string) The locale for the templates to retrieve. If a file with the suffix noted in $locale is available, it will be returned instead of the default .tpl file.
  974. * @throw TemplumError if the $templatePath can't be found or isn't a directory.
  975. */
  976. public function Templum($templatePath, $varsUniversal = array(), $locale = NULL) {
  977. if (!file_exists($templatePath)) {
  978. throw new TemplumError("No such file or directory: $templatePath", 1);
  979. }
  980. if (!is_dir($templatePath)) {
  981. throw new TemplumError("Not a directory: $templatePath", 2);
  982. }
  983. $this->templatePath = rtrim(realpath($templatePath), '/');
  984. $this->varsUniversal = $varsUniversal;
  985. $this->locale = $locale;
  986. $this->autoEscape = True;
  987. $this->cache = array();
  988. }
  989. /**
  990. * @brief Set a universal variable which will available in each template created with this Templum instance.
  991. * @param $varName (string) The name of the variable. This will become available in the template as $VARNAME.
  992. * @param $varValue (mixed) The value of the variable.
  993. */
  994. public function setVar($varName, $varValue) {
  995. $this->varsUniversal[$varName] = $varValue;
  996. }
  997. /**
  998. * @brief Turn the auto escape on or off. If on, all content rendered using {{ and }} will automatically be escaped with htmlspecialchars().
  999. * @param $escape (boolean) True of False. If True, auto escaping is turned on (this is the default). If False, it is turned off for templates retrieved with this Templum engine.
  1000. * @note Auto escaping can be overridden by passing the $autoEscape option to the template() and templateFromString() methods.
  1001. */
  1002. public function setAutoEscape($escape = True) {
  1003. $this->autoEscape = $escape;
  1004. }
  1005. /**
  1006. * @brief Set the locale for templates.
  1007. * @param $locale (string) The locale for the templates to retrieve. If a file with the suffix noted in $locale is available, it will be returned instead of the default .tpl file.
  1008. */
  1009. public function setLocale($locale) {
  1010. $this->locale = $locale;
  1011. }
  1012. /**
  1013. * @brief Retrieve a template by from disk (caching it in memory for the duration of the Templum instance lifetime) or from cache.
  1014. * @param $path (string) TemplumTemplate path, without the .tpl extension, relative to the templatePath.
  1015. * @param $varsGlobal (array) Array of key/value pairs that will be exported to the returned template and all templates included by that template.
  1016. * @param $autoEscape (boolean) Whether to auto escape {{ and }} output with htmlspecialchars()
  1017. * @throw TemplumError if the template couldn't be read.
  1018. */
  1019. public function template($path, $varsGlobal = array(), $autoEscape = NULL) {
  1020. $fpath = $this->templatePath . '/' . trim($path, '/').'.tpl';
  1021. if ($autoEscape === NULL) {
  1022. $autoEscape = $this->autoEscape;
  1023. }
  1024. // Check for translated version of this template.
  1025. if (!empty($this->locale)) {
  1026. // Check if the translated template exists in the cache. If it
  1027. // does, returned the cached result. Otherwise check the disk for
  1028. // the translated template.
  1029. $fpathTrans = realpath($fpath.'.'.$this->locale);
  1030. if ($fpathTrans !== False) {
  1031. if (array_key_exists($fpathTrans, $this->cache)) {
  1032. return($this->cache[$fpathTrans]);
  1033. } else {
  1034. if (file_exists($fpathTrans)) {
  1035. $fpath = $fpathTrans;
  1036. }
  1037. }
  1038. }
  1039. // Check the non-translated version of this template
  1040. } else {
  1041. // Check the cache for the non-translated template.
  1042. $rpath = realpath($fpath);
  1043. if($rpath === False) {
  1044. throw new TemplumError("Template not found or not a file: $fpath", 3);
  1045. }
  1046. if (array_key_exists($rpath, $this->cache)) {
  1047. return($this->cache[$rpath]);
  1048. }
  1049. $fpath = $rpath;
  1050. }
  1051. // Check if the template exists.
  1052. if (!is_file($fpath)) {
  1053. throw new TemplumError("Template not found or not a file: $fpath", 3);
  1054. }
  1055. if (!is_readable($fpath)) {
  1056. throw new TemplumError("Template not readable: $fpath", 4);
  1057. }
  1058. // Load the base or translated template.
  1059. $template = new TemplumTemplate(
  1060. $this,
  1061. $fpath,
  1062. $this->compile(file_get_contents($fpath), $autoEscape),
  1063. array_merge($this->varsUniversal, $varsGlobal)
  1064. );
  1065. $this->cache[$fpath] = $template;
  1066. return($template);
  1067. }
  1068. /**
  1069. * @brief Create a TemplumTemplate from a string.
  1070. *
  1071. * Create a TemplumTemplate instance using $contents as the template contents.
  1072. * This severely limited what you can do with the TemplumTemplate. There will be
  1073. * no including from the template, no translations, no caching, etc.
  1074. *
  1075. * @param $contents (string) The template contents.
  1076. * @param $autoEscape (boolean) Whether to auto escape {{ and }} output with htmlspecialchars()
  1077. * @returns (TemplumTemplate) TemplumTemplate class instance.
  1078. */
  1079. public static function templateFromString($contents, $autoEscape = True) {
  1080. //if ($autoEscape === Null) {
  1081. // $autoEscape = $this->autoEscape;
  1082. //}
  1083. // Load the base or translated template.
  1084. $template = new TemplumTemplate(
  1085. NULL,
  1086. "FROM_STRING",
  1087. self::compile($contents, $autoEscape),
  1088. array()
  1089. );
  1090. return($template);
  1091. }
  1092. /**
  1093. * @brief Compile a template string to PHP code.
  1094. * @param $contents (string) String to compile to PHP code.
  1095. * @param $autoEscape (boolean) Whether to auto escape {{ and }} output with htmlspecialchars()
  1096. * @note This method is used by the Templum class itself, and shouldn't be called directly yourself. Use templateFromString() instead.
  1097. */
  1098. private function compile($contents, $autoEscape = True) {
  1099. // Parse custom short-hand tags to PHP code.
  1100. $contents = preg_replace(
  1101. array(
  1102. "/{{/",
  1103. "/}}\n/",
  1104. "/}}/",
  1105. "/\[\[/",
  1106. "/\]\]/",
  1107. '/^\s*@(.*)$/m',
  1108. '/\[:\s*block\s(.*)\s*:\](.*)\[:\s*endblock\s*:\]/Usm',
  1109. ),
  1110. array(
  1111. $autoEscape ? "<?php echo(htmlspecialchars(" : "<?php echo(",
  1112. $autoEscape ? ")); ?>\n\n" : "); ?>\n\n",
  1113. $autoEscape ? ")); ?>" : "); ?>",
  1114. "<?php ",
  1115. " ?>",
  1116. "<?php \\1 ?>",
  1117. "<?php if (array_key_exists('\\1', \$this->inheritBlocks)) { print(\$this->inheritBlocks['\\1']); } else if (\$this->inheritFrom === NULL) { ?>\\2<?php } else { ob_start(); ?>\\2<?php \$this->inheritBlocks['\\1'] = ob_get_contents(); ob_end_clean(); } ?>",
  1118. ),
  1119. $contents
  1120. );
  1121. return($contents);
  1122. }
  1123. }
  1124. /**
  1125. * @brief Template class
  1126. *
  1127. * This is the TemplumTemplate class. It represents a template and handles the
  1128. * actual rendering of the template, as well as catching errors during
  1129. * rendering. It also contains helper methods which can be used in templates.
  1130. */
  1131. class TemplumTemplate {
  1132. /**
  1133. * @brief Create a new TemplumTemplate instance. You'd normally get an instance from a Templum class instance.
  1134. * @param $templum (Templum instance) The Templum class instance that generated this TemplumTemplate instance.
  1135. * @param $filename (string) The filename of this template.
  1136. * @param $contents (string) The compiled contents of this template.
  1137. * @param $varsGlobal (array) An array of key/value pairs which represent the global variables for this template and the templates it includes.
  1138. */
  1139. public function TemplumTemplate($templum, $filename, $contents, $varsGlobal = array()) {
  1140. $this->templum = $templum;
  1141. $this->filename = $filename;
  1142. $this->contents = $contents;
  1143. $this->varsGlobal = $varsGlobal;
  1144. $this->inheritFrom = NULL;
  1145. $this->inheritBlocks = array();
  1146. }
  1147. /**
  1148. * @brief Add an global variable. The global variable will be available to this templates and all the templates it includes.
  1149. * @param $varName (string) The name of the variable.
  1150. * @param $varValue (mixed) The value of the variable.
  1151. */
  1152. public function setVar($varName, $varValue) {
  1153. $this->varsGlobal[$varName] = $varValue;
  1154. }
  1155. /**
  1156. * @brief Render the contents of the template and return it as a string.
  1157. * @param $varsLocal (array) An array of key/value pairs which represent the local variables for this template.
  1158. * @return (string) The rendered contents of the template.
  1159. */
  1160. public function render($varsLocal = array()) {
  1161. // Extract the Universal (embedded in global), Global and
  1162. // Localvariables into the current scope.
  1163. extract($this->varsGlobal);
  1164. extract($varsLocal);
  1165. // Start output buffering so we can capture the output of the eval.
  1166. ob_start();
  1167. // Temporary set the error handler so we can show the faulty template
  1168. // file. Render the contents, reset the error handler and return the
  1169. // rendered contents.
  1170. $this->errorHandlerOrig = set_error_handler(array($this, 'errorHandler'));
  1171. eval("?>" . $this->contents);
  1172. restore_error_handler();
  1173. // Stop output buffering and return the contents of the buffer
  1174. // (rendered template).
  1175. $result = ob_get_contents();
  1176. ob_end_clean();
  1177. if ($this->inheritFrom !== NULL) {
  1178. $this->inheritFrom->inheritBlocks = $this->inheritBlocks;
  1179. $result = $this->inheritFrom->render();
  1180. }
  1181. return($result);
  1182. }
  1183. /**
  1184. * @brief The error handler that handles errors during the parsing of the template.
  1185. * @param $nr (int) Error code
  1186. * @param $string (string) Error message
  1187. * @param $file (string) Filename of the file in which the erorr occurred.
  1188. * @param $line (int) Linenumber of the line on which the error occurred.
  1189. * @note Do not call this yourself. It is used internally by Templum but must be public.
  1190. */
  1191. public function errorHandler($nr, $string, $file, $line) {
  1192. // We can restore the old error handler, otherwise this error handler
  1193. // will stay active because we throw an exception below.
  1194. restore_error_handler();
  1195. // If this is reached, it means we were still in Output Buffering mode.
  1196. // Stop output buffering, or we'll end up with template text on the
  1197. // Stdout.
  1198. ob_end_clean();
  1199. // Throw the exception
  1200. throw new TemplumTemplateError("$string (file: {$this->filename}, line $line)", 1, $this);
  1201. }
  1202. /**
  1203. * @brief Include another template.
  1204. * @param $template (string) The template to include.
  1205. * @param $varsLocal (array) An array of key/value pairs which represent the local variables for this template.
  1206. */
  1207. public function inc($template, $varsLocal = array()) {
  1208. if (!isset($this->templum)) {
  1209. throw new TemplumTemplateError("Cannot include templates in a TemplumTemplate instance created from a string.", 2, $this);
  1210. }
  1211. $t = $this->templum->template($template, $varsLocal);
  1212. print($t->render());
  1213. }
  1214. /**
  1215. * @brief Inherit from a parent template.
  1216. * @param $template (string) The template to inherit from.
  1217. */
  1218. public function inherit($template) {
  1219. $this->inheritFrom = $this->templum->template($template);
  1220. }
  1221. }
  1222. /* is_mobile()
  1223. * Shitty mobile device detection based on shitty user agent strings.
  1224. *
  1225. * Copyright (C) 2009-2012 Scott Zeid
  1226. *
  1227. * Permission is hereby granted, free of charge, to any person obtaining a copy
  1228. * of this software and associated documentation files (the "Software"), to deal
  1229. * in the Software without restriction, including without limitation the rights
  1230. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  1231. * copies of the Software, and to permit persons to whom the Software is
  1232. * furnished to do so, subject to the following conditions:
  1233. *
  1234. * The above copyright notice and this permission notice shall be included in
  1235. * all copies or substantial portions of the Software.
  1236. *
  1237. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1238. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1239. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1240. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1241. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1242. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  1243. * THE SOFTWARE.
  1244. *
  1245. * Except as contained in this notice, the name(s) of the above copyright holders
  1246. * shall not be used in advertising or otherwise to promote the sale, use or
  1247. * other dealings in this Software without prior written authorization.
  1248. */
  1249. /**
  1250. * Determine whether the user agent represents a mobile device.
  1251. *
  1252. * The user can use the following query string parameters to override this
  1253. * function's output:
  1254. * * !mobile, nomobile - Cause this function to return False.
  1255. * * mobile - Cause this function to return True.
  1256. * * mobile=[...], device=[...] - Override the device type.
  1257. *
  1258. * device=[...] takes precedence over mobile=[...].
  1259. *
  1260. * Valid device types are firefox-tablet, firefox, chrome-tablet, chrome,
  1261. * android-tablet, android, webos, tablet, unknown, apple, and apple-tablet
  1262. * (listed in descending order of the author's personal preference). Android
  1263. * tablets and iPads are not considered to be mobile devices, but is_mobile()
  1264. * will still return a device name ending in "-tablet", as appropriate for the
  1265. * device in question.
  1266. *
  1267. * If the user is running Firefox Mobile, the device name would be "firefox",
  1268. * or "firefox-tablet" if it is a tablet. The same is true for users using
  1269. * Chrome, except (obviously) "firefox" would be replaced with "chrome".
  1270. * Although it has been discontinued for a while, support for the HP Touchpad
  1271. * may be added in the future; its device name would be "webos-tablet".
  1272. *
  1273. * @param bool $return_device Return a string representing the type of device.
  1274. * @param bool $use_get Allow overriding default behavior using query strings.
  1275. * @return mixed If $return_device is false, returns a boolean value.
  1276. */
  1277. function is_mobile($return_device = False, $use_get = True) {
  1278. # config
  1279. $user_agent = $_SERVER["HTTP_USER_AGENT"];
  1280. $nomobile = False; $forcemobile = False; $forcedevice = "";
  1281. if ($use_get) {
  1282. if (isset($_GET["!mobile"]) || isset($_GET["nomobile"]))
  1283. $nomobile = True;
  1284. elseif (isset($_GET["mobile"])) {
  1285. $forcedevice = strtolower($_GET["mobile"]);
  1286. if (!stristr($forcedevice, "tablet") && $forcedevice != "ipad")
  1287. $forcemobile = True;
  1288. if (!$forcedevice) $forcedevice = "unknown";
  1289. }
  1290. if (!empty($_GET["device"])) {
  1291. $forcedevice = strtolower($_GET["device"]);
  1292. if (!stristr($forcedevice, "tablet") && $forcedevice != "ipad") {
  1293. $forcemobile = True;
  1294. $nomobile = False;
  1295. }
  1296. }
  1297. }
  1298. # is mobile device?
  1299. if (((
  1300. (stristr($user_agent, "Android") && !stristr($user_agent, "Android 3.") &&
  1301. stristr($user_agent, "Mobile")) ||
  1302. stristr($user_agent, "webOS") ||
  1303. ((stristr($user_agent, "Firefox") || stristr($user_agent, "Fennec")) &&
  1304. stristr($user_agent, "Mobile")) ||
  1305. stristr($user_agent, "iPhone") || stristr($user_agent, "iPod")
  1306. ) && !stristr($user_agent, "Tablet") && $nomobile == False) ||
  1307. $forcemobile == True)
  1308. $mobile = True;
  1309. else
  1310. $mobile = False;
  1311. # which mobile device
  1312. $device = "unknown";
  1313. if (stristr($user_agent, "Android")) {
  1314. if (!stristr($user_agent, "Mobile") || stristr($user_agent, "Android 3."))
  1315. $device = "android-tablet";
  1316. else $device = "android";
  1317. if (stristr($user_agent, "Chrome"))
  1318. $device = str_replace("android", "chrome", $device);
  1319. }
  1320. if (stristr($user_agent, "Firefox") || stristr($user_agent, "Fennec")) {
  1321. if (stristr($user_agent, "Ta…

Large files files are truncated, but you can click here to view the full file