VendorExposeTask   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 62
c 1
b 0
f 0
dl 0
loc 192
rs 10
wmc 25

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getMethodFilePath() 0 5 1
B getMethod() 0 23 7
A __construct() 0 5 1
A process() 0 37 6
A getMethodKey() 0 16 4
A getResourcesPath() 0 3 1
A setupResources() 0 14 4
A saveMethodKey() 0 4 1
1
<?php
2
3
4
namespace SilverStripe\VendorPlugin;
5
6
use Composer\IO\IOInterface;
7
use Composer\Util\Filesystem;
8
use Composer\Util\Platform;
9
use DirectoryIterator;
10
use InvalidArgumentException;
11
use SilverStripe\VendorPlugin\Methods\ChainedMethod;
12
use SilverStripe\VendorPlugin\Methods\CopyMethod;
13
use SilverStripe\VendorPlugin\Methods\ExposeMethod;
14
use SilverStripe\VendorPlugin\Methods\JunctionMethod;
15
use SilverStripe\VendorPlugin\Methods\SymlinkMethod;
16
17
/**
18
 * Task for exposing all vendor paths
19
 */
20
class VendorExposeTask
21
{
22
    /**
23
     * Absolute filesystem path to root folder
24
     *
25
     * @var string
26
     */
27
    protected $basePath = null;
28
29
    /**
30
     * @var Filesystem
31
     */
32
    protected $filesystem;
33
34
    /**
35
     * Path to expose to
36
     *
37
     * @var string
38
     */
39
    protected $resourcesPath;
40
41
    /**
42
     * Construct task for the given base folder
43
     *
44
     * @param string $basePath
45
     * @param Filesystem $filesystem
46
     * @param string $publicPath Public path to expose to
47
     */
48
    public function __construct($basePath, Filesystem $filesystem, $publicPath)
49
    {
50
        $this->basePath = $basePath;
51
        $this->filesystem = $filesystem;
52
        $this->resourcesPath = $publicPath;
53
    }
54
55
    /**
56
     * Expose all modules with the given method
57
     *
58
     * @param IOInterface $io
59
     * @param Library[] $libraries
60
     * @param string $methodKey Method key, or null to auto-detect from environment
61
     */
62
    public function process(IOInterface $io, array $libraries, $methodKey = null)
63
    {
64
        // No-op
65
        if (empty($libraries)) {
66
            return;
67
        }
68
69
        // Setup root folder
70
        $this->setupResources($io);
71
72
        // Get or choose method
73
        if (!$methodKey) {
74
            $methodKey = $this->getMethodKey();
75
        }
76
        $method = $this->getMethod($methodKey);
77
78
        // Update all modules
79
        foreach ($libraries as $module) {
80
            // Skip this module if no exposure required
81
            if (!$module->requiresExpose()) {
82
                continue;
83
            }
84
            $name = $module->getName();
85
            $type = $module->getType();
86
            $io->write(
87
                "Exposing web directories for {$type} <info>{$name}</info> with method <info>{$methodKey}</info>:"
88
            );
89
            foreach ($module->getExposedFolders() as $folder) {
90
                $io->write("  - <info>$folder</info>");
91
            }
92
93
            // Expose web dirs with given method
94
            $module->exposePaths($method);
95
        }
96
97
        // On success, write `.method` token to persist for subsequent updates
98
        $this->saveMethodKey($methodKey);
99
    }
100
101
102
    /**
103
     * Ensure the resources folder is safely created and protected from index.php in root
104
     *
105
     * @param IOInterface $io
106
     */
107
    protected function setupResources(IOInterface $io)
108
    {
109
        // Setup root dir
110
        $resourcesPath = $this->getResourcesPath();
111
        $this->filesystem->ensureDirectoryExists($resourcesPath);
112
113
        // Copy missing resources
114
        $files = new DirectoryIterator(__DIR__.'/../resources');
115
        foreach ($files as $file) {
116
            $targetPath = $resourcesPath . DIRECTORY_SEPARATOR . $file->getFilename();
117
            if ($file->isFile() && !file_exists($targetPath)) {
118
                $name = $file->getFilename();
119
                $io->write("Writing <info>{$name}</info> to resources folder");
120
                copy($file->getPathname(), $targetPath);
121
            }
122
        }
123
    }
124
125
    /**
126
     * Get named method instance
127
     *
128
     * @param string $key Key of method to use
129
     * @return ExposeMethod
130
     */
131
    protected function getMethod($key)
132
    {
133
        switch ($key) {
134
            case CopyMethod::NAME:
135
                return new CopyMethod();
136
            case SymlinkMethod::NAME:
137
                return new SymlinkMethod();
138
            case JunctionMethod::NAME:
139
                return new JunctionMethod();
140
            case VendorPlugin::METHOD_NONE:
141
                // 'none' is forced to an empty chain
142
                return new ChainedMethod([]);
0 ignored issues
show
Bug introduced by
array() of type array is incompatible with the type SilverStripe\VendorPlugin\Methods\ExposeMethod expected by parameter $failovers of SilverStripe\VendorPlugi...edMethod::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

142
                return new ChainedMethod(/** @scrutinizer ignore-type */ []);
Loading history...
143
            case VendorPlugin::METHOD_AUTO:
144
                // Default to safe-failover method
145
                if (Platform::isWindows()) {
146
                    // Use junctions on windows environment
147
                    return new ChainedMethod(new JunctionMethod(), new CopyMethod());
148
                } else {
149
                    // Use symlink on non-windows environments
150
                    return new ChainedMethod(new SymlinkMethod(), new CopyMethod());
151
                }
152
            default:
153
                throw new InvalidArgumentException("Invalid method: {$key}");
154
        }
155
    }
156
157
    /**
158
     * Get 'key' of method to use
159
     *
160
     * @return string
161
     */
162
    protected function getMethodKey()
163
    {
164
        // Switch if `resources/.method` contains a file
165
        $methodFilePath = $this->getMethodFilePath();
166
        if (file_exists($methodFilePath) && is_readable($methodFilePath)) {
167
            return trim(file_get_contents($methodFilePath));
168
        }
169
170
        // Switch based on SS_VENDOR_METHOD arg
171
        $method = getenv(VendorPlugin::METHOD_ENV);
172
        if ($method) {
173
            return $method;
174
        }
175
176
        // Default method
177
        return VendorPlugin::METHOD_DEFAULT;
178
    }
179
180
    /**
181
     * Persist method key to `resources/.method` to set value
182
     *
183
     * @param string $key
184
     */
185
    protected function saveMethodKey($key)
186
    {
187
        $methodFilePath = $this->getMethodFilePath();
188
        file_put_contents($methodFilePath, $key);
189
    }
190
191
    /**
192
     * Get path to method cache file
193
     *
194
     * @return string
195
     */
196
    protected function getMethodFilePath()
197
    {
198
        return Util::joinPaths(
199
            $this->getResourcesPath(),
200
            VendorPlugin::METHOD_FILE
201
        );
202
    }
203
204
    /**
205
     * Path to 'resources' folder
206
     *
207
     * @return string
208
     */
209
    protected function getResourcesPath()
210
    {
211
        return $this->resourcesPath;
212
    }
213
}
214