d2c70c661a92d3dc9069e38d833aaad29a0160b7
[yaffs-website] / vendor / drupal / console / src / Command / Shared / ProjectDownloadTrait.php
1 <?php
2
3 /**
4  * @file
5  * Contains Drupal\Console\Command\Shared\ProjectDownloadTrait.
6  */
7
8 namespace Drupal\Console\Command\Shared;
9
10 use Drupal\Console\Core\Style\DrupalStyle;
11 use Drupal\Console\Zippy\Adapter\TarGzGNUTarForWindowsAdapter;
12 use Drupal\Console\Zippy\FileStrategy\TarGzFileForWindowsStrategy;
13 use Alchemy\Zippy\Zippy;
14 use Alchemy\Zippy\Adapter\AdapterContainer;
15 use Symfony\Component\Filesystem\Filesystem;
16
17 /**
18  * Class ProjectDownloadTrait
19  *
20  * @package Drupal\Console\Command
21  */
22 trait ProjectDownloadTrait
23 {
24     public function modulesQuestion(DrupalStyle $io)
25     {
26         $moduleList = [];
27
28         $modules = $this->extensionManager->discoverModules()
29             ->showUninstalled()
30             ->showNoCore()
31             ->getList(true);
32
33         while (true) {
34             $moduleName = $io->choiceNoList(
35                 $this->trans('commands.module.install.questions.module'),
36                 $modules,
37                 null,
38                 true
39             );
40
41             if (empty($moduleName)) {
42                 break;
43             }
44
45             $moduleList[] = $moduleName;
46
47             if (array_search($moduleName, $moduleList, true) >= 0) {
48                 unset($modules[array_search($moduleName, $modules)]);
49             }
50         }
51
52         return $moduleList;
53     }
54
55     public function modulesUninstallQuestion(DrupalStyle $io)
56     {
57         $moduleList = [];
58
59         $modules = $this->extensionManager->discoverModules()
60             ->showInstalled()
61             ->showNoCore()
62             ->showCore()
63             ->getList(true);
64
65         while (true) {
66             $moduleName = $io->choiceNoList(
67                 $this->trans('commands.module.uninstall.questions.module'),
68                 $modules,
69                 null,
70                 true
71             );
72
73             if (empty($moduleName)) {
74                 break;
75             }
76
77             $moduleList[] = $moduleName;
78         }
79
80         return $moduleList;
81     }
82
83     private function downloadModules(DrupalStyle $io, $modules, $latest, $path = null, $resultList = [])
84     {
85         if (!$resultList) {
86             $resultList = [
87               'invalid' => [],
88               'uninstalled' => [],
89               'dependencies' => []
90             ];
91         }
92         drupal_static_reset('system_rebuild_module_data');
93
94         $missingModules = $this->validator->getMissingModules($modules);
95
96         $invalidModules = [];
97         if ($missingModules) {
98             $io->info(
99                 sprintf(
100                     $this->trans('commands.module.install.messages.getting-missing-modules'),
101                     implode(', ', $missingModules)
102                 )
103             );
104             foreach ($missingModules as $missingModule) {
105                 $version = $this->releasesQuestion($io, $missingModule, $latest);
106                 if ($version) {
107                     $this->downloadProject($io, $missingModule, $version, 'module', $path);
108                 } else {
109                     $invalidModules[] = $missingModule;
110                     unset($modules[array_search($missingModule, $modules)]);
111                 }
112                 $this->extensionManager->discoverModules();
113             }
114         }
115
116         $unInstalledModules = $this->validator->getUninstalledModules($modules);
117
118         $dependencies = $this->calculateDependencies($unInstalledModules);
119
120         $resultList = [
121           'invalid' => array_unique(array_merge($resultList['invalid'], $invalidModules)),
122           'uninstalled' => array_unique(array_merge($resultList['uninstalled'], $unInstalledModules)),
123           'dependencies' => array_unique(array_merge($resultList['dependencies'], $dependencies))
124         ];
125
126         if (!$dependencies) {
127             return $resultList;
128         }
129
130         return $this->downloadModules($io, $dependencies, $latest, $path, $resultList);
131     }
132
133     protected function calculateDependencies($modules)
134     {
135         $this->site->loadLegacyFile('/core/modules/system/system.module');
136         $moduleList = system_rebuild_module_data();
137
138         $dependencies = [];
139
140         foreach ($modules as $moduleName) {
141             $module = $moduleList[$moduleName];
142
143             $dependencies = array_unique(
144                 array_merge(
145                     $dependencies,
146                     $this->validator->getUninstalledModules(
147                         array_keys($module->requires)?:[]
148                     )
149                 )
150             );
151         }
152
153         return array_diff($dependencies, $modules);
154     }
155
156     /**
157      * @param \Drupal\Console\Core\Style\DrupalStyle $io
158      * @param $project
159      * @param $version
160      * @param $type
161      * @param $path
162      *
163      * @return string
164      */
165     public function downloadProject(DrupalStyle $io, $project, $version, $type, $path = null)
166     {
167         $commandKey = str_replace(':', '.', $this->getName());
168
169         $io->comment(
170             sprintf(
171                 $this->trans('commands.'.$commandKey.'.messages.downloading'),
172                 $project,
173                 $version
174             )
175         );
176
177         try {
178             $destination = $this->drupalApi->downloadProjectRelease(
179                 $project,
180                 $version
181             );
182
183             if (!$path) {
184                 $path = $this->getExtractPath($type);
185             }
186
187             $projectPath = sprintf(
188                 '%s/%s',
189                 $this->appRoot,
190                 $path
191             );
192
193             if (!file_exists($projectPath)) {
194                 if (!mkdir($projectPath, 0777, true)) {
195                     $io->error(
196                         sprintf(
197                             $this->trans('commands.'.$commandKey.'.messages.error-creating-folder'),
198                             $projectPath
199                         )
200                     );
201                     return null;
202                 }
203             }
204
205             $zippy = Zippy::load();
206             if (PHP_OS === "WIN32" || PHP_OS === "WINNT") {
207                 $container = AdapterContainer::load();
208                 $container['Drupal\\Console\\Zippy\\Adapter\\TarGzGNUTarForWindowsAdapter'] = function ($container) {
209                     return TarGzGNUTarForWindowsAdapter::newInstance(
210                         $container['executable-finder'],
211                         $container['resource-manager'],
212                         $container['gnu-tar.inflator'],
213                         $container['gnu-tar.deflator']
214                     );
215                 };
216                 $zippy->addStrategy(new TarGzFileForWindowsStrategy($container));
217             }
218             $archive = $zippy->open($destination);
219             if ($type == 'core') {
220                 $archive->extract(getenv('MSYSTEM') ? null : $projectPath);
221             } elseif (getenv('MSYSTEM')) {
222                 $current_dir = getcwd();
223                 $temp_dir = sys_get_temp_dir();
224                 chdir($temp_dir);
225                 $archive->extract();
226                 $fileSystem = new Filesystem();
227                 $fileSystem->rename($temp_dir . '/' . $project, $projectPath . '/' . $project);
228                 chdir($current_dir);
229             } else {
230                 $archive->extract($projectPath);
231             }
232
233             unlink($destination);
234
235             if ($type != 'core') {
236                 $io->success(
237                     sprintf(
238                         $this->trans(
239                             'commands.' . $commandKey . '.messages.downloaded'
240                         ),
241                         $project,
242                         $version,
243                         sprintf('%s/%s', $projectPath, $project)
244                     )
245                 );
246             }
247         } catch (\Exception $e) {
248             $io->error($e->getMessage());
249
250             return null;
251         }
252
253         return $projectPath;
254     }
255
256     /**
257      * @param \Drupal\Console\Core\Style\DrupalStyle $io
258      * @param string                                 $project
259      * @param bool                                   $latest
260      * @param bool                                   $stable
261      * @return string
262      */
263     public function releasesQuestion(DrupalStyle $io, $project, $latest = false, $stable = false)
264     {
265         $commandKey = str_replace(':', '.', $this->getName());
266
267         $io->comment(
268             sprintf(
269                 $this->trans('commands.'.$commandKey.'.messages.getting-releases'),
270                 implode(',', [$project])
271             )
272         );
273
274         $releases = $this->drupalApi->getProjectReleases($project, $latest?1:15, $stable);
275
276         if (!$releases) {
277             $io->error(
278                 sprintf(
279                     $this->trans('commands.'.$commandKey.'.messages.no-releases'),
280                     implode(',', [$project])
281                 )
282             );
283
284             return null;
285         }
286
287         if ($latest) {
288             return $releases[0];
289         }
290
291         $version = $io->choice(
292             $this->trans('commands.'.$commandKey.'.messages.select-release'),
293             $releases
294         );
295
296         return $version;
297     }
298
299     /**
300      * @param $type
301      * @return string
302      */
303     private function getExtractPath($type)
304     {
305         switch ($type) {
306         case 'module':
307             return 'modules/contrib';
308         case 'theme':
309             return 'themes';
310         case 'profile':
311             return 'profiles';
312         case 'core':
313             return '';
314         }
315     }
316
317     /**
318      * check if a modules repo is in composer.json
319      * check if the repo is setted and matchs the one in config.yml
320      *
321      * @param  object $config
322      * @return boolean
323      */
324     private function repositoryAlreadySet($config, $repo)
325     {
326         if (!$config->repositories) {
327             return false;
328         } else {
329             if (in_array($repo, $config->repositories)) {
330                 return true;
331             } else {
332                 return false;
333             }
334         }
335     }
336 }