1 | <?php |
||
82 | class MergePlugin implements PluginInterface, EventSubscriberInterface |
||
83 | { |
||
84 | |||
85 | /** |
||
86 | * Offical package name |
||
87 | */ |
||
88 | const PACKAGE_NAME = 'wikimedia/composer-merge-plugin'; |
||
89 | |||
90 | /** |
||
91 | * Name of the composer 1.1 init event. |
||
92 | */ |
||
93 | const COMPAT_PLUGINEVENTS_INIT = 'init'; |
||
94 | |||
95 | /** |
||
96 | * @var Composer $composer |
||
97 | */ |
||
98 | protected $composer; |
||
99 | |||
100 | /** |
||
101 | * @var PluginState $state |
||
102 | */ |
||
103 | protected $state; |
||
104 | |||
105 | /** |
||
106 | * @var Logger $logger |
||
107 | */ |
||
108 | protected $logger; |
||
109 | |||
110 | /** |
||
111 | * Files that have already been fully processed |
||
112 | * |
||
113 | * @var string[] $loaded |
||
114 | */ |
||
115 | protected $loaded = array(); |
||
116 | |||
117 | /** |
||
118 | * Files that have already been partially processed |
||
119 | * |
||
120 | * @var string[] $loadedNoDev |
||
121 | */ |
||
122 | protected $loadedNoDev = array(); |
||
123 | |||
124 | /** |
||
125 | * {@inheritdoc} |
||
126 | */ |
||
127 | 165 | public function activate(Composer $composer, IOInterface $io) |
|
133 | |||
134 | /** |
||
135 | * {@inheritdoc} |
||
136 | */ |
||
137 | 5 | public static function getSubscribedEvents() |
|
138 | { |
||
139 | return array( |
||
140 | // Use our own constant to make this event optional. Once |
||
141 | // composer-1.1 is required, this can use PluginEvents::INIT |
||
142 | // instead. |
||
143 | 5 | self::COMPAT_PLUGINEVENTS_INIT => 'onInit', |
|
144 | 5 | InstallerEvents::PRE_DEPENDENCIES_SOLVING => 'onDependencySolve', |
|
145 | 5 | PackageEvents::POST_PACKAGE_INSTALL => 'onPostPackageInstall', |
|
146 | 5 | ScriptEvents::POST_INSTALL_CMD => 'onPostInstallOrUpdate', |
|
147 | 5 | ScriptEvents::POST_UPDATE_CMD => 'onPostInstallOrUpdate', |
|
148 | 5 | ScriptEvents::PRE_AUTOLOAD_DUMP => 'onInstallUpdateOrDump', |
|
149 | 5 | ScriptEvents::PRE_INSTALL_CMD => 'onInstallUpdateOrDump', |
|
150 | 5 | ScriptEvents::PRE_UPDATE_CMD => 'onInstallUpdateOrDump', |
|
151 | 5 | ); |
|
152 | } |
||
153 | |||
154 | /** |
||
155 | * Handle an event callback for initialization. |
||
156 | * |
||
157 | * @param \Composer\EventDispatcher\Event $event |
||
158 | */ |
||
159 | 60 | public function onInit(BaseEvent $event) |
|
160 | { |
||
161 | 60 | $this->state->loadSettings(); |
|
162 | // It is not possible to know if the user specified --dev or --no-dev |
||
163 | // so assume it is false. The dev section will be merged later when |
||
164 | // the other events fire. |
||
165 | 60 | $this->state->setDevMode(false); |
|
166 | 60 | $this->mergeFiles($this->state->getIncludes(), false); |
|
167 | 60 | $this->mergeFiles($this->state->getRequires(), true); |
|
168 | 60 | } |
|
169 | |||
170 | /** |
||
171 | * Handle an event callback for an install, update or dump command by |
||
172 | * checking for "merge-plugin" in the "extra" data and merging package |
||
173 | * contents if found. |
||
174 | * |
||
175 | * @param ScriptEvent $event |
||
176 | */ |
||
177 | 145 | public function onInstallUpdateOrDump(ScriptEvent $event) |
|
192 | |||
193 | /** |
||
194 | * Find configuration files matching the configured glob patterns and |
||
195 | * merge their contents with the master package. |
||
196 | * |
||
197 | * @param array $patterns List of files/glob patterns |
||
198 | * @param bool $required Are the patterns required to match files? |
||
199 | * @throws MissingFileException when required and a pattern returns no |
||
200 | * results |
||
201 | */ |
||
202 | 145 | protected function mergeFiles(array $patterns, $required = false) |
|
223 | |||
224 | /** |
||
225 | * Read a JSON file and merge its contents |
||
226 | * |
||
227 | * @param RootPackageInterface $root |
||
228 | * @param string $path |
||
229 | */ |
||
230 | 140 | protected function mergeFile(RootPackageInterface $root, $path) |
|
231 | { |
||
232 | 140 | if (isset($this->loaded[$path]) || |
|
233 | 140 | (isset($this->loadedNoDev[$path]) && !$this->state->isDevMode()) |
|
234 | 140 | ) { |
|
235 | 140 | $this->logger->debug( |
|
236 | 140 | "Already merged <comment>$path</comment> completely" |
|
237 | 140 | ); |
|
238 | 140 | return; |
|
239 | } |
||
240 | |||
241 | 140 | $package = new ExtraPackage($path, $this->composer, $this->logger); |
|
242 | |||
243 | 140 | if (isset($this->loadedNoDev[$path])) { |
|
244 | 60 | $this->logger->info( |
|
245 | 60 | "Loading -dev sections of <comment>{$path}</comment>..." |
|
246 | 60 | ); |
|
247 | 60 | $package->mergeDevInto($root, $this->state); |
|
248 | 60 | } else { |
|
249 | 140 | $this->logger->info("Loading <comment>{$path}</comment>..."); |
|
250 | 140 | $package->mergeInto($root, $this->state); |
|
251 | } |
||
252 | |||
253 | 140 | if ($this->state->isDevMode()) { |
|
254 | 135 | $this->loaded[$path] = true; |
|
255 | 135 | } else { |
|
256 | 65 | $this->loadedNoDev[$path] = true; |
|
257 | } |
||
258 | |||
259 | 140 | if ($this->state->recurseIncludes()) { |
|
260 | 135 | $this->mergeFiles($package->getIncludes(), false); |
|
261 | 135 | $this->mergeFiles($package->getRequires(), true); |
|
262 | 135 | } |
|
263 | 140 | } |
|
264 | |||
265 | /** |
||
266 | * Handle an event callback for pre-dependency solving phase of an install |
||
267 | * or update by adding any duplicate package dependencies found during |
||
268 | * initial merge processing to the request that will be processed by the |
||
269 | * dependency solver. |
||
270 | * |
||
271 | * @param InstallerEvent $event |
||
272 | */ |
||
273 | 140 | public function onDependencySolve(InstallerEvent $event) |
|
291 | |||
292 | /** |
||
293 | * Handle an event callback following installation of a new package by |
||
294 | * checking to see if the package that was installed was our plugin. |
||
295 | * |
||
296 | * @param PackageEvent $event |
||
297 | */ |
||
298 | 15 | public function onPostPackageInstall(PackageEvent $event) |
|
312 | |||
313 | /** |
||
314 | * Handle an event callback following an install or update command. If our |
||
315 | * plugin was installed during the run then trigger an update command to |
||
316 | * process any merge-patterns in the current config. |
||
317 | * |
||
318 | * @param ScriptEvent $event |
||
319 | */ |
||
320 | 140 | public function onPostInstallOrUpdate(ScriptEvent $event) |
|
362 | } |
||
363 | // vim:sw=4:ts=4:sts=4:et: |
||
364 |