AlternativeSource.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\View\Asset\PreProcessor;
  7. use Magento\Framework\ObjectManagerInterface;
  8. use Magento\Framework\View\Asset\File\FallbackContext;
  9. use Magento\Framework\View\Asset\LockerProcessInterface;
  10. use Magento\Framework\View\Asset\ContentProcessorInterface;
  11. use Magento\Framework\View\Asset\PreProcessor\AlternativeSource\AssetBuilder;
  12. /**
  13. * Class AlternativeSource
  14. *
  15. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  16. */
  17. class AlternativeSource implements AlternativeSourceInterface
  18. {
  19. /**
  20. * The key name of the processor class
  21. */
  22. const PROCESSOR_CLASS = 'class';
  23. /**
  24. * @var Helper\SortInterface
  25. */
  26. private $sorter;
  27. /**
  28. * @var array
  29. */
  30. private $alternatives;
  31. /**
  32. * @var ObjectManagerInterface
  33. */
  34. private $objectManager;
  35. /**
  36. * @var array
  37. */
  38. private $alternativesSorted;
  39. /**
  40. * @var LockerProcessInterface
  41. */
  42. private $lockerProcess;
  43. /**
  44. * @var string
  45. */
  46. private $lockName;
  47. /**
  48. * @var AssetBuilder
  49. */
  50. private $assetBuilder;
  51. /**
  52. * @var FilenameResolverInterface
  53. */
  54. private $filenameResolver;
  55. /**
  56. * Constructor
  57. *
  58. * @param FilenameResolverInterface $filenameResolver
  59. * @param ObjectManagerInterface $objectManager
  60. * @param LockerProcessInterface $lockerProcess
  61. * @param Helper\SortInterface $sorter
  62. * @param AssetBuilder $assetBuilder
  63. * @param string $lockName
  64. * @param array $alternatives
  65. */
  66. public function __construct(
  67. FilenameResolverInterface $filenameResolver,
  68. ObjectManagerInterface $objectManager,
  69. LockerProcessInterface $lockerProcess,
  70. Helper\SortInterface $sorter,
  71. AssetBuilder $assetBuilder,
  72. $lockName,
  73. array $alternatives = []
  74. ) {
  75. $this->objectManager = $objectManager;
  76. $this->lockerProcess = $lockerProcess;
  77. $this->sorter = $sorter;
  78. $this->alternatives = $alternatives;
  79. $this->lockName = $lockName;
  80. $this->assetBuilder = $assetBuilder;
  81. $this->filenameResolver = $filenameResolver;
  82. }
  83. /**
  84. * @inheritdoc
  85. * @throws \UnexpectedValueException
  86. */
  87. public function process(Chain $chain)
  88. {
  89. $path = $chain->getAsset()->getFilePath();
  90. $content = $chain->getContent();
  91. if (trim($content) !== '') {
  92. return;
  93. }
  94. try {
  95. $this->lockerProcess->lockProcess($this->lockName);
  96. $module = $chain->getAsset()->getModule();
  97. /** @var FallbackContext $context */
  98. $context = $chain->getAsset()->getContext();
  99. $chain->setContent($this->processContent($path, $content, $module, $context));
  100. } finally {
  101. $this->lockerProcess->unlockProcess();
  102. }
  103. }
  104. /**
  105. * Preparation of content for the destination file
  106. *
  107. * @param string $path
  108. * @param string $content
  109. * @param string $module
  110. * @param FallbackContext $context
  111. * @return string
  112. * @throws \UnexpectedValueException
  113. */
  114. private function processContent($path, $content, $module, FallbackContext $context)
  115. {
  116. if ($this->alternativesSorted === null) {
  117. $this->alternativesSorted = $this->sorter->sort($this->alternatives);
  118. }
  119. $path = $this->filenameResolver->resolve($path);
  120. foreach ($this->alternativesSorted as $name => $alternative) {
  121. $asset = $this->assetBuilder->setArea($context->getAreaCode())
  122. ->setTheme($context->getThemePath())
  123. ->setLocale($context->getLocale())
  124. ->setModule($module)
  125. ->setPath(preg_replace(
  126. '#\.' . preg_quote(pathinfo($path, PATHINFO_EXTENSION)) . '$#',
  127. '.' . $name,
  128. $path
  129. ))->build();
  130. $processor = $this->objectManager->get($alternative[self::PROCESSOR_CLASS]);
  131. if (!$processor instanceof ContentProcessorInterface) {
  132. throw new \UnexpectedValueException(
  133. '"' . $alternative[self::PROCESSOR_CLASS] . '" has to implement the ContentProcessorInterface.'
  134. );
  135. }
  136. $content = $processor->processContent($asset);
  137. if (trim($content) !== '') {
  138. return $content;
  139. }
  140. }
  141. return $content;
  142. }
  143. /**
  144. * @inheritdoc
  145. */
  146. public function getAlternativesExtensionsNames()
  147. {
  148. return array_keys($this->alternatives);
  149. }
  150. }