Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/Render/BubbleableMetadata.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\Render; | |
4 | |
5 use Drupal\Component\Utility\NestedArray; | |
6 use Drupal\Core\Cache\CacheableMetadata; | |
7 | |
8 /** | |
9 * Value object used for bubbleable rendering metadata. | |
10 * | |
11 * @see \Drupal\Core\Render\RendererInterface::render() | |
12 */ | |
13 class BubbleableMetadata extends CacheableMetadata implements AttachmentsInterface { | |
14 | |
15 use AttachmentsTrait; | |
16 | |
17 /** | |
18 * Merges the values of another bubbleable metadata object with this one. | |
19 * | |
20 * @param \Drupal\Core\Cache\CacheableMetadata $other | |
21 * The other bubbleable metadata object. | |
22 * | |
23 * @return static | |
24 * A new bubbleable metadata object, with the merged data. | |
25 */ | |
26 public function merge(CacheableMetadata $other) { | |
27 $result = parent::merge($other); | |
28 | |
29 // This is called many times per request, so avoid merging unless absolutely | |
30 // necessary. | |
31 if ($other instanceof BubbleableMetadata) { | |
32 if (empty($this->attachments)) { | |
33 $result->attachments = $other->attachments; | |
34 } | |
35 elseif (empty($other->attachments)) { | |
36 $result->attachments = $this->attachments; | |
37 } | |
38 else { | |
39 $result->attachments = static::mergeAttachments($this->attachments, $other->attachments); | |
40 } | |
41 } | |
42 | |
43 return $result; | |
44 } | |
45 | |
46 /** | |
47 * Applies the values of this bubbleable metadata object to a render array. | |
48 * | |
49 * @param array &$build | |
50 * A render array. | |
51 */ | |
52 public function applyTo(array &$build) { | |
53 parent::applyTo($build); | |
54 $build['#attached'] = $this->attachments; | |
55 } | |
56 | |
57 /** | |
58 * Creates a bubbleable metadata object with values taken from a render array. | |
59 * | |
60 * @param array $build | |
61 * A render array. | |
62 * | |
63 * @return static | |
64 */ | |
65 public static function createFromRenderArray(array $build) { | |
66 $meta = parent::createFromRenderArray($build); | |
67 $meta->attachments = (isset($build['#attached'])) ? $build['#attached'] : []; | |
68 return $meta; | |
69 } | |
70 | |
71 /** | |
72 * Creates a bubbleable metadata object from a depended object. | |
73 * | |
74 * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $object | |
75 * The object whose cacheability metadata to retrieve. If it implements | |
76 * CacheableDependencyInterface, its cacheability metadata will be used, | |
77 * otherwise, the passed in object must be assumed to be uncacheable, so | |
78 * max-age 0 is set. | |
79 * | |
80 * @return static | |
81 */ | |
82 public static function createFromObject($object) { | |
83 $meta = parent::createFromObject($object); | |
84 | |
85 if ($object instanceof AttachmentsInterface) { | |
86 $meta->attachments = $object->getAttachments(); | |
87 } | |
88 | |
89 return $meta; | |
90 } | |
91 | |
92 /** | |
93 * {@inheritdoc} | |
94 */ | |
95 public function addCacheableDependency($other_object) { | |
96 parent::addCacheableDependency($other_object); | |
97 | |
98 if ($other_object instanceof AttachmentsInterface) { | |
99 $this->addAttachments($other_object->getAttachments()); | |
100 } | |
101 | |
102 return $this; | |
103 } | |
104 | |
105 /** | |
106 * Merges two attachments arrays (which live under the '#attached' key). | |
107 * | |
108 * The values under the 'drupalSettings' key are merged in a special way, to | |
109 * match the behavior of: | |
110 * | |
111 * @code | |
112 * jQuery.extend(true, {}, $settings_items[0], $settings_items[1], ...) | |
113 * @endcode | |
114 * | |
115 * This means integer indices are preserved just like string indices are, | |
116 * rather than re-indexed as is common in PHP array merging. | |
117 * | |
118 * Example: | |
119 * @code | |
120 * function module1_page_attachments(&$page) { | |
121 * $page['a']['#attached']['drupalSettings']['foo'] = ['a', 'b', 'c']; | |
122 * } | |
123 * function module2_page_attachments(&$page) { | |
124 * $page['#attached']['drupalSettings']['foo'] = ['d']; | |
125 * } | |
126 * // When the page is rendered after the above code, and the browser runs the | |
127 * // resulting <SCRIPT> tags, the value of drupalSettings.foo is | |
128 * // ['d', 'b', 'c'], not ['a', 'b', 'c', 'd']. | |
129 * @endcode | |
130 * | |
131 * By following jQuery.extend() merge logic rather than common PHP array merge | |
132 * logic, the following are ensured: | |
133 * - Attaching JavaScript settings is idempotent: attaching the same settings | |
134 * twice does not change the output sent to the browser. | |
135 * - If pieces of the page are rendered in separate PHP requests and the | |
136 * returned settings are merged by JavaScript, the resulting settings are | |
137 * the same as if rendered in one PHP request and merged by PHP. | |
138 * | |
139 * @param array $a | |
140 * An attachments array. | |
141 * @param array $b | |
142 * Another attachments array. | |
143 * | |
144 * @return array | |
145 * The merged attachments array. | |
146 */ | |
147 public static function mergeAttachments(array $a, array $b) { | |
148 // If both #attached arrays contain drupalSettings, then merge them | |
149 // correctly; adding the same settings multiple times needs to behave | |
150 // idempotently. | |
151 if (!empty($a['drupalSettings']) && !empty($b['drupalSettings'])) { | |
152 $drupalSettings = NestedArray::mergeDeepArray([$a['drupalSettings'], $b['drupalSettings']], TRUE); | |
153 // No need for re-merging them. | |
154 unset($a['drupalSettings']); | |
155 unset($b['drupalSettings']); | |
156 } | |
157 // Optimize merging of placeholders: no need for deep merging. | |
158 if (!empty($a['placeholders']) && !empty($b['placeholders'])) { | |
159 $placeholders = $a['placeholders'] + $b['placeholders']; | |
160 // No need for re-merging them. | |
161 unset($a['placeholders']); | |
162 unset($b['placeholders']); | |
163 } | |
164 // Apply the normal merge. | |
165 $a = array_merge_recursive($a, $b); | |
166 if (isset($drupalSettings)) { | |
167 // Save the custom merge for the drupalSettings. | |
168 $a['drupalSettings'] = $drupalSettings; | |
169 } | |
170 if (isset($placeholders)) { | |
171 // Save the custom merge for the placeholders. | |
172 $a['placeholders'] = $placeholders; | |
173 } | |
174 return $a; | |
175 } | |
176 | |
177 } |