3 namespace Drupal\advagg\Asset;
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Core\Asset\AssetCollectionRendererInterface;
7 use Drupal\Core\Asset\JsCollectionRenderer as CoreJsCollectionRenderer;
8 use Drupal\Core\Config\ConfigFactoryInterface;
9 use Drupal\Core\State\StateInterface;
14 class JsCollectionRenderer extends CoreJsCollectionRenderer implements AssetCollectionRendererInterface {
17 * A config object for the advagg configuration.
19 * @var \Drupal\Core\Config\Config
26 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
27 * A config factory for retrieving required config objects.
29 public function __construct(StateInterface $state, ConfigFactoryInterface $config_factory) {
30 $this->state = $state;
31 $this->config = $config_factory->get('advagg.settings');
37 public function render(array $js_assets) {
38 // Check assets array to ensure that it isn't malformed.
39 if (isset($js_assets['-1']) && empty($js_assets[-1])) {
40 unset($js_assets['-1']);
43 $elements = ['prefetch' => []];
44 $prefetch = $this->config->get('dns_prefetch');
46 // A dummy query-string is added to filenames, to gain control over
47 // browser-caching. The string changes on every update or full cache
48 // flush, forcing browsers to load a new copy of the files, as the
49 // URL changed. Files that should not be cached get REQUEST_TIME as
50 // query-string instead, to enforce reload on every page request.
51 $default_query_string = $this->state->get('system.css_js_query_string') ?: '0';
53 // Defaults for each element.
55 '#type' => 'html_tag',
59 $prefetch_element_defaults = [
60 '#type' => 'html_tag',
63 'rel' => 'dns-prefetch',
67 // Loop through all JS assets.
68 foreach ($js_assets as $js_asset) {
69 // Element properties that do not depend on JS asset type.
70 $element = $element_defaults;
71 $element['#browsers'] = $js_asset['browsers'];
73 // Element properties that depend on item type.
74 switch ($js_asset['type']) {
76 $element['#attributes'] = [
77 // This type attribute prevents this from being parsed as an
79 'type' => 'application/json',
80 'data-drupal-selector' => 'drupal-settings-json',
82 $element['#value'] = Json::encode($js_asset['data']);
86 $query_string = $js_asset['version'] == -1 ? $default_query_string : 'v=' . $js_asset['version'];
87 $query_string_separator = (strpos($js_asset['data'], '?') !== FALSE) ? '&' : '?';
88 $element['#attributes']['src'] = file_url_transform_relative(file_create_url($js_asset['data']));
89 // Only add the cache-busting query string if this isn't an aggregate
91 if (!isset($js_asset['preprocessed'])) {
92 $element['#attributes']['src'] .= $query_string_separator . ($js_asset['cache'] ? $query_string : REQUEST_TIME);
94 $element['#inline'] = !empty($js_asset['inline']) ? TRUE : FALSE;
98 $element['#attributes']['src'] = $js_asset['data'];
100 $pre_element = $prefetch_element_defaults;
101 $pre_element['#attributes']['href'] = '//' . parse_url($js_asset['data'], PHP_URL_HOST);
102 $elements['prefetch'][] = $pre_element;
107 throw new \Exception('Invalid JS asset type.');
110 // Attributes may only be set if this script is output independently.
111 if (!empty($element['#attributes']['src']) && !empty($js_asset['attributes'])) {
112 $element['#attributes'] += $js_asset['attributes'];
115 $elements[] = $element;
117 if (empty($elements['prefetch'])) {
118 unset($elements['prefetch']);