PageRenderTime 41ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/View/Environment.php

https://gitlab.com/oytunistrator/92five
PHP | 715 lines | 296 code | 87 blank | 332 comment | 10 complexity | b1c16eb220ea53f8fbf2cc24b1c6fc0c MD5 | raw file
  1. <?php namespace Illuminate\View;
  2. use Closure;
  3. use Illuminate\Events\Dispatcher;
  4. use Illuminate\Container\Container;
  5. use Illuminate\View\Engines\EngineResolver;
  6. use Illuminate\Support\Contracts\ArrayableInterface as Arrayable;
  7. class Environment {
  8. /**
  9. * The engine implementation.
  10. *
  11. * @var \Illuminate\View\Engines\EngineResolver
  12. */
  13. protected $engines;
  14. /**
  15. * The view finder implementation.
  16. *
  17. * @var \Illuminate\View\ViewFinderInterface
  18. */
  19. protected $finder;
  20. /**
  21. * The event dispatcher instance.
  22. *
  23. * @var \Illuminate\Events\Dispatcher
  24. */
  25. protected $events;
  26. /**
  27. * The IoC container instance.
  28. *
  29. * @var \Illuminate\Container
  30. */
  31. protected $container;
  32. /**
  33. * Data that should be available to all templates.
  34. *
  35. * @var array
  36. */
  37. protected $shared = array();
  38. /**
  39. * All of the registered view names.
  40. *
  41. * @var array
  42. */
  43. protected $names = array();
  44. /**
  45. * The extension to engine bindings.
  46. *
  47. * @var array
  48. */
  49. protected $extensions = array('blade.php' => 'blade', 'php' => 'php');
  50. /**
  51. * The view composer events.
  52. *
  53. * @var array
  54. */
  55. protected $composers = array();
  56. /**
  57. * All of the finished, captured sections.
  58. *
  59. * @var array
  60. */
  61. protected $sections = array();
  62. /**
  63. * The stack of in-progress sections.
  64. *
  65. * @var array
  66. */
  67. protected $sectionStack = array();
  68. /**
  69. * The number of active rendering operations.
  70. *
  71. * @var int
  72. */
  73. protected $renderCount = 0;
  74. /**
  75. * Create a new view environment instance.
  76. *
  77. * @param \Illuminate\View\Engines\EngineResolver $engines
  78. * @param \Illuminate\View\ViewFinderInterface $finder
  79. * @param \Illuminate\Events\Dispatcher $events
  80. * @return void
  81. */
  82. public function __construct(EngineResolver $engines, ViewFinderInterface $finder, Dispatcher $events)
  83. {
  84. $this->finder = $finder;
  85. $this->events = $events;
  86. $this->engines = $engines;
  87. $this->share('__env', $this);
  88. }
  89. /**
  90. * Get a evaluated view contents for the given view.
  91. *
  92. * @param string $view
  93. * @param array $data
  94. * @param array $mergeData
  95. * @return \Illuminate\View\View
  96. */
  97. public function make($view, $data = array(), $mergeData = array())
  98. {
  99. $path = $this->finder->find($view);
  100. $data = array_merge($mergeData, $this->parseData($data));
  101. $this->callCreator($view = new View($this, $this->getEngineFromPath($path), $view, $path, $data));
  102. return $view;
  103. }
  104. /**
  105. * Parse the given data into a raw array.
  106. *
  107. * @param mixed $data
  108. * @return array
  109. */
  110. protected function parseData($data)
  111. {
  112. return $data instanceof Arrayable ? $data->toArray() : $data;
  113. }
  114. /**
  115. * Get a evaluated view contents for a named view.
  116. *
  117. * @param string $view
  118. * @param mixed $data
  119. * @return \Illuminate\View\View
  120. */
  121. public function of($view, $data = array())
  122. {
  123. return $this->make($this->names[$view], $data);
  124. }
  125. /**
  126. * Register a named view.
  127. *
  128. * @param string $view
  129. * @param string $name
  130. * @return void
  131. */
  132. public function name($view, $name)
  133. {
  134. $this->names[$name] = $view;
  135. }
  136. /**
  137. * Determine if a given view exists.
  138. *
  139. * @param string $view
  140. * @return bool
  141. */
  142. public function exists($view)
  143. {
  144. try
  145. {
  146. $this->finder->find($view);
  147. }
  148. catch (\InvalidArgumentException $e)
  149. {
  150. return false;
  151. }
  152. return true;
  153. }
  154. /**
  155. * Get the rendered contents of a partial from a loop.
  156. *
  157. * @param string $view
  158. * @param array $data
  159. * @param string $iterator
  160. * @param string $empty
  161. * @return string
  162. */
  163. public function renderEach($view, $data, $iterator, $empty = 'raw|')
  164. {
  165. $result = '';
  166. // If is actually data in the array, we will loop through the data and append
  167. // an instance of the partial view to the final result HTML passing in the
  168. // iterated value of this data array, allowing the views to access them.
  169. if (count($data) > 0)
  170. {
  171. foreach ($data as $key => $value)
  172. {
  173. $data = array('key' => $key, $iterator => $value);
  174. $result .= $this->make($view, $data)->render();
  175. }
  176. }
  177. // If there is no data in the array, we will render the contents of the empty
  178. // view. Alternatively, the "empty view" could be a raw string that begins
  179. // with "raw|" for convenience and to let this know that it is a string.
  180. else
  181. {
  182. if (starts_with($empty, 'raw|'))
  183. {
  184. $result = substr($empty, 4);
  185. }
  186. else
  187. {
  188. $result = $this->make($empty)->render();
  189. }
  190. }
  191. return $result;
  192. }
  193. /**
  194. * Get the appropriate view engine for the given path.
  195. *
  196. * @param string $path
  197. * @return \Illuminate\View\Engines\EngineInterface
  198. */
  199. protected function getEngineFromPath($path)
  200. {
  201. $engine = $this->extensions[$this->getExtension($path)];
  202. return $this->engines->resolve($engine);
  203. }
  204. /**
  205. * Get the extension used by the view file.
  206. *
  207. * @param string $path
  208. * @return string
  209. */
  210. protected function getExtension($path)
  211. {
  212. $extensions = array_keys($this->extensions);
  213. return array_first($extensions, function($key, $value) use ($path)
  214. {
  215. return ends_with($path, $value);
  216. });
  217. }
  218. /**
  219. * Add a piece of shared data to the environment.
  220. *
  221. * @param string $key
  222. * @param mixed $value
  223. * @return void
  224. */
  225. public function share($key, $value = null)
  226. {
  227. if ( ! is_array($key)) return $this->shared[$key] = $value;
  228. foreach ($key as $innerKey => $innerValue)
  229. {
  230. $this->share($innerKey, $innerValue);
  231. }
  232. }
  233. /**
  234. * Register a view creator event.
  235. *
  236. * @param array|string $views
  237. * @param \Closure|string $callback
  238. * @return array
  239. */
  240. public function creator($views, $callback)
  241. {
  242. $creators = array();
  243. foreach ((array) $views as $view)
  244. {
  245. $creators[] = $this->addViewEvent($view, $callback, 'creating: ');
  246. }
  247. return $creators;
  248. }
  249. /**
  250. * Register a view composer event.
  251. *
  252. * @param array|string $views
  253. * @param \Closure|string $callback
  254. * @return array
  255. */
  256. public function composer($views, $callback)
  257. {
  258. $composers = array();
  259. foreach ((array) $views as $view)
  260. {
  261. $composers[] = $this->addViewEvent($view, $callback);
  262. }
  263. return $composers;
  264. }
  265. /**
  266. * Add an event for a given view.
  267. *
  268. * @param string $view
  269. * @param Closure|string $callback
  270. * @param string $prefix
  271. * @return Closure
  272. */
  273. protected function addViewEvent($view, $callback, $prefix = 'composing: ')
  274. {
  275. if ($callback instanceof Closure)
  276. {
  277. $this->events->listen($prefix.$view, $callback);
  278. return $callback;
  279. }
  280. elseif (is_string($callback))
  281. {
  282. return $this->addClassEvent($view, $callback, $prefix);
  283. }
  284. }
  285. /**
  286. * Register a class based view composer.
  287. *
  288. * @param string $view
  289. * @param string $class
  290. * @param string $prefix
  291. * @return \Closure
  292. */
  293. protected function addClassEvent($view, $class, $prefix)
  294. {
  295. $name = $prefix.$view;
  296. // When registering a class based view "composer", we will simply resolve the
  297. // classes from the application IoC container then call the compose method
  298. // on the instance. This allows for convenient, testable view composers.
  299. $callback = $this->buildClassEventCallback($class, $prefix);
  300. $this->events->listen($name, $callback);
  301. return $callback;
  302. }
  303. /**
  304. * Build a class based container callback Closure.
  305. *
  306. * @param string $class
  307. * @param string $prefix
  308. * @return \Closure
  309. */
  310. protected function buildClassEventCallback($class, $prefix)
  311. {
  312. $container = $this->container;
  313. list($class, $method) = $this->parseClassEvent($class, $prefix);
  314. // Once we have the class and method name, we can build the Closure to resolve
  315. // the instance out of the IoC container and call the method on it with the
  316. // given arguments that are passed to the Closure as the composer's data.
  317. return function() use ($class, $method, $container)
  318. {
  319. $callable = array($container->make($class), $method);
  320. return call_user_func_array($callable, func_get_args());
  321. };
  322. }
  323. /**
  324. * Parse a class based composer name.
  325. *
  326. * @param string $class
  327. * @param string $prefix
  328. * @return array
  329. */
  330. protected function parseClassEvent($class, $prefix)
  331. {
  332. if (str_contains($class, '@'))
  333. {
  334. return explode('@', $class);
  335. }
  336. else
  337. {
  338. $method = str_contains($prefix, 'composing') ? 'compose' : 'create';
  339. return array($class, $method);
  340. }
  341. }
  342. /**
  343. * Call the composer for a given view.
  344. *
  345. * @param \Illuminate\View\View $view
  346. * @return void
  347. */
  348. public function callComposer(View $view)
  349. {
  350. $this->events->fire('composing: '.$view->getName(), array($view));
  351. }
  352. /**
  353. * Call the creator for a given view.
  354. *
  355. * @param \Illuminate\View\View $view
  356. * @return void
  357. */
  358. public function callCreator(View $view)
  359. {
  360. $this->events->fire('creating: '.$view->getName(), array($view));
  361. }
  362. /**
  363. * Start injecting content into a section.
  364. *
  365. * @param string $section
  366. * @param string $content
  367. * @return void
  368. */
  369. public function startSection($section, $content = '')
  370. {
  371. if ($content === '')
  372. {
  373. ob_start() and $this->sectionStack[] = $section;
  374. }
  375. else
  376. {
  377. $this->extendSection($section, $content);
  378. }
  379. }
  380. /**
  381. * Inject inline content into a section.
  382. *
  383. * @param string $section
  384. * @param string $content
  385. * @return void
  386. */
  387. public function inject($section, $content)
  388. {
  389. return $this->startSection($section, $content);
  390. }
  391. /**
  392. * Stop injecting content into a section and return its contents.
  393. *
  394. * @return string
  395. */
  396. public function yieldSection()
  397. {
  398. return $this->yieldContent($this->stopSection());
  399. }
  400. /**
  401. * Stop injecting content into a section.
  402. *
  403. * @param bool $overwrite
  404. * @return string
  405. */
  406. public function stopSection($overwrite = false)
  407. {
  408. $last = array_pop($this->sectionStack);
  409. if ($overwrite)
  410. {
  411. $this->sections[$last] = ob_get_clean();
  412. }
  413. else
  414. {
  415. $this->extendSection($last, ob_get_clean());
  416. }
  417. return $last;
  418. }
  419. /**
  420. * Append content to a given section.
  421. *
  422. * @param string $section
  423. * @param string $content
  424. * @return void
  425. */
  426. protected function extendSection($section, $content)
  427. {
  428. if (isset($this->sections[$section]))
  429. {
  430. $content = str_replace('@parent', $content, $this->sections[$section]);
  431. $this->sections[$section] = $content;
  432. }
  433. else
  434. {
  435. $this->sections[$section] = $content;
  436. }
  437. }
  438. /**
  439. * Get the string contents of a section.
  440. *
  441. * @param string $section
  442. * @param string $default
  443. * @return string
  444. */
  445. public function yieldContent($section, $default = '')
  446. {
  447. return isset($this->sections[$section]) ? $this->sections[$section] : $default;
  448. }
  449. /**
  450. * Flush all of the section contents.
  451. *
  452. * @return void
  453. */
  454. public function flushSections()
  455. {
  456. $this->sections = array();
  457. $this->sectionStack = array();
  458. }
  459. /**
  460. * Increment the rendering counter.
  461. *
  462. * @return void
  463. */
  464. public function incrementRender()
  465. {
  466. $this->renderCount++;
  467. }
  468. /**
  469. * Decrement the rendering counter.
  470. *
  471. * @return void
  472. */
  473. public function decrementRender()
  474. {
  475. $this->renderCount--;
  476. }
  477. /**
  478. * Check if there are no active render operations.
  479. *
  480. * @return bool
  481. */
  482. public function doneRendering()
  483. {
  484. return $this->renderCount == 0;
  485. }
  486. /**
  487. * Add a location to the array of view locations.
  488. *
  489. * @param string $location
  490. * @return void
  491. */
  492. public function addLocation($location)
  493. {
  494. $this->finder->addLocation($location);
  495. }
  496. /**
  497. * Add a new namespace to the loader.
  498. *
  499. * @param string $namespace
  500. * @param string|array $hints
  501. * @return void
  502. */
  503. public function addNamespace($namespace, $hints)
  504. {
  505. $this->finder->addNamespace($namespace, $hints);
  506. }
  507. /**
  508. * Register a valid view extension and its engine.
  509. *
  510. * @param string $extension
  511. * @param string $engine
  512. * @param Closure $resolver
  513. * @return void
  514. */
  515. public function addExtension($extension, $engine, $resolver = null)
  516. {
  517. $this->finder->addExtension($extension);
  518. if (isset($resolver))
  519. {
  520. $this->engines->register($engine, $resolver);
  521. }
  522. unset($this->extensions[$engine]);
  523. $this->extensions = array_merge(array($extension => $engine), $this->extensions);
  524. }
  525. /**
  526. * Get the extension to engine bindings.
  527. *
  528. * @return array
  529. */
  530. public function getExtensions()
  531. {
  532. return $this->extensions;
  533. }
  534. /**
  535. * Get the engine resolver instance.
  536. *
  537. * @return \Illuminate\View\Engines\EngineResolver
  538. */
  539. public function getEngineResolver()
  540. {
  541. return $this->engines;
  542. }
  543. /**
  544. * Get the view finder instance.
  545. *
  546. * @return \Illuminate\View\ViewFinderInterface
  547. */
  548. public function getFinder()
  549. {
  550. return $this->finder;
  551. }
  552. /**
  553. * Get the event dispatcher instance.
  554. *
  555. * @return \Illuminate\Events\Dispatcher
  556. */
  557. public function getDispatcher()
  558. {
  559. return $this->events;
  560. }
  561. /**
  562. * Set the event dispatcher instance.
  563. *
  564. * @param \Illuminate\Events\Dispatcher
  565. * @return void
  566. */
  567. public function setDispatcher(Dispatcher $events)
  568. {
  569. $this->events = $events;
  570. }
  571. /**
  572. * Get the IoC container instance.
  573. *
  574. * @return \Illuminate\Container\Container
  575. */
  576. public function getContainer()
  577. {
  578. return $this->container;
  579. }
  580. /**
  581. * Set the IoC container instance.
  582. *
  583. * @param \Illuminate\Container\Container $container
  584. * @return void
  585. */
  586. public function setContainer(Container $container)
  587. {
  588. $this->container = $container;
  589. }
  590. /**
  591. * Get an item from the shared data.
  592. *
  593. * @param string $key
  594. * @param mixed $default
  595. * @return mixed
  596. */
  597. public function shared($key, $default = null)
  598. {
  599. return array_get($this->shared, $key, $default);
  600. }
  601. /**
  602. * Get all of the shared data for the environment.
  603. *
  604. * @return array
  605. */
  606. public function getShared()
  607. {
  608. return $this->shared;
  609. }
  610. /**
  611. * Get the entire array of sections.
  612. *
  613. * @return array
  614. */
  615. public function getSections()
  616. {
  617. return $this->sections;
  618. }
  619. /**
  620. * Get all of the registered named views in environment.
  621. *
  622. * @return array
  623. */
  624. public function getNames()
  625. {
  626. return $this->names;
  627. }
  628. }