PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/View/Compilers/BladeCompiler.php

https://gitlab.com/techniconline/kmc
PHP | 797 lines | 313 code | 101 blank | 383 comment | 16 complexity | c4f0d1ffce2030128ecfe1502d2f9929 MD5 | raw file
  1. <?php namespace Illuminate\View\Compilers;
  2. class BladeCompiler extends Compiler implements CompilerInterface
  3. {
  4. /**
  5. * All of the registered extensions.
  6. *
  7. * @var array
  8. */
  9. protected $extensions = array();
  10. /**
  11. * The file currently being compiled.
  12. *
  13. * @var string
  14. */
  15. protected $path;
  16. /**
  17. * All of the available compiler functions.
  18. *
  19. * @var array
  20. */
  21. protected $compilers = array(
  22. 'Extensions',
  23. 'Statements',
  24. 'Comments',
  25. 'Echos',
  26. );
  27. /**
  28. * Array of opening and closing tags for raw echos.
  29. *
  30. * @var array
  31. */
  32. protected $rawTags = array('{!!', '!!}');
  33. /**
  34. * Array of opening and closing tags for regular echos.
  35. *
  36. * @var array
  37. */
  38. protected $contentTags = array('{{', '}}');
  39. /**
  40. * Array of opening and closing tags for escaped echos.
  41. *
  42. * @var array
  43. */
  44. protected $escapedTags = array('{{{', '}}}');
  45. /**
  46. * The "regular" / legacy echo string format.
  47. *
  48. * @var string
  49. */
  50. protected $echoFormat = 'e(%s)';
  51. /**
  52. * Array of footer lines to be added to template.
  53. *
  54. * @var array
  55. */
  56. protected $footer = array();
  57. /**
  58. * Counter to keep track of nested forelse statements.
  59. *
  60. * @var int
  61. */
  62. protected $forelseCounter = 0;
  63. /**
  64. * Compile the view at the given path.
  65. *
  66. * @param string $path
  67. * @return void
  68. */
  69. public function compile($path = null)
  70. {
  71. if ($path) {
  72. $this->setPath($path);
  73. }
  74. $contents = $this->compileString($this->files->get($this->getPath()));
  75. if (!is_null($this->cachePath)) {
  76. $this->files->put($this->getCompiledPath($this->getPath()), $contents);
  77. }
  78. }
  79. /**
  80. * Get the path currently being compiled.
  81. *
  82. * @return string
  83. */
  84. public function getPath()
  85. {
  86. return $this->path;
  87. }
  88. /**
  89. * Set the path currently being compiled.
  90. *
  91. * @param string $path
  92. * @return void
  93. */
  94. public function setPath($path)
  95. {
  96. $this->path = $path;
  97. }
  98. /**
  99. * Compile the given Blade template contents.
  100. *
  101. * @param string $value
  102. * @return string
  103. */
  104. public function compileString($value)
  105. {
  106. $result = '';
  107. $this->footer = [];
  108. // Here we will loop through all of the tokens returned by the Zend lexer and
  109. // parse each one into the corresponding valid PHP. We will then have this
  110. // template as the correctly rendered PHP that can be rendered natively.
  111. foreach (token_get_all($value) as $token) {
  112. $result .= is_array($token) ? $this->parseToken($token) : $token;
  113. }
  114. // If there are any footer lines that need to get added to a template we will
  115. // add them here at the end of the template. This gets used mainly for the
  116. // template inheritance via the extends keyword that should be appended.
  117. if (count($this->footer) > 0) {
  118. $result = ltrim($result, PHP_EOL)
  119. . PHP_EOL . implode(PHP_EOL, array_reverse($this->footer));
  120. }
  121. return $result;
  122. }
  123. /**
  124. * Parse the tokens from the template.
  125. *
  126. * @param array $token
  127. * @return string
  128. */
  129. protected function parseToken($token)
  130. {
  131. list($id, $content) = $token;
  132. if ($id == T_INLINE_HTML) {
  133. foreach ($this->compilers as $type) {
  134. $content = $this->{"compile{$type}"}($content);
  135. }
  136. }
  137. return $content;
  138. }
  139. /**
  140. * Execute the user defined extensions.
  141. *
  142. * @param string $value
  143. * @return string
  144. */
  145. protected function compileExtensions($value)
  146. {
  147. foreach ($this->extensions as $compiler) {
  148. $value = call_user_func($compiler, $value, $this);
  149. }
  150. return $value;
  151. }
  152. /**
  153. * Compile Blade comments into valid PHP.
  154. *
  155. * @param string $value
  156. * @return string
  157. */
  158. protected function compileComments($value)
  159. {
  160. $pattern = sprintf('/%s--((.|\s)*?)--%s/', $this->contentTags[0], $this->contentTags[1]);
  161. return preg_replace($pattern, '<?php /*$1*/ ?>', $value);
  162. }
  163. /**
  164. * Compile Blade echos into valid PHP.
  165. *
  166. * @param string $value
  167. * @return string
  168. */
  169. protected function compileEchos($value)
  170. {
  171. foreach ($this->getEchoMethods() as $method => $length) {
  172. $value = $this->$method($value);
  173. }
  174. return $value;
  175. }
  176. /**
  177. * Get the echo methods in the proper order for compilation.
  178. *
  179. * @return array
  180. */
  181. protected function getEchoMethods()
  182. {
  183. $methods = [
  184. "compileRawEchos" => strlen(stripcslashes($this->rawTags[0])),
  185. "compileEscapedEchos" => strlen(stripcslashes($this->escapedTags[0])),
  186. "compileRegularEchos" => strlen(stripcslashes($this->contentTags[0])),
  187. ];
  188. uksort($methods, function ($method1, $method2) use ($methods) {
  189. // Ensure the longest tags are processed first
  190. if ($methods[$method1] > $methods[$method2]) return -1;
  191. if ($methods[$method1] < $methods[$method2]) return 1;
  192. // Otherwise give preference to raw tags (assuming they've overridden)
  193. if ($method1 === "compileRawEchos") return -1;
  194. if ($method2 === "compileRawEchos") return 1;
  195. if ($method1 === "compileEscapedEchos") return -1;
  196. if ($method2 === "compileEscapedEchos") return 1;
  197. });
  198. return $methods;
  199. }
  200. /**
  201. * Compile Blade statements that start with "@".
  202. *
  203. * @param string $value
  204. * @return mixed
  205. */
  206. protected function compileStatements($value)
  207. {
  208. $callback = function ($match) {
  209. if (method_exists($this, $method = 'compile' . ucfirst($match[1]))) {
  210. $match[0] = $this->$method(array_get($match, 3));
  211. }
  212. return isset($match[3]) ? $match[0] : $match[0] . $match[2];
  213. };
  214. return preg_replace_callback('/\B@(\w+)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value);
  215. }
  216. /**
  217. * Compile the "raw" echo statements.
  218. *
  219. * @param string $value
  220. * @return string
  221. */
  222. protected function compileRawEchos($value)
  223. {
  224. $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->rawTags[0], $this->rawTags[1]);
  225. $callback = function ($matches) {
  226. $whitespace = empty($matches[3]) ? '' : $matches[3] . $matches[3];
  227. return $matches[1] ? substr($matches[0], 1) : '<?php echo ' . $this->compileEchoDefaults($matches[2]) . '; ?>' . $whitespace;
  228. };
  229. return preg_replace_callback($pattern, $callback, $value);
  230. }
  231. /**
  232. * Compile the "regular" echo statements.
  233. *
  234. * @param string $value
  235. * @return string
  236. */
  237. protected function compileRegularEchos($value)
  238. {
  239. $pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $this->contentTags[0], $this->contentTags[1]);
  240. $callback = function ($matches) {
  241. $whitespace = empty($matches[3]) ? '' : $matches[3] . $matches[3];
  242. $wrapped = sprintf($this->echoFormat, $this->compileEchoDefaults($matches[2]));
  243. return $matches[1] ? substr($matches[0], 1) : '<?php echo ' . $wrapped . '; ?>' . $whitespace;
  244. };
  245. return preg_replace_callback($pattern, $callback, $value);
  246. }
  247. /**
  248. * Compile the escaped echo statements.
  249. *
  250. * @param string $value
  251. * @return string
  252. */
  253. protected function compileEscapedEchos($value)
  254. {
  255. $pattern = sprintf('/%s\s*(.+?)\s*%s(\r?\n)?/s', $this->escapedTags[0], $this->escapedTags[1]);
  256. $callback = function ($matches) {
  257. $whitespace = empty($matches[2]) ? '' : $matches[2] . $matches[2];
  258. return '<?php echo e(' . $this->compileEchoDefaults($matches[1]) . '); ?>' . $whitespace;
  259. };
  260. return preg_replace_callback($pattern, $callback, $value);
  261. }
  262. /**
  263. * Compile the default values for the echo statement.
  264. *
  265. * @param string $value
  266. * @return string
  267. */
  268. public function compileEchoDefaults($value)
  269. {
  270. return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/s', 'isset($1) ? $1 : $2', $value);
  271. }
  272. /**
  273. * Compile the each statements into valid PHP.
  274. *
  275. * @param string $expression
  276. * @return string
  277. */
  278. protected function compileEach($expression)
  279. {
  280. return "<?php echo \$__env->renderEach{$expression}; ?>";
  281. }
  282. /**
  283. * Compile the yield statements into valid PHP.
  284. *
  285. * @param string $expression
  286. * @return string
  287. */
  288. protected function compileYield($expression)
  289. {
  290. return "<?php echo \$__env->yieldContent{$expression}; ?>";
  291. }
  292. /**
  293. * Compile the show statements into valid PHP.
  294. *
  295. * @param string $expression
  296. * @return string
  297. */
  298. protected function compileShow($expression)
  299. {
  300. return "<?php echo \$__env->yieldSection(); ?>";
  301. }
  302. /**
  303. * Compile the section statements into valid PHP.
  304. *
  305. * @param string $expression
  306. * @return string
  307. */
  308. protected function compileSection($expression)
  309. {
  310. return "<?php \$__env->startSection{$expression}; ?>";
  311. }
  312. /**
  313. * Compile the append statements into valid PHP.
  314. *
  315. * @param string $expression
  316. * @return string
  317. */
  318. protected function compileAppend($expression)
  319. {
  320. return "<?php \$__env->appendSection(); ?>";
  321. }
  322. /**
  323. * Compile the end-section statements into valid PHP.
  324. *
  325. * @param string $expression
  326. * @return string
  327. */
  328. protected function compileEndsection($expression)
  329. {
  330. return "<?php \$__env->stopSection(); ?>";
  331. }
  332. /**
  333. * Compile the stop statements into valid PHP.
  334. *
  335. * @param string $expression
  336. * @return string
  337. */
  338. protected function compileStop($expression)
  339. {
  340. return "<?php \$__env->stopSection(); ?>";
  341. }
  342. /**
  343. * Compile the overwrite statements into valid PHP.
  344. *
  345. * @param string $expression
  346. * @return string
  347. */
  348. protected function compileOverwrite($expression)
  349. {
  350. return "<?php \$__env->stopSection(true); ?>";
  351. }
  352. /**
  353. * Compile the unless statements into valid PHP.
  354. *
  355. * @param string $expression
  356. * @return string
  357. */
  358. protected function compileUnless($expression)
  359. {
  360. return "<?php if ( ! $expression): ?>";
  361. }
  362. /**
  363. * Compile the end unless statements into valid PHP.
  364. *
  365. * @param string $expression
  366. * @return string
  367. */
  368. protected function compileEndunless($expression)
  369. {
  370. return "<?php endif; ?>";
  371. }
  372. /**
  373. * Compile the lang statements into valid PHP.
  374. *
  375. * @param string $expression
  376. * @return string
  377. */
  378. protected function compileLang($expression)
  379. {
  380. return "<?php echo \\Illuminate\\Support\\Facades\\Lang::get$expression; ?>";
  381. }
  382. /**
  383. * Compile the choice statements into valid PHP.
  384. *
  385. * @param string $expression
  386. * @return string
  387. */
  388. protected function compileChoice($expression)
  389. {
  390. return "<?php echo \\Illuminate\\Support\\Facades\\Lang::choice$expression; ?>";
  391. }
  392. /**
  393. * Compile the else statements into valid PHP.
  394. *
  395. * @param string $expression
  396. * @return string
  397. */
  398. protected function compileElse($expression)
  399. {
  400. return "<?php else: ?>";
  401. }
  402. /**
  403. * Compile the for statements into valid PHP.
  404. *
  405. * @param string $expression
  406. * @return string
  407. */
  408. protected function compileFor($expression)
  409. {
  410. return "<?php for{$expression}: ?>";
  411. }
  412. /**
  413. * Compile the foreach statements into valid PHP.
  414. *
  415. * @param string $expression
  416. * @return string
  417. */
  418. protected function compileForeach($expression)
  419. {
  420. return "<?php foreach{$expression}: ?>";
  421. }
  422. /**
  423. * Compile the forelse statements into valid PHP.
  424. *
  425. * @param string $expression
  426. * @return string
  427. */
  428. protected function compileForelse($expression)
  429. {
  430. $empty = '$__empty_' . ++$this->forelseCounter;
  431. return "<?php {$empty} = true; foreach{$expression}: {$empty} = false; ?>";
  432. }
  433. /**
  434. * Compile the if statements into valid PHP.
  435. *
  436. * @param string $expression
  437. * @return string
  438. */
  439. protected function compileIf($expression)
  440. {
  441. return "<?php if{$expression}: ?>";
  442. }
  443. /**
  444. * Compile the else-if statements into valid PHP.
  445. *
  446. * @param string $expression
  447. * @return string
  448. */
  449. protected function compileElseif($expression)
  450. {
  451. return "<?php elseif{$expression}: ?>";
  452. }
  453. /**
  454. * Compile the forelse statements into valid PHP.
  455. *
  456. * @param string $expression
  457. * @return string
  458. */
  459. protected function compileEmpty($expression)
  460. {
  461. $empty = '$__empty_' . $this->forelseCounter--;
  462. return "<?php endforeach; if ({$empty}): ?>";
  463. }
  464. /**
  465. * Compile the while statements into valid PHP.
  466. *
  467. * @param string $expression
  468. * @return string
  469. */
  470. protected function compileWhile($expression)
  471. {
  472. return "<?php while{$expression}: ?>";
  473. }
  474. /**
  475. * Compile the end-while statements into valid PHP.
  476. *
  477. * @param string $expression
  478. * @return string
  479. */
  480. protected function compileEndwhile($expression)
  481. {
  482. return "<?php endwhile; ?>";
  483. }
  484. /**
  485. * Compile the end-for statements into valid PHP.
  486. *
  487. * @param string $expression
  488. * @return string
  489. */
  490. protected function compileEndfor($expression)
  491. {
  492. return "<?php endfor; ?>";
  493. }
  494. /**
  495. * Compile the end-for-each statements into valid PHP.
  496. *
  497. * @param string $expression
  498. * @return string
  499. */
  500. protected function compileEndforeach($expression)
  501. {
  502. return "<?php endforeach; ?>";
  503. }
  504. /**
  505. * Compile the end-if statements into valid PHP.
  506. *
  507. * @param string $expression
  508. * @return string
  509. */
  510. protected function compileEndif($expression)
  511. {
  512. return "<?php endif; ?>";
  513. }
  514. /**
  515. * Compile the end-for-else statements into valid PHP.
  516. *
  517. * @param string $expression
  518. * @return string
  519. */
  520. protected function compileEndforelse($expression)
  521. {
  522. return "<?php endif; ?>";
  523. }
  524. /**
  525. * Compile the extends statements into valid PHP.
  526. *
  527. * @param string $expression
  528. * @return string
  529. */
  530. protected function compileExtends($expression)
  531. {
  532. if (starts_with($expression, '(')) {
  533. $expression = substr($expression, 1, -1);
  534. }
  535. $data = "<?php echo \$__env->make($expression, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
  536. $this->footer[] = $data;
  537. return '';
  538. }
  539. /**
  540. * Compile the include statements into valid PHP.
  541. *
  542. * @param string $expression
  543. * @return string
  544. */
  545. protected function compileInclude($expression)
  546. {
  547. if (starts_with($expression, '(')) {
  548. $expression = substr($expression, 1, -1);
  549. }
  550. return "<?php echo \$__env->make($expression, array_except(get_defined_vars(), array('__data', '__path')))->render(); ?>";
  551. }
  552. /**
  553. * Compile the stack statements into the content.
  554. *
  555. * @param string $expression
  556. * @return string
  557. */
  558. protected function compileStack($expression)
  559. {
  560. return "<?php echo \$__env->yieldContent{$expression}; ?>";
  561. }
  562. /**
  563. * Compile the push statements into valid PHP.
  564. *
  565. * @param string $expression
  566. * @return string
  567. */
  568. protected function compilePush($expression)
  569. {
  570. return "<?php \$__env->startSection{$expression}; ?>";
  571. }
  572. /**
  573. * Compile the endpush statements into valid PHP.
  574. *
  575. * @param string $expression
  576. * @return string
  577. */
  578. protected function compileEndpush($expression)
  579. {
  580. return "<?php \$__env->appendSection(); ?>";
  581. }
  582. /**
  583. * Register a custom Blade compiler.
  584. *
  585. * @param callable $compiler
  586. * @return void
  587. */
  588. public function extend(callable $compiler)
  589. {
  590. $this->extensions[] = $compiler;
  591. }
  592. /**
  593. * Get the regular expression for a generic Blade function.
  594. *
  595. * @param string $function
  596. * @return string
  597. */
  598. public function createMatcher($function)
  599. {
  600. return '/(?<!\w)(\s*)@' . $function . '(\s*\(.*\))/';
  601. }
  602. /**
  603. * Get the regular expression for a generic Blade function.
  604. *
  605. * @param string $function
  606. * @return string
  607. */
  608. public function createOpenMatcher($function)
  609. {
  610. return '/(?<!\w)(\s*)@' . $function . '(\s*\(.*)\)/';
  611. }
  612. /**
  613. * Create a plain Blade matcher.
  614. *
  615. * @param string $function
  616. * @return string
  617. */
  618. public function createPlainMatcher($function)
  619. {
  620. return '/(?<!\w)(\s*)@' . $function . '(\s*)/';
  621. }
  622. /**
  623. * Sets the raw tags used for the compiler.
  624. *
  625. * @param string $openTag
  626. * @param string $closeTag
  627. * @return void
  628. */
  629. public function setRawTags($openTag, $closeTag)
  630. {
  631. $this->rawTags = array(preg_quote($openTag), preg_quote($closeTag));
  632. }
  633. /**
  634. * Sets the content tags used for the compiler.
  635. *
  636. * @param string $openTag
  637. * @param string $closeTag
  638. * @param bool $escaped
  639. * @return void
  640. */
  641. public function setContentTags($openTag, $closeTag, $escaped = false)
  642. {
  643. $property = ($escaped === true) ? 'escapedTags' : 'contentTags';
  644. $this->{$property} = array(preg_quote($openTag), preg_quote($closeTag));
  645. }
  646. /**
  647. * Sets the escaped content tags used for the compiler.
  648. *
  649. * @param string $openTag
  650. * @param string $closeTag
  651. * @return void
  652. */
  653. public function setEscapedContentTags($openTag, $closeTag)
  654. {
  655. $this->setContentTags($openTag, $closeTag, true);
  656. }
  657. /**
  658. * Gets the content tags used for the compiler.
  659. *
  660. * @return string
  661. */
  662. public function getContentTags()
  663. {
  664. return $this->getTags();
  665. }
  666. /**
  667. * Gets the escaped content tags used for the compiler.
  668. *
  669. * @return string
  670. */
  671. public function getEscapedContentTags()
  672. {
  673. return $this->getTags(true);
  674. }
  675. /**
  676. * Gets the tags used for the compiler.
  677. *
  678. * @param bool $escaped
  679. * @return array
  680. */
  681. protected function getTags($escaped = false)
  682. {
  683. $tags = $escaped ? $this->escapedTags : $this->contentTags;
  684. return array_map('stripcslashes', $tags);
  685. }
  686. /**
  687. * Set the echo format to be used by the compiler.
  688. *
  689. * @param string $format
  690. * @return void
  691. */
  692. public function setEchoFormat($format)
  693. {
  694. $this->echoFormat = $format;
  695. }
  696. }