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