3 namespace Drupal\Core\Render\Placeholder;
6 * Renders placeholders using a chain of placeholder strategies.
8 class ChainedPlaceholderStrategy implements PlaceholderStrategyInterface {
11 * An ordered list of placeholder strategy services.
13 * Ordered according to service priority.
15 * @var \Drupal\Core\Render\Placeholder\PlaceholderStrategyInterface[]
17 protected $placeholderStrategies = [];
20 * Adds a placeholder strategy to use.
22 * @param \Drupal\Core\Render\Placeholder\PlaceholderStrategyInterface $strategy
23 * The strategy to add to the placeholder strategies.
25 public function addPlaceholderStrategy(PlaceholderStrategyInterface $strategy) {
26 $this->placeholderStrategies[] = $strategy;
32 public function processPlaceholders(array $placeholders) {
33 if (empty($placeholders)) {
37 // Assert that there is at least one strategy.
38 assert('!empty($this->placeholderStrategies)', 'At least one placeholder strategy must be present; by default the fallback strategy \Drupal\Core\Render\Placeholder\SingleFlushStrategy is always present.');
40 $new_placeholders = [];
42 // Give each placeholder strategy a chance to replace all not-yet replaced
43 // placeholders. The order of placeholder strategies is well defined
44 // and this uses a variation of the "chain of responsibility" design pattern.
45 foreach ($this->placeholderStrategies as $strategy) {
46 $processed_placeholders = $strategy->processPlaceholders($placeholders);
47 assert('array_intersect_key($processed_placeholders, $placeholders) === $processed_placeholders', 'Processed placeholders must be a subset of all placeholders.');
48 $placeholders = array_diff_key($placeholders, $processed_placeholders);
49 $new_placeholders += $processed_placeholders;
51 if (empty($placeholders)) {
56 return $new_placeholders;