Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.48% covered (warning)
85.48%
53 / 62
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
AutoloadProcessor
85.48% covered (warning)
85.48%
53 / 62
75.00% covered (warning)
75.00%
3 / 4
30.40
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 processClassmap
76.32% covered (warning)
76.32%
29 / 38
0.00% covered (danger)
0.00%
0 / 1
22.30
 processPsr4Packages
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
 processFiles
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * Autoload Processor.
4 *
5 * @package automattic/jetpack-autoloader
6 */
7
8namespace Automattic\Jetpack\Autoloader;
9
10/**
11 * Class AutoloadProcessor.
12 */
13class AutoloadProcessor {
14
15    /**
16     * A callable for scanning a directory for all of its classes.
17     *
18     * @var callable
19     */
20    private $classmapScanner;
21
22    /**
23     * A callable for transforming a path into one to be used in code.
24     *
25     * @var callable
26     */
27    private $pathCodeTransformer;
28
29    /**
30     * The constructor.
31     *
32     * @param callable $classmapScanner A callable for scanning a directory for all of its classes.
33     * @param callable $pathCodeTransformer A callable for transforming a path into one to be used in code.
34     */
35    public function __construct( $classmapScanner, $pathCodeTransformer ) {
36        $this->classmapScanner     = $classmapScanner;
37        $this->pathCodeTransformer = $pathCodeTransformer;
38    }
39
40    /**
41     * Processes the classmap autoloads into a relative path format including the version for each file.
42     *
43     * @param array $autoloads The autoloads we are processing.
44     * @param bool  $scanPsrPackages Whether or not PSR packages should be converted to a classmap.
45     *
46     * @return array|null $processed
47     * @phan-param array{classmap:?array{path:string,version:string}[],psr-4:?array<string,array{path:string,version:string}[]>,psr-0:?array<string,array{path:string,version:string}[]>} $autoloads
48     */
49    public function processClassmap( $autoloads, $scanPsrPackages ) {
50        // We can't scan PSR packages if we don't actually have any.
51        if ( empty( $autoloads['psr-4'] ) ) {
52            $scanPsrPackages = false;
53        }
54
55        if ( empty( $autoloads['classmap'] ) && ! $scanPsrPackages ) {
56            return null;
57        }
58
59        $excludedClasses = null;
60        if ( ! empty( $autoloads['exclude-from-classmap'] ) ) {
61            $excludedClasses = '{(' . implode( '|', $autoloads['exclude-from-classmap'] ) . ')}';
62        }
63
64        $processed = array();
65
66        if ( $scanPsrPackages ) {
67            foreach ( $autoloads['psr-4'] as $namespace => $sources ) {
68                $namespace = empty( $namespace ) ? null : $namespace;
69
70                foreach ( $sources as $source ) {
71                    $classmap = call_user_func( $this->classmapScanner, $source['path'], $excludedClasses, $namespace );
72
73                    foreach ( $classmap as $class => $path ) {
74                        $processed[ $class ] = array(
75                            'version' => $source['version'],
76                            'path'    => call_user_func( $this->pathCodeTransformer, $path ),
77                        );
78                    }
79                }
80            }
81        }
82
83        /*
84         * PSR-0 namespaces are converted to classmaps for both optimized and unoptimized autoloaders because any new
85         * development should use classmap or PSR-4 autoloading.
86         */
87        if ( ! empty( $autoloads['psr-0'] ) ) {
88            foreach ( $autoloads['psr-0'] as $namespace => $sources ) {
89                $namespace = empty( $namespace ) ? null : $namespace;
90
91                foreach ( $sources as $source ) {
92                    $classmap = call_user_func( $this->classmapScanner, $source['path'], $excludedClasses, $namespace );
93                    foreach ( $classmap as $class => $path ) {
94                        $processed[ $class ] = array(
95                            'version' => $source['version'],
96                            'path'    => call_user_func( $this->pathCodeTransformer, $path ),
97                        );
98                    }
99                }
100            }
101        }
102
103        if ( ! empty( $autoloads['classmap'] ) ) {
104            foreach ( $autoloads['classmap'] as $package ) {
105                $classmap = call_user_func( $this->classmapScanner, $package['path'], $excludedClasses, null );
106
107                foreach ( $classmap as $class => $path ) {
108                    $processed[ $class ] = array(
109                        'version' => $package['version'],
110                        'path'    => call_user_func( $this->pathCodeTransformer, $path ),
111                    );
112                }
113            }
114        }
115
116        ksort( $processed );
117
118        return $processed;
119    }
120
121    /**
122     * Processes the PSR-4 autoloads into a relative path format including the version for each file.
123     *
124     * @param array $autoloads The autoloads we are processing.
125     * @param bool  $scanPsrPackages Whether or not PSR packages should be converted to a classmap.
126     *
127     * @return array|null $processed
128     */
129    public function processPsr4Packages( $autoloads, $scanPsrPackages ) {
130        if ( $scanPsrPackages || empty( $autoloads['psr-4'] ) ) {
131            return null;
132        }
133
134        $processed = array();
135
136        foreach ( $autoloads['psr-4'] as $namespace => $packages ) {
137            $namespace = empty( $namespace ) ? null : $namespace;
138            $paths     = array();
139
140            foreach ( $packages as $package ) {
141                $paths[] = call_user_func( $this->pathCodeTransformer, $package['path'] );
142            }
143
144            $processed[ $namespace ] = array(
145                'version' => $package['version'],
146                'path'    => $paths,
147            );
148        }
149
150        return $processed;
151    }
152
153    /**
154     * Processes the file autoloads into a relative format including the version for each file.
155     *
156     * @param array $autoloads The autoloads we are processing.
157     *
158     * @return array|null $processed
159     */
160    public function processFiles( $autoloads ) {
161        if ( empty( $autoloads['files'] ) ) {
162            return null;
163        }
164
165        $processed = array();
166
167        foreach ( $autoloads['files'] as $file_id => $package ) {
168            $processed[ $file_id ] = array(
169                'version' => $package['version'],
170                'path'    => call_user_func( $this->pathCodeTransformer, $package['path'] ),
171            );
172        }
173
174        return $processed;
175    }
176}