ThemeViewFinder.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. namespace Webkul\Theme;
  3. use Illuminate\Support\Arr;
  4. use Illuminate\Support\Str;
  5. use Illuminate\View\FileViewFinder;
  6. use Webkul\Theme\Facades\Themes;
  7. class ThemeViewFinder extends FileViewFinder
  8. {
  9. /**
  10. * The namespace for admin package views.
  11. *
  12. * @var string
  13. */
  14. public const ADMIN_PACKAGE_VIEWS_NAMESPACE = 'admin';
  15. /**
  16. * The namespace for shop package views.
  17. *
  18. * @var string
  19. */
  20. public const SHOP_PACKAGE_VIEWS_NAMESPACE = 'shop';
  21. /**
  22. * Find a namespaced view considering the active theme.
  23. *
  24. * @param string $name
  25. * @return string
  26. */
  27. protected function findNamespacedView($name)
  28. {
  29. [$namespace, $view] = $this->parseNamespaceSegments($name);
  30. $isAdmin = Str::contains(request()->url(), config('app.admin_url').'/');
  31. $this->setActiveTheme($isAdmin);
  32. $paths = $this->addThemeNamespacePaths($namespace);
  33. try {
  34. return $this->findInPaths($view, $paths);
  35. } catch (\Exception $e) {
  36. $view = $this->getThemedViewName($namespace, $view, $isAdmin);
  37. return $this->findInPaths($view, $paths);
  38. }
  39. }
  40. /**
  41. * Sets the active theme depending on request context.
  42. */
  43. protected function setActiveTheme(bool $isAdmin)
  44. {
  45. if ($isAdmin) {
  46. themes()->set(config('themes.admin-default'));
  47. }
  48. }
  49. /**
  50. * Get the theme-specific view name if not found on first try.
  51. *
  52. * @param string $namespace
  53. * @param string $view
  54. * @param bool $isAdmin
  55. * @return string
  56. */
  57. protected function getThemedViewName($namespace, $view, $isAdmin)
  58. {
  59. $themeCode = themes()->current()?->code;
  60. if (
  61. ! $isAdmin
  62. && $namespace !== self::SHOP_PACKAGE_VIEWS_NAMESPACE
  63. && Str::contains($view, 'shop.')
  64. ) {
  65. return Str::replaceFirst('shop.', "shop.$themeCode.", $view);
  66. }
  67. if (
  68. $isAdmin
  69. && $namespace !== self::ADMIN_PACKAGE_VIEWS_NAMESPACE
  70. && Str::contains($view, 'admin.')
  71. ) {
  72. return Str::replaceFirst('admin.', "admin.$themeCode.", $view);
  73. }
  74. return $view;
  75. }
  76. /**
  77. * Add possible paths for this namespace, including theme overlays.
  78. *
  79. * @param string $namespace
  80. * @return array
  81. */
  82. public function addThemeNamespacePaths($namespace)
  83. {
  84. if (! isset($this->hints[$namespace])) {
  85. return [];
  86. }
  87. $paths = [];
  88. $theme = themes()->current();
  89. if (
  90. $theme
  91. && $theme->code !== 'default'
  92. && in_array($namespace, [
  93. self::SHOP_PACKAGE_VIEWS_NAMESPACE,
  94. self::ADMIN_PACKAGE_VIEWS_NAMESPACE,
  95. ])
  96. ) {
  97. $themeNamespace = $theme->viewsNamespace ?? $theme->code;
  98. if (isset($this->hints[$themeNamespace])) {
  99. $paths = [...$this->hints[$themeNamespace]];
  100. }
  101. }
  102. $paths = [...$paths, ...$this->hints[$namespace]];
  103. $searchPaths = array_diff($this->paths, Themes::getLaravelViewPaths());
  104. foreach (array_reverse($searchPaths) as $path) {
  105. $paths = Arr::prepend($paths, base_path($path));
  106. }
  107. return $paths;
  108. }
  109. /**
  110. * Add paths for custom error/mails pages in the theme.
  111. *
  112. * @param string $namespace
  113. * @param string|array $hints
  114. * @return void
  115. */
  116. public function replaceNamespace($namespace, $hints)
  117. {
  118. $this->hints[$namespace] = (array) $hints;
  119. if (in_array($namespace, ['errors', 'mails'])) {
  120. $searchPaths = array_diff($this->paths, Themes::getLaravelViewPaths());
  121. $addPaths = array_map(fn ($path) => base_path("$path/$namespace"), $searchPaths);
  122. $this->prependNamespace($namespace, $addPaths);
  123. }
  124. }
  125. /**
  126. * Set base paths and clear cache.
  127. */
  128. public function setPaths($paths)
  129. {
  130. $this->paths = $paths;
  131. $this->flush();
  132. }
  133. }