Issues (10)

src/VendorPlugin.php (4 issues)

Severity
1
<?php
2
3
namespace SilverStripe\VendorPlugin;
4
5
use Composer\Composer;
6
use Composer\DependencyResolver\Operation\InstallOperation;
7
use Composer\DependencyResolver\Operation\UninstallOperation;
8
use Composer\DependencyResolver\Operation\UpdateOperation;
9
use Composer\EventDispatcher\EventSubscriberInterface;
10
use Composer\Factory;
11
use Composer\Installer\PackageEvent;
12
use Composer\IO\IOInterface;
13
use Composer\Package\PackageInterface;
14
use Composer\Plugin\Capability\CommandProvider;
15
use Composer\Plugin\Capable;
16
use Composer\Plugin\PluginInterface;
17
use Composer\Script\Event;
18
use Composer\Util\Filesystem;
19
use SilverStripe\VendorPlugin\Console\VendorCommandProvider;
20
21
/**
22
 * Provides public webroot rewrite functionality for vendor modules
23
 */
24
class VendorPlugin implements PluginInterface, EventSubscriberInterface, Capable
25
{
26
    /**
27
     * Default module type
28
     *
29
     * @deprecated 1.3..2.0 No longer used
30
     */
31
    const MODULE_TYPE = 'silverstripe-vendormodule';
32
33
    /**
34
     * Filter for matching library types to expose
35
     *
36
     * @deprecated 1.3..2.0 No longer used
37
     */
38
    const MODULE_FILTER = '/^silverstripe\-(\w+)$/';
39
40
    /**
41
     * Method env var to query
42
     */
43
    const METHOD_ENV = 'SS_VENDOR_METHOD';
44
45
    /**
46
     * Method name for "none" option
47
     */
48
    const METHOD_NONE = 'none';
49
50
    /**
51
     * Method name to auto-attempt best method
52
     */
53
    const METHOD_AUTO = 'auto';
54
55
    /**
56
     * File name to use for linking method storage
57
     */
58
    const METHOD_FILE = '.method';
59
60
    /**
61
     * Define default as 'auto'
62
     */
63
    const METHOD_DEFAULT = self::METHOD_AUTO;
64
65
    /**
66
     * @var Filesystem
67
     */
68
    protected $filesystem = null;
69
70
    public function __construct()
71
    {
72
        $this->filesystem = new Filesystem();
73
    }
74
75
    /**
76
     * Apply vendor plugin
77
     *
78
     * @param Composer $composer
79
     * @param IOInterface $io
80
     */
81
    public function activate(Composer $composer, IOInterface $io)
82
    {
83
    }
84
85
    public static function getSubscribedEvents()
86
    {
87
        return [
88
            'post-package-update' => 'installPackage',
89
            'post-package-install' => 'installPackage',
90
            'pre-package-uninstall' => 'uninstallPackage',
91
            'post-install-cmd' => 'installRootPackage',
92
            'post-update-cmd' => 'installRootPackage',
93
        ];
94
    }
95
96
    /**
97
     * Get vendor module instance for this event
98
     *
99
     * @deprecated 1.3..2.0
100
     * @param PackageEvent $event
101
     * @return Library|null
102
     */
103
    protected function getVendorModule(PackageEvent $event)
104
    {
105
        return $this->getLibrary($event);
106
    }
107
108
    /**
109
     * Gets library being installed
110
     *
111
     * @param PackageEvent $event
112
     * @return Library|null
113
     */
114
    public function getLibrary(PackageEvent $event)
115
    {
116
        // Ensure package is the valid type
117
        $package = $this->getOperationPackage($event);
118
        if (!$package) {
0 ignored issues
show
$package is of type Composer\Package\PackageInterface, thus it always evaluated to true.
Loading history...
119
            return null;
120
        }
121
122
        // Get appropriate installer and query install path
123
        $installer = $event->getComposer()->getInstallationManager()->getInstaller($package->getType());
124
        $path = $installer->getInstallPath($package);
125
126
        // Build module
127
        return new Library($this->getProjectPath(), $path);
128
    }
129
130
    /**
131
     * Install resources from an installed or updated package
132
     *
133
     * @param PackageEvent $event
134
     */
135
    public function installPackage(PackageEvent $event)
136
    {
137
        // Ensure module exists and requires exposure
138
        $library = $this->getLibrary($event);
139
        if (!$library) {
0 ignored issues
show
$library is of type SilverStripe\VendorPlugin\Library, thus it always evaluated to true.
Loading history...
140
            return;
141
        }
142
143
        // Install found library
144
        $this->installLibrary($event->getIO(), $library);
145
    }
146
147
    /**
148
     * Install resources from the root package
149
     *
150
     * @param Event $event
151
     */
152
    public function installRootPackage(Event $event)
153
    {
154
        // Build library in base path
155
        $basePath = $this->getProjectPath();
156
        $library = new Library($basePath, $basePath);
157
158
        // Pass to library installer
159
        $this->installLibrary($event->getIO(), $library);
160
    }
161
162
    /**
163
     * Get base path to project
164
     *
165
     * @return string
166
     */
167
    protected function getProjectPath()
168
    {
169
        return dirname(realpath(Factory::getComposerFile()));
170
    }
171
172
    /**
173
     * Remove package
174
     *
175
     * @param PackageEvent $event
176
     */
177
    public function uninstallPackage(PackageEvent $event)
178
    {
179
        // Check if library exists and exposes any directories
180
        $library = $this->getLibrary($event);
181
        if (!$library || !$library->requiresExpose()) {
0 ignored issues
show
$library is of type SilverStripe\VendorPlugin\Library, thus it always evaluated to true.
Loading history...
182
            return;
183
        }
184
185
        // Check path to remove
186
        $target = $library->getPublicPath();
187
        if (!is_dir($target)) {
188
            return;
189
        }
190
191
        // Remove directory
192
        $name = $library->getName();
193
        $event->getIO()->write("Removing web directories for module <info>{$name}</info>:");
194
        $this->filesystem->removeDirectory($target);
195
196
        // Cleanup empty vendor dir if this is the last module
197
        $targetParent = dirname($target);
198
        if ($this->filesystem->isDirEmpty($targetParent)) {
199
            $this->filesystem->removeDirectory($targetParent);
200
        }
201
    }
202
203
    /**
204
     * Get target package from operation
205
     *
206
     * @param PackageEvent $event
207
     * @return PackageInterface
208
     */
209
    protected function getOperationPackage(PackageEvent $event)
210
    {
211
        $operation = $event->getOperation();
212
        if ($operation instanceof UpdateOperation) {
213
            return $operation->getTargetPackage();
214
        }
215
        if ($operation instanceof InstallOperation) {
216
            return $operation->getPackage();
217
        }
218
        if ($operation instanceof UninstallOperation) {
219
            return $operation->getPackage();
220
        }
221
        return null;
222
    }
223
224
    public function getCapabilities()
225
    {
226
        return [
227
            CommandProvider::class => VendorCommandProvider::class
228
        ];
229
    }
230
231
    /**
232
     * Expose the given Library object
233
     *
234
     * @param IOInterface $IO
235
     * @param Library $library
236
     */
237
    protected function installLibrary(IOInterface $IO, Library $library)
238
    {
239
        if (!$library || !$library->requiresExpose()) {
0 ignored issues
show
$library is of type SilverStripe\VendorPlugin\Library, thus it always evaluated to true.
Loading history...
240
            return;
241
        }
242
243
        // Create exposure task
244
        $task = new VendorExposeTask(
245
            $this->getProjectPath(),
246
            $this->filesystem,
247
            $library->getBasePublicPath()
248
        );
249
        $task->process($IO, [$library]);
250
    }
251
252
    /**
253
     * Required by the composer 2 plugin interface
254
     */
255
    public function deactivate(Composer $composer, IOInterface $io)
256
    {
257
    }
258
259
    /**
260
     * Required by the composer 2 plugin interface
261
     */
262
    public function uninstall(Composer $composer, IOInterface $io)
263
    {
264
    }
265
}
266