Completed
Push — update/story-block-loading-med... ( e6e62b...d81748 )
by
unknown
28:46 queued 18:45
created

AutoloadGenerator::dump()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 7
dl 0
loc 52
rs 9.0472
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php // phpcs:ignore WordPress.Files.FileName
2
/**
3
 * Autoloader Generator.
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.FunctionDeclarations.NewClosure.Found
11
// phpcs:disable PHPCompatibility.Keywords.NewKeywords.t_namespaceFound
12
// phpcs:disable PHPCompatibility.Keywords.NewKeywords.t_dirFound
13
// phpcs:disable WordPress.Files.FileName.InvalidClassFileName
14
// phpcs:disable WordPress.Files.FileName.InvalidClassFileName
15
// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_var_export
16
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
17
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_fopen
18
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_fwrite
19
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
20
// phpcs:disable WordPress.NamingConventions.ValidVariableName.InterpolatedVariableNotSnakeCase
21
// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
22
// phpcs:disable WordPress.NamingConventions.ValidVariableName.PropertyNotSnakeCase
23
24
25
namespace Automattic\Jetpack\Autoloader;
26
27
use Composer\Autoload\AutoloadGenerator as BaseGenerator;
28
use Composer\Autoload\ClassMapGenerator;
29
use Composer\Config;
30
use Composer\Installer\InstallationManager;
31
use Composer\IO\IOInterface;
32
use Composer\Package\PackageInterface;
33
use Composer\Repository\InstalledRepositoryInterface;
34
use Composer\Util\Filesystem;
35
36
/**
37
 * Class AutoloadGenerator.
38
 */
