Completed
Push — add/changelog-tooling ( b30521...fa9ac3 )
by
unknown
1097:09 queued 1086:59
created

Config::changesDir()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase
2
/**
3
 * Configuration loader for the changelogger tool.
4
 *
5
 * @package automattic/jetpack-changelogger
6
 */
7
8
// phpcs:disable WordPress.NamingConventions.ValidFunctionName, WordPress.NamingConventions.ValidVariableName, WordPress.WP.AlternativeFunctions
9
10
namespace Automattic\Jetpack\Changelogger;
11
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
/**
15
 * Configuration loader for the changelogger tool.
16
 */
17
class Config {
18
19
	/**
20
	 * Default config settings.
21
	 *
22
	 * @var array
23
	 */
24
	private static $defaultConfig = array(
25
		'changes-dir' => 'changelog',
26
		'types'       => array(
27
			'security'   => 'Security',
28
			'added'      => 'Added',
29
			'changed'    => 'Changed',
30
			'deprecated' => 'Deprecated',
31
			'removed'    => 'Removed',
32
			'fixed'      => 'Fixed',
33
		),
34
		'versioning'  => 'semver',
35
	);
36
37
	/**
38
	 * Active config settings.
39
	 *
40
	 * @var array
41
	 */
42
	private static $config = array();
43
44
	/**
45
	 * Cached config settings.
46
	 *
47
	 * @var array
48
	 */
49
	private static $cache = array();
50
51
	/**
52
	 * Whether `load()` was called already.
53
	 *
54
	 * @var bool
55
	 */
56
	private static $loaded = false;
57
58
	/**
59
	 * OutputInterface.
60
	 *
61
	 * @var OutputInterface|null
62
	 */
63
	private static $out;
64
65
	/**
66
	 * Set the OutputInterface.
67
	 *
68
	 * @param OutputInterface $out OutputInterface.
69
	 */
70
	public static function setOutput( OutputInterface $out ) {
71
		self::$out = $out;
72
	}
73
74
	/**
75
	 * Load the configuration.
76
	 *
77
	 * @throws \LogicException If called before `setOutput()`.
78
	 * @throws \DomainException If the path to composer.json exists but can't be `realpath`-ed.
79
	 */
80
	private static function load() {
81
		if ( ! self::$out ) {
82
			throw new \LogicException( 'Must call Config::setOutput() before Config::load()' );
83
		}
84
		if ( self::$loaded ) {
85
			return;
86
		}
87
		self::$loaded = true;
88
89
		self::$config         = self::$defaultConfig;
90
		self::$config['base'] = getcwd();
91
92
		$composer = getenv( 'COMPOSER' );
93
		if ( $composer ) {
94
			$from = ' (as specified by the COMPOSER environment variable)'; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
95
		} else {
96
			$composer = 'composer.json';
97
			$from     = ''; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
98
		}
99
		if ( ! file_exists( $composer ) ) {
100
			self::$out->writeln( "<error>File {$composer}{$from} is not found.</>" );
101
			return;
102
		}
103
		$data = json_decode( file_get_contents( $composer ), true );
104
		if ( ! is_array( $data ) ) {
105
			self::$out->writeln( "<error>File {$composer}{$from} could not be parsed.</>" );
106
			return;
107
		}
108
109
		$dir = realpath( $composer );
110
		if ( false === $dir ) {
111
			throw new \DomainException( "Path $composer is not valid" ); // @codeCoverageIgnore
112
		}
113
		self::$config['base'] = dirname( $dir );
114
		if ( isset( $data['extra']['changelogger'] ) ) {
115
			self::$config = array_merge( self::$config, $data['extra']['changelogger'] );
116
		}
117
	}
118
119
	/**
120
	 * Get the base directory.
121
	 *
122
	 * @return string
123
	 */
124
	public static function base() {
125
		self::load();
126
		return self::$config['base'];
127
	}
128
129
	/**
130
	 * Get the changes directory.
131
	 *
132
	 * @return string
133
	 */
134
	public static function changesDir() {
135
		self::load();
136
		if ( ! isset( self::$cache['changes-dir'] ) ) {
137
			$dir = self::$config['changes-dir'];
138
			// Stupid Windows requires a regex.
139
			if ( ! preg_match( '#^(?:/|' . preg_quote( DIRECTORY_SEPARATOR, '#' ) . '|[a-zA-Z]:\\\\)#', $dir ) ) {
140
				$dir = self::base() . DIRECTORY_SEPARATOR . $dir;
141
			}
142
			self::$cache['changes-dir'] = $dir;
143
		}
144
		return self::$cache['changes-dir'];
145
	}
146
147
	/**
148
	 * Get verisoning method.
149
	 *
150
	 * @return Versioning
151
	 */
152
	public static function versioning() {
153
		self::load();
154
		if ( ! isset( self::$cache['versioning'] ) ) {
155
			$class = __NAMESPACE . '\\Versioning\\' . ucfirst( self::$config['versioning'] );
156
			if ( ! class_exists( $class ) ) {
157
				self::$out->writeln( '<warning>Unknown versioning method "' . self::$config['versioning'] . '". Using "semver".</>' );
158
				$class = __NAMESPACE . '\\Versioning\\Semver';
159
			}
160
			self::$cache['versioning'] = new $class( self::$out );
161
		}
162
		return self::$cache['versioning'];
163
	}
164
165
	/**
166
	 * Get change types.
167
	 *
168
	 * @return array
169
	 */
170
	public static function types() {
171
		self::load();
172
		if ( ! isset( self::$cache['types'] ) ) {
173
			self::$cache['types'] = array();
174
			foreach ( self::$config['types'] as $k => $v ) {
175
				self::$cache['types'][ strtolower( $k ) ] = $v;
176
			}
177
		}
178
		return self::$cache['types'];
179
	}
180
181
}
182