Chris@18
|
1 <?php
|
Chris@18
|
2
|
Chris@18
|
3 /**
|
Chris@18
|
4 * @file
|
Chris@18
|
5 * Contains \DrupalFinder\DrupalFinder.
|
Chris@18
|
6 */
|
Chris@18
|
7
|
Chris@18
|
8 namespace DrupalFinder;
|
Chris@18
|
9
|
Chris@18
|
10 class DrupalFinder
|
Chris@18
|
11 {
|
Chris@18
|
12 /**
|
Chris@18
|
13 * Drupal web public directory.
|
Chris@18
|
14 *
|
Chris@18
|
15 * @var string
|
Chris@18
|
16 */
|
Chris@18
|
17 private $drupalRoot;
|
Chris@18
|
18
|
Chris@18
|
19 /**
|
Chris@18
|
20 * Drupal package composer directory.
|
Chris@18
|
21 *
|
Chris@18
|
22 * @var bool
|
Chris@18
|
23 */
|
Chris@18
|
24 private $composerRoot;
|
Chris@18
|
25
|
Chris@18
|
26 /**
|
Chris@18
|
27 * Composer vendor directory.
|
Chris@18
|
28 *
|
Chris@18
|
29 * @var string
|
Chris@18
|
30 *
|
Chris@18
|
31 * @see https://getcomposer.org/doc/06-config.md#vendor-dir
|
Chris@18
|
32 */
|
Chris@18
|
33 private $vendorDir;
|
Chris@18
|
34
|
Chris@18
|
35 public function locateRoot($start_path)
|
Chris@18
|
36 {
|
Chris@18
|
37 $this->drupalRoot = false;
|
Chris@18
|
38 $this->composerRoot = false;
|
Chris@18
|
39 $this->vendorDir = false;
|
Chris@18
|
40
|
Chris@18
|
41 foreach (array(true, false) as $follow_symlinks) {
|
Chris@18
|
42 $path = $start_path;
|
Chris@18
|
43 if ($follow_symlinks && is_link($path)) {
|
Chris@18
|
44 $path = realpath($path);
|
Chris@18
|
45 }
|
Chris@18
|
46 // Check the start path.
|
Chris@18
|
47 if ($this->isValidRoot($path)) {
|
Chris@18
|
48 return true;
|
Chris@18
|
49 } else {
|
Chris@18
|
50 // Move up dir by dir and check each.
|
Chris@18
|
51 while ($path = $this->shiftPathUp($path)) {
|
Chris@18
|
52 if ($follow_symlinks && is_link($path)) {
|
Chris@18
|
53 $path = realpath($path);
|
Chris@18
|
54 }
|
Chris@18
|
55 if ($this->isValidRoot($path)) {
|
Chris@18
|
56 return true;
|
Chris@18
|
57 }
|
Chris@18
|
58 }
|
Chris@18
|
59 }
|
Chris@18
|
60 }
|
Chris@18
|
61
|
Chris@18
|
62 return false;
|
Chris@18
|
63 }
|
Chris@18
|
64
|
Chris@18
|
65 /**
|
Chris@18
|
66 * Returns parent directory.
|
Chris@18
|
67 *
|
Chris@18
|
68 * @param string
|
Chris@18
|
69 * Path to start from
|
Chris@18
|
70 *
|
Chris@18
|
71 * @return string|false
|
Chris@18
|
72 * Parent path of given path or false when $path is filesystem root
|
Chris@18
|
73 */
|
Chris@18
|
74 private function shiftPathUp($path)
|
Chris@18
|
75 {
|
Chris@18
|
76 $parent = dirname($path);
|
Chris@18
|
77
|
Chris@18
|
78 return in_array($parent, ['.', $path]) ? false : $parent;
|
Chris@18
|
79 }
|
Chris@18
|
80
|
Chris@18
|
81 /**
|
Chris@18
|
82 * @param $path
|
Chris@18
|
83 *
|
Chris@18
|
84 * @return bool
|
Chris@18
|
85 */
|
Chris@18
|
86 protected function isValidRoot($path)
|
Chris@18
|
87 {
|
Chris@18
|
88 if (!empty($path) && is_dir($path) && file_exists($path . '/autoload.php') && file_exists($path . '/' . $this->getComposerFileName())) {
|
Chris@18
|
89 // Additional check for the presence of core/composer.json to
|
Chris@18
|
90 // grant it is not a Drupal 7 site with a base folder named "core".
|
Chris@18
|
91 $candidate = 'core/includes/common.inc';
|
Chris@18
|
92 if (file_exists($path . '/' . $candidate) && file_exists($path . '/core/core.services.yml')) {
|
Chris@18
|
93 if (file_exists($path . '/core/misc/drupal.js') || file_exists($path . '/core/assets/js/drupal.js')) {
|
Chris@18
|
94 $this->composerRoot = $path;
|
Chris@18
|
95 $this->drupalRoot = $path;
|
Chris@18
|
96 $this->vendorDir = $this->composerRoot . '/vendor';
|
Chris@18
|
97 }
|
Chris@18
|
98 }
|
Chris@18
|
99 }
|
Chris@18
|
100 if (!empty($path) && is_dir($path) && file_exists($path . '/' . $this->getComposerFileName())) {
|
Chris@18
|
101 $json = json_decode(
|
Chris@18
|
102 file_get_contents($path . '/' . $this->getComposerFileName()),
|
Chris@18
|
103 true
|
Chris@18
|
104 );
|
Chris@18
|
105 if (is_array($json)) {
|
Chris@18
|
106 if (isset($json['extra']['installer-paths']) && is_array($json['extra']['installer-paths'])) {
|
Chris@18
|
107 foreach ($json['extra']['installer-paths'] as $install_path => $items) {
|
Chris@18
|
108 if (in_array('type:drupal-core', $items) ||
|
Chris@18
|
109 in_array('drupal/core', $items) ||
|
Chris@18
|
110 in_array('drupal/drupal', $items)) {
|
Chris@18
|
111 $this->composerRoot = $path;
|
Chris@18
|
112 // @todo: Remove this magic and detect the major version instead.
|
Chris@18
|
113 if ($install_path == 'core') {
|
Chris@18
|
114 $install_path = null;
|
Chris@18
|
115 } elseif (substr($install_path, -5) == '/core') {
|
Chris@18
|
116 $install_path = substr($install_path, 0, -5);
|
Chris@18
|
117 }
|
Chris@18
|
118 $this->drupalRoot = rtrim($path . '/' . $install_path, '/');
|
Chris@18
|
119 $this->vendorDir = $this->composerRoot . '/vendor';
|
Chris@18
|
120 }
|
Chris@18
|
121 }
|
Chris@18
|
122 }
|
Chris@18
|
123 }
|
Chris@18
|
124 }
|
Chris@18
|
125 if ($this->composerRoot && file_exists($this->composerRoot . '/' . $this->getComposerFileName())) {
|
Chris@18
|
126 $json = json_decode(
|
Chris@18
|
127 file_get_contents($path . '/' . $this->getComposerFileName()),
|
Chris@18
|
128 true
|
Chris@18
|
129 );
|
Chris@18
|
130 if (is_array($json) && isset($json['config']['vendor-dir'])) {
|
Chris@18
|
131 $this->vendorDir = $this->composerRoot . '/' . $json['config']['vendor-dir'];
|
Chris@18
|
132 }
|
Chris@18
|
133 }
|
Chris@18
|
134
|
Chris@18
|
135 return $this->drupalRoot && $this->composerRoot && $this->vendorDir;
|
Chris@18
|
136 }
|
Chris@18
|
137
|
Chris@18
|
138 /**
|
Chris@18
|
139 * @return string
|
Chris@18
|
140 */
|
Chris@18
|
141 public function getDrupalRoot()
|
Chris@18
|
142 {
|
Chris@18
|
143 return $this->drupalRoot;
|
Chris@18
|
144 }
|
Chris@18
|
145
|
Chris@18
|
146 /**
|
Chris@18
|
147 * @return string
|
Chris@18
|
148 */
|
Chris@18
|
149 public function getComposerRoot()
|
Chris@18
|
150 {
|
Chris@18
|
151 return $this->composerRoot;
|
Chris@18
|
152 }
|
Chris@18
|
153
|
Chris@18
|
154 /**
|
Chris@18
|
155 * @return string
|
Chris@18
|
156 */
|
Chris@18
|
157 protected function getComposerFileName()
|
Chris@18
|
158 {
|
Chris@18
|
159 return trim(getenv('COMPOSER')) ?: 'composer.json';
|
Chris@18
|
160 }
|
Chris@18
|
161
|
Chris@18
|
162 /**
|
Chris@18
|
163 * @return string
|
Chris@18
|
164 */
|
Chris@18
|
165 public function getVendorDir()
|
Chris@18
|
166 {
|
Chris@18
|
167 return $this->vendorDir;
|
Chris@18
|
168 }
|
Chris@18
|
169 }
|