Completed
Pull Request — master (#25)
by Damian
03:36
created

VendorExposeCommand   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 48
dl 0
loc 125
rs 10
c 0
b 0
f 0
wmc 18

6 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 10 1
A getAllLibraries() 0 23 5
A execute() 0 21 2
A isPathModule() 0 4 2
B getModulePaths() 0 32 7
A getProjectPath() 0 3 1
1
<?php
2
3
namespace SilverStripe\VendorPlugin\Console;
4
5
use Composer\Command\BaseCommand;
6
use Composer\Factory;
7
use Composer\IO\ConsoleIO;
8
use Composer\Util\Filesystem;
9
use Generator;
10
use SilverStripe\VendorPlugin\Library;
11
use SilverStripe\VendorPlugin\Util;
12
use SilverStripe\VendorPlugin\VendorExposeTask;
13
use SilverStripe\VendorPlugin\VendorPlugin;
14
use Symfony\Component\Console\Input\InputArgument;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Output\OutputInterface;
17
18
/**
19
 * Provides `composer vendor-expose` behaviour
20
 */
21
class VendorExposeCommand extends BaseCommand
22
{
23
    public function configure()
24
    {
25
        $this->setName('vendor-expose');
26
        $this->setDescription('Refresh all exposed module/theme/project folders');
27
        $this->addArgument(
28
            'method',
29
            InputArgument::OPTIONAL,
30
            'Optional method to use. Defaults to last used value, or ' . VendorPlugin::METHOD_DEFAULT . ' otherwise'
31
        );
32
        $this->setHelp('This command will update all resources for all installed modules using the given method');
33
    }
34
35
    public function execute(InputInterface $input, OutputInterface $output)
36
    {
37
        $io = new ConsoleIO($input, $output, $this->getHelperSet());
38
39
        // Check libraries to expose
40
        $modules = $this->getAllLibraries();
41
        if (empty($modules)) {
42
            $io->write("No modules to expose");
43
            return;
44
        }
45
46
        // Query first library for base destination
47
        $basePublicPath = $modules[0]->getBasePublicPath();
48
49
        // Expose all modules
50
        $method = $input->getArgument('method');
51
        $task = new VendorExposeTask($this->getProjectPath(), new Filesystem(), $basePublicPath);
52
        $task->process($io, $modules, $method);
53
54
        // Success
55
        $io->write("All modules updated!");
56
    }
57
58
    /**
59
     * Get all libraries
60
     *
61
     * @return Library[]
62
     */
63
    protected function getAllLibraries()
64
    {
65
        $modules = [];
66
        $basePath = $this->getProjectPath();
67
68
        // Get all modules
69
        foreach ($this->getModulePaths() as $modulePath) {
70
            // Filter by non-composer folders
71
            $composerPath = Util::joinPaths($modulePath, 'composer.json');
72
            if (!file_exists($composerPath)) {
73
                continue;
74
            }
75
76
            // Ensure this library should be exposed, and has at least one folder
77
            $module = new Library($basePath, $modulePath);
78
            if (!$module->requiresExpose() || !$module->getExposedFolders()) {
79
                continue;
80
            }
81
82
            // Save this module
83
            $modules[] = $module;
84
        }
85
        return $modules;
86
    }
87
88
    /**
89
     * Search all paths that could contain a module / theme
90
     *
91
     * @return Generator
92
     */
93
    protected function getModulePaths()
94
    {
95
        // Project root is always returned
96
        $basePath = $this->getProjectPath();
97
        yield $basePath;
98
99
        // Get vendor modules
100
        $search = Util::joinPaths($basePath, 'vendor', '*', '*');
101
        foreach (glob($search, GLOB_ONLYDIR) as $modulePath) {
102
            if ($this->isPathModule($modulePath)) {
103
                yield $modulePath;
104
            }
105
        }
106
107
        // Check if public/ folder exists
108
        $publicExists = is_dir(Util::joinPaths($basePath, Library::PUBLIC_PATH));
109
        if (!$publicExists) {
110
            return;
111
        }
112
113
        // Search all base folders / modules
114
        $search = Util::joinPaths($basePath, '*');
115
        foreach (glob($search, GLOB_ONLYDIR) as $modulePath) {
116
            if ($this->isPathModule($modulePath)) {
117
                yield $modulePath;
118
            }
119
        }
120
121
        // Check all themes
122
        $search = Util::joinPaths($basePath, 'themes', '*');
123
        foreach (glob($search, GLOB_ONLYDIR) as $themePath) {
124
            yield $themePath;
125
        }
126
    }
127
128
    /**
129
     * Check if the given path is a silverstripe module
130
     *
131
     * @param string $path
132
     * @return bool
133
     */
134
    protected function isPathModule($path)
135
    {
136
        return file_exists(Util::joinPaths($path, '_config'))
137
            || file_exists(Util::joinPaths($path, '_config.php'));
138
    }
139
140
    /**
141
     * @return string
142
     */
143
    protected function getProjectPath()
144
    {
145
        return dirname(realpath(Factory::getComposerFile()));
146
    }
147
}
148