1<?php
2
3namespace Drupal\Core\Asset;
4
5/**
6 * Resolves the dependencies of asset (CSS/JavaScript) libraries.
7 */
8class LibraryDependencyResolver implements LibraryDependencyResolverInterface {
9
10  /**
11   * The library discovery service.
12   *
13   * @var \Drupal\Core\Asset\LibraryDiscoveryInterface
14   */
15  protected $libraryDiscovery;
16
17  /**
18   * Constructs a new LibraryDependencyResolver instance.
19   *
20   * @param \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery
21   *   The library discovery service.
22   */
23  public function __construct(LibraryDiscoveryInterface $library_discovery) {
24    $this->libraryDiscovery = $library_discovery;
25  }
26
27  /**
28   * {@inheritdoc}
29   */
30  public function getLibrariesWithDependencies(array $libraries) {
31    return $this->doGetDependencies($libraries);
32  }
33
34  /**
35   * Gets the given libraries with its dependencies.
36   *
37   * Helper method for ::getLibrariesWithDependencies().
38   *
39   * @param string[] $libraries_with_unresolved_dependencies
40   *   A list of libraries, with unresolved dependencies, in the order they
41   *   should be loaded.
42   * @param string[] $final_libraries
43   *   The final list of libraries (the return value) that is being built
44   *   recursively.
45   *
46   * @return string[]
47   *   A list of libraries, in the order they should be loaded, including their
48   *   dependencies.
49   */
50  protected function doGetDependencies(array $libraries_with_unresolved_dependencies, array $final_libraries = []) {
51    foreach ($libraries_with_unresolved_dependencies as $library) {
52      if (!in_array($library, $final_libraries)) {
53        list($extension, $name) = explode('/', $library, 2);
54        $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
55        if (!empty($definition['dependencies'])) {
56          $final_libraries = $this->doGetDependencies($definition['dependencies'], $final_libraries);
57        }
58        $final_libraries[] = $library;
59      }
60    }
61    return $final_libraries;
62  }
63
64  /**
65   * {@inheritdoc}
66   */
67  public function getMinimalRepresentativeSubset(array $libraries) {
68    assert(count($libraries) === count(array_unique($libraries)), '$libraries can\'t contain duplicate items.');
69
70    $minimal = [];
71
72    // Determine each library's dependencies.
73    $with_deps = [];
74    foreach ($libraries as $library) {
75      $with_deps[$library] = $this->getLibrariesWithDependencies([$library]);
76    }
77
78    foreach ($libraries as $library) {
79      $exists = FALSE;
80      foreach ($with_deps as $other_library => $dependencies) {
81        if ($library == $other_library) {
82          continue;
83        }
84        if (in_array($library, $dependencies)) {
85          $exists = TRUE;
86          break;
87        }
88      }
89      if (!$exists) {
90        $minimal[] = $library;
91      }
92    }
93
94    return $minimal;
95  }
96
97}
98