Completed
Push — renovate/slack-web-api-6.x ( 1d54b7...bfe495 )
by
unknown
193:23 queued 183:13
created

CustomAutoloaderPlugin   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 170
Duplicated Lines 8.24 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 14
loc 170
rs 10
c 0
b 0
f 0
wmc 19
lcom 1
cbo 1

7 Methods

Rating   Name   Duplication   Size   Complexity  
A activate() 0 4 1
A deactivate() 0 6 1
A uninstall() 0 6 1
A getSubscribedEvents() 0 5 1
A postAutoloadDump() 0 28 3
B determineSuffix() 14 31 6
B isRequiredByRoot() 0 25 6

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php //phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
2
/**
3
 * Custom Autoloader Composer Plugin, hooks into composer events to generate the custom autoloader.
4
 *
5
 * @package automattic/jetpack-autoloader
6
 */
7
8
// phpcs:disable PHPCompatibility.Keywords.NewKeywords.t_useFound
9
// phpcs:disable PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
10
// phpcs:disable PHPCompatibility.Keywords.NewKeywords.t_namespaceFound
11
// phpcs:disable WordPress.Files.FileName.NotHyphenatedLowercase
12
// phpcs:disable WordPress.Files.FileName.InvalidClassFileName
13
// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
14
15
namespace Automattic\Jetpack\Autoloader;
16
17
use Composer\Composer;
18
use Composer\EventDispatcher\EventSubscriberInterface;
19
use Composer\IO\IOInterface;
20
use Composer\Plugin\PluginInterface;
21
use Composer\Script\Event;
22
use Composer\Script\ScriptEvents;
23
24
/**
25
 * Class CustomAutoloaderPlugin.
26
 *
27
 * @package automattic/jetpack-autoloader
28
 */
29
class CustomAutoloaderPlugin implements PluginInterface, EventSubscriberInterface {
30
31
	/**
32
	 * IO object.
33
	 *
34
	 * @var IOInterface IO object.
35
	 */
36
	private $io;
37
38
	/**
39
	 * Composer object.
40
	 *
41
	 * @var Composer Composer object.
42
	 */
43
	private $composer;
44
45
	/**
46
	 * Do nothing.
47
	 *
48
	 * @param Composer    $composer Composer object.
49
	 * @param IOInterface $io IO object.
50
	 */
51
	public function activate( Composer $composer, IOInterface $io ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
52
		$this->composer = $composer;
53
		$this->io       = $io;
54
	}
55
56
	/**
57
	 * Do nothing.
58
	 * phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
59
	 *
60
	 * @param Composer    $composer Composer object.
61
	 * @param IOInterface $io IO object.
62
	 */
63
	public function deactivate( Composer $composer, IOInterface $io ) {
64
		/*
65
		 * Intentionally left empty. This is a PluginInterface method.
66
		 * phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
67
		 */
68
	}
69
70
	/**
71
	 * Do nothing.
72
	 * phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
73
	 *
74
	 * @param Composer    $composer Composer object.
75
	 * @param IOInterface $io IO object.
76
	 */
77
	public function uninstall( Composer $composer, IOInterface $io ) {
78
		/*
79
		 * Intentionally left empty. This is a PluginInterface method.
80
		 * phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
81
		 */
82
	}
83
84
	/**
85
	 * Tell composer to listen for events and do something with them.
86
	 *
87
	 * @return array List of subscribed events.
88
	 */
89
	public static function getSubscribedEvents() {
90
		return array(
91
			ScriptEvents::POST_AUTOLOAD_DUMP => 'postAutoloadDump',
92
		);
93
	}
94
95
	/**
96
	 * Generate the custom autolaoder.
97
	 *
98
	 * @param Event $event Script event object.
99
	 */
100
	public function postAutoloadDump( Event $event ) {
101
		// When the autoloader is not required by the root package we don't want to execute it.
102
		// This prevents unwanted transitive execution that generates unused autoloaders or
103
		// at worst throws fatal executions.
104
		if ( ! $this->isRequiredByRoot() ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->isRequiredByRoot() of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
105
			return;
106
		}
107
108
		$config = $this->composer->getConfig();
109
110
		if ( 'vendor' !== $config->raw()['config']['vendor-dir'] ) {
111
			$this->io->writeError( "\n<error>An error occurred while generating the autoloader files:", true );
112
			$this->io->writeError( 'The project\'s composer.json or composer environment set a non-default vendor directory.', true );
113
			$this->io->writeError( 'The default composer vendor directory must be used.</error>', true );
114
			exit();
115
		}
116
117
		$installationManager = $this->composer->getInstallationManager();
118
		$repoManager         = $this->composer->getRepositoryManager();
119
		$localRepo           = $repoManager->getLocalRepository();
120
		$package             = $this->composer->getPackage();
121
		$optimize            = $event->getFlags()['optimize'];
122
		$suffix              = $this->determineSuffix();
123
124
		$generator = new AutoloadGenerator( $this->io );
125
		$generator->dump( $this->composer, $config, $localRepo, $package, $installationManager, 'composer', $optimize, $suffix );
126
		$this->generated = true;
127
	}
128
129
	/**
130
	 * Determine the suffix for the autoloader class.
131
	 *
132
	 * Reuses an existing suffix from vendor/autoload_packages.php or vendor/autoload.php if possible.
133
	 *
134
	 * @return string Suffix.
135
	 */
136
	private function determineSuffix() {
137
		$config     = $this->composer->getConfig();
138
		$vendorPath = $config->get( 'vendor-dir' );
139
140
		// Command line.
141
		$suffix = $config->get( 'autoloader-suffix' );
142
		if ( $suffix ) {
143
			return $suffix;
144
		}
145
146
		// Reuse our own suffix, if any.
147 View Code Duplication
		if ( is_readable( $vendorPath . '/autoload_packages.php' ) ) {
148
			// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
149
			$content = file_get_contents( $vendorPath . '/autoload_packages.php' );
150
			if ( preg_match( '/^namespace Automattic\\\\Jetpack\\\\Autoloader\\\\jp([^;\s]+);/m', $content, $match ) ) {
151
				return $match[1];
152
			}
153
		}
154
155
		// Reuse Composer's suffix, if any.
156 View Code Duplication
		if ( is_readable( $vendorPath . '/autoload.php' ) ) {
157
			// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
158
			$content = file_get_contents( $vendorPath . '/autoload.php' );
159
			if ( preg_match( '{ComposerAutoloaderInit([^:\s]+)::}', $content, $match ) ) {
160
				return $match[1];
161
			}
162
		}
163
164
		// Generate a random suffix.
165
		return md5( uniqid( '', true ) );
166
	}
167
168
	/**
169
	 * Checks to see whether or not the root package is the one that required the autoloader.
170
	 *
171
	 * @return bool
172
	 */
173
	private function isRequiredByRoot() {
174
		$package  = $this->composer->getPackage();
175
		$requires = $package->getRequires();
176
		if ( ! is_array( $requires ) ) {
177
			$requires = array();
178
		}
179
		$devRequires = $package->getDevRequires();
180
		if ( ! is_array( $devRequires ) ) {
181
			$devRequires = array();
182
		}
183
		$requires = array_merge( $requires, $devRequires );
184
185
		if ( empty( $requires ) ) {
186
			$this->io->writeError( "\n<error>The package is not required and this should never happen?</error>", true );
187
			exit();
188
		}
189
190
		foreach ( $requires as $require ) {
191
			if ( 'automattic/jetpack-autoloader' === $require->getTarget() ) {
192
				return true;
193
			}
194
		}
195
196
		return false;
197
	}
198
}
199