39
class AutoloadGenerator extends BaseGenerator {
40
41
	const COMMENT = <<<AUTOLOADER_COMMENT
42
/**
43
 * This file was automatically generated by automattic/jetpack-autoloader.
44
 *
45
 * @package automattic/jetpack-autoloader
46
 */
47
48
AUTOLOADER_COMMENT;
49
50
	/**
51
	 * Instantiate an AutoloadGenerator object.
52
	 *
53
	 * @param IOInterface $io IO object.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $io not be null|IOInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
54
	 */
55
	public function __construct( IOInterface $io = null ) {
56
		$this->io = $io;
57
	}
58
59
	/**
60
	 * Dump the autoloader.
61
	 *
62
	 * @param Config                       $config Config object.
63
	 * @param InstalledRepositoryInterface $localRepo Installed Reposetories object.
64
	 * @param PackageInterface             $mainPackage Main Package object.
65
	 * @param InstallationManager          $installationManager Manager for installing packages.
66
	 * @param string                       $targetDir Path to the current target directory.
67
	 * @param bool                         $scanPsr0Packages Whether to search for packages. Currently hard coded to always be false.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $scanPsr0Packages not be boolean|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
68
	 * @param string                       $suffix The autoloader suffix.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $suffix not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
69
	 */
70
	public function dump(
71
		Config $config,
72
		InstalledRepositoryInterface $localRepo,
73
		PackageInterface $mainPackage,
74
		InstallationManager $installationManager,
75
		$targetDir,
76
		$scanPsr0Packages = null, // Not used we always optimize.
77
		$suffix = null
78
	) {
79
80
		$filesystem = new Filesystem();
81
		$filesystem->ensureDirectoryExists( $config->get( 'vendor-dir' ) );
82
83
		$basePath   = $filesystem->normalizePath( realpath( getcwd() ) );
84
		$vendorPath = $filesystem->normalizePath( realpath( $config->get( 'vendor-dir' ) ) );
85
		$targetDir  = $vendorPath . '/' . $targetDir;
86
		$filesystem->ensureDirectoryExists( $targetDir );
87
88
		$packageMap = $this->buildPackageMap( $installationManager, $mainPackage, $localRepo->getCanonicalPackages() );
89
		$autoloads  = $this->parseAutoloads( $packageMap, $mainPackage );
90
91
		$classMap = $this->getClassMap( $autoloads, $filesystem, $vendorPath, $basePath );
92
		$fileMap  = $this->getFileMap( $autoloads, $filesystem, $vendorPath, $basePath );
93
94
		// Generate the files.
95
		file_put_contents( $targetDir . '/jetpack_autoload_classmap.php', $this->getAutoloadClassmapPackagesFile( $classMap ) );
96
		$this->io->writeError( '<info>Generated ' . $targetDir . '/jetpack_autoload_classmap.php</info>', true );
97
98
		file_put_contents( $targetDir . '/jetpack_autoload_filemap.php', $this->getAutoloadFilesPackagesFile( $fileMap ) );
99
		$this->io->writeError( '<info>Generated ' . $targetDir . '/jetpack_autoload_filemap.php</info>', true );
100
101
		file_put_contents( $vendorPath . '/autoload_packages.php', $this->getAutoloadPackageFile( 'autoload.php', $suffix ) );
102
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/autoload_packages.php</info>', true );
103
104
		file_put_contents( $vendorPath . '/autoload_functions.php', $this->getAutoloadPackageFile( 'functions.php', $suffix ) );
105
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/autoload_functions.php</info>', true );
106
107
		file_put_contents( $vendorPath . '/class-autoloader-handler.php', $this->getAutoloadPackageFile( 'class-autoloader-handler.php', $suffix ) );
108
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/class-autoloader-handler.php</info>', true );
109
110
		file_put_contents( $vendorPath . '/class-classes-handler.php', $this->getAutoloadPackageFile( 'class-classes-handler.php', $suffix ) );
111
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/class-classes-handler.php</info>', true );
112
113
		file_put_contents( $vendorPath . '/class-files-handler.php', $this->getAutoloadPackageFile( 'class-files-handler.php', $suffix ) );
114
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/class-files-handler.php</info>', true );
115
116
		file_put_contents( $vendorPath . '/class-plugins-handler.php', $this->getAutoloadPackageFile( 'class-plugins-handler.php', $suffix ) );
117
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/class-plugins-handler.php</info>', true );
118
119
		file_put_contents( $vendorPath . '/class-version-selector.php', $this->getAutoloadPackageFile( 'class-version-selector.php', $suffix ) );
120
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/class-version-selector.php</info>', true );
121
	}
122
123
	/**
124
	 * This function differs from the composer parseAutoloadsType in that beside returning the path.
125
	 * It also return the path and the version of a package.
126
	 *
127
	 * Currently supports only psr-4 and clasmap parsing.
128
	 *
129
	 * @param array            $packageMap Map of all the packages.
130
	 * @param string           $type Type of autoloader to use, currently not used, since we only support psr-4.
131
	 * @param PackageInterface $mainPackage Instance of the Package Object.
132
	 *
133
	 * @return array
134
	 */
135
	protected function parseAutoloadsType( array $packageMap, $type, PackageInterface $mainPackage ) {
136
		$autoloads = array();
137
138
		if ( 'psr-4' !== $type && 'classmap' !== $type && 'files' !== $type ) {
139
			return parent::parseAutoloadsType( $packageMap, $type, $mainPackage );
140
		}
141
142
		foreach ( $packageMap as $item ) {
143
			list($package, $installPath) = $item;
144
			$autoload                    = $package->getAutoload();
145
146
			if ( $package === $mainPackage ) {
147
				$autoload = array_merge_recursive( $autoload, $package->getDevAutoload() );
148
			}
149
150
			if ( null !== $package->getTargetDir() && $package !== $mainPackage ) {
151
				$installPath = substr( $installPath, 0, -strlen( '/' . $package->getTargetDir() ) );
152
			}
153
154 View Code Duplication
			if ( 'psr-4' === $type && isset( $autoload['psr-4'] ) && is_array( $autoload['psr-4'] ) ) {
155
				foreach ( $autoload['psr-4'] as $namespace => $paths ) {
156
					$paths = is_array( $paths ) ? $paths : array( $paths );
157
					foreach ( $paths as $path ) {
158
						$relativePath              = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
159
						$autoloads[ $namespace ][] = array(
160
							'path'    => $relativePath,
161
							'version' => $package->getVersion(), // Version of the class comes from the package - should we try to parse it?
162
						);
163
					}
164
				}
165
			}
166
167 View Code Duplication
			if ( 'classmap' === $type && isset( $autoload['classmap'] ) && is_array( $autoload['classmap'] ) ) {
168
				foreach ( $autoload['classmap'] as $paths ) {
169
					$paths = is_array( $paths ) ? $paths : array( $paths );
170
					foreach ( $paths as $path ) {
171
						$relativePath = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
172
						$autoloads[]  = array(
173
							'path'    => $relativePath,
174
							'version' => $package->getVersion(), // Version of the class comes from the package - should we try to parse it?
175
						);
176
					}
177
				}
178
			}
179 View Code Duplication
			if ( 'files' === $type && isset( $autoload['files'] ) && is_array( $autoload['files'] ) ) {
180
				foreach ( $autoload['files'] as $file_id => $paths ) {
181
					$paths = is_array( $paths ) ? $paths : array( $paths );
182
					foreach ( $paths as $path ) {
183
						$relativePath = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
184
						$autoloads[ $this->getFileIdentifier( $package, $path ) ] = array(
185
							'path'    => $relativePath,
186
							'version' => $package->getVersion(), // Version of the file comes from the package - should we try to parse it?
187
						);
188
					}
189
				}
190
			}
191
		}
192
193
		return $autoloads;
194
	}
195
196
	/**
197
	 * Take the autoloads array and return the classMap that contains the path and the version for each namespace.
198
	 *
199
	 * @param array      $autoloads Array of autoload settings defined defined by the packages.
200
	 * @param Filesystem $filesystem Filesystem class instance.
201
	 * @param string     $vendorPath Path to the vendor directory.
202
	 * @param string     $basePath Base Path.
203
	 *
204
	 * @return string $classMap
205
	 */
206
	private function getClassMap( array $autoloads, Filesystem $filesystem, $vendorPath, $basePath ) {
207
		$blacklist = null;
208
209
		if ( ! empty( $autoloads['exclude-from-classmap'] ) ) {
210
			$blacklist = '{(' . implode( '|', $autoloads['exclude-from-classmap'] ) . ')}';
211
		}
212
213
		$classmapString = '';
214
215
		// Scan the PSR-4 and classmap directories for class files, and add them to the class map.
216
		foreach ( $autoloads['psr-4'] as $namespace => $packages_info ) {
217
			foreach ( $packages_info as $package ) {
218
				$dir       = $filesystem->normalizePath(
219
					$filesystem->isAbsolutePath( $package['path'] )
220
						? $package['path']
221
						: $basePath . '/' . $package['path']
222
				);
223
				$namespace = empty( $namespace ) ? null : $namespace;
224
				$map       = ClassMapGenerator::createMap( $dir, $blacklist, $this->io, $namespace );
225
226 View Code Duplication
				foreach ( $map as $class => $path ) {
227
					$classCode       = var_export( $class, true );
228
					$pathCode        = $this->getPathCode( $filesystem, $basePath, $vendorPath, $path );
229
					$versionCode     = var_export( $package['version'], true );
230
					$classmapString .= <<<CLASS_CODE
231
	$classCode => array(
232
		'version' => $versionCode,
233
		'path'    => $pathCode
234
	),
235
CLASS_CODE;
236
					$classmapString .= PHP_EOL;
237
				}
238
			}
239
		}
240
241
		foreach ( $autoloads['classmap'] as $package ) {
242
			$dir = $filesystem->normalizePath(
243
				$filesystem->isAbsolutePath( $package['path'] )
244
					? $package['path']
245
					: $basePath . '/' . $package['path']
246
			);
247
			$map = ClassMapGenerator::createMap( $dir, $blacklist, $this->io, null );
248
249 View Code Duplication
			foreach ( $map as $class => $path ) {
250
				$classCode       = var_export( $class, true );
251
				$pathCode        = $this->getPathCode( $filesystem, $basePath, $vendorPath, $path );
252
				$versionCode     = var_export( $package['version'], true );
253
				$classmapString .= <<<CLASS_CODE
254
	$classCode => array(
255
		'version' => $versionCode,
256
		'path'    => $pathCode
257
	),
258
CLASS_CODE;
259
				$classmapString .= PHP_EOL;
260
			}
261
		}
262
263
		return 'array( ' . PHP_EOL . $classmapString . ');' . PHP_EOL;
264
	}
265
266
	/**
267
	 * Generate the PHP that will be used in the autoload_classmap_package.php files.
268
	 *
269
	 * @param string $classMap class map array string that is to be written out to the file.
270
	 *
271
	 * @return string
272
	 */
273
	private function getAutoloadClassmapPackagesFile( $classMap ) {
274
275
		return <<<INCLUDE_CLASSMAP
276
<?php
277
278
// This file `autoload_classmap_packages.php` was auto generated by automattic/jetpack-autoloader.
279
280
\$vendorDir = dirname(__DIR__);
281
\$baseDir   = dirname(\$vendorDir);
282
283
return $classMap
284
285
INCLUDE_CLASSMAP;
286
	}
287
288
	/**
289
	 * Take the autoloads array and return the fileMap that contains the path and the version for each namespace.
290
	 *
291
	 * @param array      $autoloads Array of autoload settings defined defined by the packages.
292
	 * @param Filesystem $filesystem Filesystem class instance.
293
	 * @param string     $vendorPath Path to the vendor directory.
294
	 * @param string     $basePath Base Path.
295
	 *
296
	 * @return string $fileMap
297
	 */
298
	private function getFileMap( array $autoloads, Filesystem $filesystem, $vendorPath, $basePath ) {
299
		$fileMapString = '';
300 View Code Duplication
		foreach ( $autoloads['files'] as $file_id => $package ) {
301
			$key            = var_export( $file_id, true );
302
			$pathCode       = $this->getPathCode( $filesystem, $basePath, $vendorPath, $package['path'] );
303
			$versionCode    = var_export( $package['version'], true );
304
			$fileMapString .= <<<FILE_CODE
305
	$key => array(
306
		'version' => $versionCode,
307
		'path'    => $pathCode
308
	),
309
FILE_CODE;
310
			$fileMapString .= PHP_EOL;
311
		}
312
313
		return 'array( ' . PHP_EOL . $fileMapString . ');' . PHP_EOL;
314
	}
315
316
	/**
317
	 * Generate the PHP that will be used in the autoload_files_package.php files.
318
	 *
319
	 * @param string $filesMap files array as string that is to be written out to the file.
320
	 *
321
	 * @return string
322
	 */
323
	private function getAutoloadFilesPackagesFile( $filesMap ) {
324
325
		return <<<INCLUDE_FILEMAP
326
<?php
327
328
// This file `autoload_files_packages.php` was auto generated by automattic/jetpack-autoloader.
329
330
\$vendorDir = dirname(__DIR__);
331
\$baseDir   = dirname(\$vendorDir);
332
333
return $filesMap
334
335
INCLUDE_FILEMAP;
336
	}
337
338
	/**
339
	 * Generate the PHP that will be used in the autoload_packages.php files.
340
	 *
341
	 * @param String $filename a file to prepare.
342
	 * @param String $suffix   Unique suffix used in the namespace.
343
	 *
344
	 * @return string
345
	 */
346
	private function getAutoloadPackageFile( $filename, $suffix ) {
347
		$header  = self::COMMENT;
348
		$header .= PHP_EOL;
349
		$header .= 'namespace Automattic\Jetpack\Autoloader\jp' . $suffix . ';';
350
		$header .= PHP_EOL . PHP_EOL;
351
352
		$sourceLoader  = fopen( __DIR__ . '/' . $filename, 'r' );
353
		$file_contents = stream_get_contents( $sourceLoader );
354
		return str_replace(
355
			'/* HEADER */',
356
			$header,
357
			$file_contents
358
		);
359
	}
360
}
361