Completed
Push — try/independent-logo-package-t... ( e4c534...5e4013 )
by Marin
14:47 queued 05:39
created

AutoloadGenerator::dump()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 7
dl 0
loc 31
rs 9.424
c 0
b 0
f 0
1
<?php
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.NotHyphenatedLowercase
15
// phpcs:disable WordPress.Files.FileName.InvalidClassFileName
16
// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_var_export
17
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
18
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_fopen
19
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_fwrite
20
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
21
// phpcs:disable WordPress.NamingConventions.ValidVariableName.InterpolatedVariableNotSnakeCase
22
// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
23
// phpcs:disable WordPress.NamingConventions.ValidVariableName.PropertyNotSnakeCase
24
25
26
namespace Automattic\Jetpack\Autoloader;
27
28
use Composer\Autoload\AutoloadGenerator as BaseGenerator;
29
use Composer\Autoload\ClassMapGenerator;
30
use Composer\Config;
31
use Composer\Installer\InstallationManager;
32
use Composer\IO\IOInterface;
33
use Composer\Package\PackageInterface;
34
use Composer\Repository\InstalledRepositoryInterface;
35
use Composer\Util\Filesystem;
36
37
/**
38
 * Class AutoloadGenerator.
39
 */
40
class AutoloadGenerator extends BaseGenerator {
41
42
	/**
43
	 * Instantiate an AutoloadGenerator object.
44
	 *
45
	 * @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...
46
	 */
47
	public function __construct( IOInterface $io = null ) {
48
		$this->io = $io;
49
	}
50
51
	/**
52
	 * Dump the autoloader.
53
	 *
54
	 * @param Config                       $config Config object.
55
	 * @param InstalledRepositoryInterface $localRepo Installed Reposetories object.
56
	 * @param PackageInterface             $mainPackage Main Package object.
57
	 * @param InstallationManager          $installationManager Manager for installing packages.
58
	 * @param string                       $targetDir Path to the current target directory.
59
	 * @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...
60
	 * @param string                       $suffix The autoloader suffix, ignored since we want our autoloader to only be included once.
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...
61
	 */
62
	public function dump(
63
		Config $config,
64
		InstalledRepositoryInterface $localRepo,
65
		PackageInterface $mainPackage,
66
		InstallationManager $installationManager,
67
		$targetDir,
68
		$scanPsr0Packages = null, // Not used we always optimize.
69
		$suffix = null
70
	) {
71
72
		$filesystem = new Filesystem();
73
		$filesystem->ensureDirectoryExists( $config->get( 'vendor-dir' ) );
74
75
		$basePath   = $filesystem->normalizePath( realpath( getcwd() ) );
76
		$vendorPath = $filesystem->normalizePath( realpath( $config->get( 'vendor-dir' ) ) );
77
		$targetDir  = $vendorPath . '/' . $targetDir;
78
		$filesystem->ensureDirectoryExists( $targetDir );
79
80
		$packageMap = $this->buildPackageMap( $installationManager, $mainPackage, $localRepo->getCanonicalPackages() );
81
		$autoloads  = $this->parseAutoloads( $packageMap, $mainPackage );
82
83
		$classMap = $this->getClassMap( $autoloads, $filesystem, $vendorPath, $basePath );
84
85
		// Generate the files.
86
		file_put_contents( $targetDir . '/autoload_classmap_package.php', $this->getAutoloadClassmapPackagesFile( $classMap ) );
87
		$this->io->writeError( '<info>Generated ' . $targetDir . '/autoload_classmap_package.php</info>', true );
88
89
		file_put_contents( $vendorPath . '/autoload_packages.php', $this->getAutoloadPackageFile( $suffix ) );
90
		$this->io->writeError( '<info>Generated ' . $vendorPath . '/autoload_packages.php</info>', true );
91
92
	}
93
94
	/**
95
	 * This function differs from the composer parseAutoloadsType in that beside returning the path.
96
	 * It also return the path and the version of a package.
97
	 *
98
	 * @param array            $packageMap Map of all the packages.
99
	 * @param string           $type Type of autoloader to use, currently not used, since we only support psr-4.
100
	 * @param PackageInterface $mainPackage Instance of the Package Object.
101
	 *
102
	 * @return array
103
	 */
104
	protected function parseAutoloadsType( array $packageMap, $type, PackageInterface $mainPackage ) {
105
		$autoloads = array();
106
		foreach ( $packageMap as $item ) {
107
			list($package, $installPath) = $item;
108
			$autoload                    = $package->getAutoload();
109
110
			if ( $package === $mainPackage ) {
111
				$autoload = array_merge_recursive( $autoload, $package->getDevAutoload() );
112
			}
113
114
			// Skip packages that are not 'psr-4' since we only support them for now.
115
			if ( ! isset( $autoload['psr-4'] ) || ! is_array( $autoload['psr-4'] ) ) {
116
				continue;
117
			}
118
119
			if ( null !== $package->getTargetDir() && $package !== $mainPackage ) {
120
				$installPath = substr( $installPath, 0, -strlen( '/' . $package->getTargetDir() ) );
121
			}
122
			foreach ( $autoload['psr-4'] as $namespace => $paths ) {
123
				foreach ( (array) $paths as $path ) {
124
					$relativePath              = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
125
					$autoloads[ $namespace ][] = array(
126
						'path'    => $relativePath,
127
						'version' => $package->getVersion(), // Version of the class comes from the package - should we try to parse it?
128
					);
129
				}
130
			}
131
		}
132
		return $autoloads;
133
	}
134
135
	/**
136
	 * Take the autoloads array and return the classMap that contains the path and the version for each namespace.
137
	 *
138
	 * @param array      $autoloads Array of autoload settings defined defined by the packages.
139
	 * @param Filesystem $filesystem Filesystem class instance.
140
	 * @param string     $vendorPath Path to the vendor directory.
141
	 * @param string     $basePath Base Path.
142
	 *
143
	 * @return array $classMap
144
	 */
145
	private function getClassMap( array $autoloads, Filesystem $filesystem, $vendorPath, $basePath ) {
146
		$blacklist      = null; // not supported for now.
147
		$classmapString = '';
148
149
		// Scan the PSR-4 directories for class files, and add them to the class map.
150
		foreach ( $autoloads['psr-4'] as $namespace => $packages_info ) {
151
			foreach ( $packages_info as $package ) {
152
				$dir = $filesystem->normalizePath(
153
					$filesystem->isAbsolutePath( $package['path'] )
154
					? $package['path']
155
					: $basePath . '/' . $package['path']
156
				);
157
				$map = ClassMapGenerator::createMap( $dir, $blacklist, $this->io, $namespace );
158
159
				foreach ( $map as $class => $path ) {
160
					$classCode       = var_export( $class, true );
161
					$pathCode        = $this->getPathCode( $filesystem, $basePath, $vendorPath, $path );
162
					$versionCode     = var_export( $package['version'], true );
163
					$classmapString .= <<<CLASS_CODE
164
	$classCode => array(
165
		'version' => $versionCode,
166
		'path'    => $pathCode
167
	),
168
CLASS_CODE;
169
					$classmapString .= PHP_EOL;
170
				}
171
			}
172
		}
173
174
		return 'array( ' . PHP_EOL . $classmapString . ');' . PHP_EOL;
175
176
	}
177
178
	/**
179
	 * Generate the PHP that will be used in the autoload_classmap_package.php files.
180
	 *
181
	 * @param srting $classMap class map array string that is to be written out to the file.
182
	 *
183
	 * @return string
184
	 */
185
	private function getAutoloadClassmapPackagesFile( $classMap ) {
186
187
		return <<<INCLUDE_CLASSMAP
188
<?php
189
190
// This file `autoload_classmap_packages.php` was auto generated by automattic/jetpack-autoloader.
191
192
\$vendorDir = dirname(__DIR__);
193
194
return $classMap
195
196
INCLUDE_CLASSMAP;
197
	}
198
199
	/**
200
	 * Generate the PHP that will be used in the autoload_packages.php files.
201
	 *
202
	 * @param string $suffix  Unique suffix added to the jetpack_enqueue_packages function.
203
	 *
204
	 * @return string
205
	 */
206
	private function getAutoloadPackageFile( $suffix ) {
207
		$sourceLoader   = fopen( __DIR__ . '/autoload.php', 'r' );
208
		$file_contents  = stream_get_contents( $sourceLoader );
209
		$file_contents .= <<<INCLUDE_FILES
210
/**
211
 * Prepare all the classes for autoloading.
212
 */
213
function enqueue_packages_$suffix() {
214
	\$class_map = require_once dirname( __FILE__ ) . '/composer/autoload_classmap_package.php';
215
	foreach ( \$class_map as \$class_name => \$class_info ) {
216
		enqueue_package_class( \$class_name, \$class_info['version'], \$class_info['path'] );
217
	}
218
}
219
220
enqueue_packages_$suffix();
221
		
222
INCLUDE_FILES;
223
224
		return $file_contents;
225
	}
226
}
227