Completed
Push — master ( e44400...cbfd05 )
by Alexander
03:19
created

AbstractCommand::getPath()   C

Complexity

Conditions 7
Paths 10

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 0
loc 29
ccs 0
cts 17
cp 0
rs 6.7272
cc 7
eloc 15
nc 10
nop 0
crap 56
1
<?php
2
/**
3
 * This file is part of the SVN-Buddy library.
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 *
7
 * @copyright Alexander Obuhovich <[email protected]>
8
 * @link      https://github.com/console-helpers/svn-buddy
9
 */
10
11
namespace ConsoleHelpers\SVNBuddy\Command;
12
13
14
use ConsoleHelpers\ConsoleKit\Command\AbstractCommand as BaseCommand;
15
use ConsoleHelpers\SVNBuddy\Config\AbstractConfigSetting;
16
use ConsoleHelpers\ConsoleKit\Config\ConfigEditor;
17
use ConsoleHelpers\SVNBuddy\Repository\Connector\Connector;
18
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\RevisionLog;
19
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\RevisionLogFactory;
20
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Output\OutputInterface;
23
24
/**
25
 * Base command class.
26
 */
27
abstract class AbstractCommand extends BaseCommand
28
{
29
30
	/**
31
	 * Whatever "path" argument accepts repository urls.
32
	 *
33
	 * @var boolean
34
	 */
35
	protected $pathAcceptsUrl = false;
36
37
	/**
38
	 * Repository connector
39
	 *
40
	 * @var Connector
41
	 */
42
	protected $repositoryConnector;
43
44
	/**
45
	 * Working directory.
46
	 *
47
	 * @var string
48
	 */
49
	protected $workingDirectory = null;
50
51
	/**
52
	 * Revision logs by url
53
	 *
54
	 * @var RevisionLog[]
55
	 */
56
	private $_revisionLogs = array();
57
58
	/**
59
	 * Working copy paths.
60
	 *
61
	 * @var array
62
	 */
63
	private $_workingCopyPaths = array();
64
65
	/**
66
	 * Mapping between working copy paths and their urls.
67
	 *
68
	 * @var array
69
	 */
70
	private $_workingCopyUrlMapping = array();
71
72
	/**
73
	 * Mapping between path to working copy specified by user to one, that is actually used.
74
	 *
75
	 * @var array
76
	 */
77
	private $_resolvedPathMapping = array();
78
79
	/**
80
	 * Revision log factory.
81
	 *
82
	 * @var RevisionLogFactory
83
	 */
84
	private $_revisionLogFactory;
85
86
	/**
87
	 * Config editor.
88
	 *
89
	 * @var ConfigEditor
90
	 */
91
	private $_configEditor;
92
93
	/**
94
	 * {@inheritdoc}
95
	 */
96
	protected function initialize(InputInterface $input, OutputInterface $output)
97
	{
98
		$output->getFormatter()->setStyle('debug', new OutputFormatterStyle('white', 'magenta'));
99
100
		parent::initialize($input, $output);
101
	}
102
103
	/**
104
	 * Prepare dependencies.
105
	 *
106
	 * @return void
107
	 */
108
	protected function prepareDependencies()
109
	{
110
		parent::prepareDependencies();
111
112
		$container = $this->getContainer();
113
114
		$this->repositoryConnector = $container['repository_connector'];
115
		$this->_revisionLogFactory = $container['revision_log_factory'];
116
		$this->workingDirectory = $container['working_directory'];
117
		$this->_configEditor = $container['config_editor'];
118
	}
119
120
	/**
121
	 * Returns command setting value.
122
	 *
123
	 * @param string      $name         Name.
124
	 * @param string|null $command_name Command name to get settings from instead of current command.
125
	 *
126
	 * @return mixed
127
	 */
128
	protected function getSetting($name, $command_name = null)
129
	{
130
		return $this->_getConfigSetting($name, $command_name)->getValue();
131
	}
132
133
	/**
134
	 * Sets command setting value.
135
	 *
136
	 * @param string      $name         Name.
137
	 * @param mixed       $value        Value.
138
	 * @param string|null $command_name Command name to get settings from instead of current command.
139
	 *
140
	 * @return void
141
	 */
142
	protected function setSetting($name, $value, $command_name = null)
143
	{
144
		$this->_getConfigSetting($name, $command_name)->setValue($value);
145
	}
146
147
	/**
148
	 * Validates command setting usage.
149
	 *
150
	 * @param string      $name         Name.
151
	 * @param string|null $command_name Command name to get settings from instead of current command.
152
	 *
153
	 * @return AbstractConfigSetting
154
	 * @throws \LogicException When command don't have any config settings to provide.
155
	 * @throws \LogicException When config setting is not found.
156
	 */
157
	private function _getConfigSetting($name, $command_name = null)
158
	{
159
		// By default access own config settings.
160
		if ( !isset($command_name) ) {
161
			$command_name = $this->getName();
162
		}
163
164
		/** @var IConfigAwareCommand $command */
165
		$command = $this->getApplication()->get($command_name);
166
167
		if ( !($command instanceof IConfigAwareCommand) ) {
168
			throw new \LogicException('The "' . $command_name . '" command does not have any settings.');
169
		}
170
171
		foreach ( $command->getConfigSettings() as $config_setting ) {
172
			if ( $config_setting->getName() === $name ) {
173
				if ( $config_setting->isWithinScope(AbstractConfigSetting::SCOPE_WORKING_COPY) ) {
174
					$config_setting->setWorkingCopyUrl($this->getWorkingCopyUrl());
175
				}
176
177
				$config_setting->setEditor($this->_configEditor);
178
179
				return $config_setting;
180
			}
181
		}
182
183
		throw new \LogicException('The "' . $command_name . '" command doesn\'t have "' . $name . '" config setting.');
184
	}
185
186
	/**
187
	 * Prepare setting prefix.
188
	 *
189
	 * @param boolean $is_global Return global setting prefix.
190
	 *
191
	 * @return string
192
	 * @todo   Possibly not in use.
193
	 */
194
	protected function getConfigScope($is_global)
195
	{
196
		if ( $is_global ) {
197
			return 'global-settings.';
198
		}
199
200
		return 'path-settings[' . $this->getWorkingCopyUrl() . '].';
201
	}
202
203
	/**
204
	 * Returns revision log.
205
	 *
206
	 * @param string $repository_url Repository url.
207
	 *
208
	 * @return RevisionLog
209
	 */
210
	protected function getRevisionLog($repository_url)
211
	{
212
		if ( !isset($this->_revisionLogs[$repository_url]) ) {
213
			$this->_revisionLogs[$repository_url] = $this->_revisionLogFactory->getRevisionLog(
214
				$repository_url,
215
				$this->io
216
			);
217
		}
218
219
		return $this->_revisionLogs[$repository_url];
220
	}
221
222
	/**
223
	 * Transforms string into list.
224
	 *
225
	 * @param string $string    String.
226
	 * @param string $separator Separator.
227
	 *
228
	 * @return array
229
	 */
230
	protected function getList($string, $separator = ',')
231
	{
232
		return array_filter(array_map('trim', explode($separator, $string)));
233
	}
234
235
	/**
236
	 * Returns URL to the working copy.
237
	 *
238
	 * @return string
239
	 */
240
	protected function getWorkingCopyUrl()
241
	{
242
		$wc_path = $this->getWorkingCopyPath();
243
244
		if ( !isset($this->_workingCopyUrlMapping[$wc_path]) ) {
245
			$this->_workingCopyUrlMapping[$wc_path] = $this->repositoryConnector->getWorkingCopyUrl($wc_path);
246
		}
247
248
		return $this->_workingCopyUrlMapping[$wc_path];
249
	}
250
251
	/**
252
	 * Return working copy path.
253
	 *
254
	 * @return string
255
	 * @throws \RuntimeException When folder isn't a working copy.
256
	 */
257
	protected function getWorkingCopyPath()
258
	{
259
		$path = $this->getPath();
260
261
		if ( !in_array($path, $this->_workingCopyPaths) ) {
262
			if ( !$this->repositoryConnector->isUrl($path)
263
				&& !$this->repositoryConnector->isWorkingCopy($path)
264
			) {
265
				throw new \RuntimeException('The "' . $path . '" isn\'t a working copy.');
266
			}
267
268
			$this->_workingCopyPaths[] = $path;
269
		}
270
271
		return $path;
272
	}
273
274
	/**
275
	 * Returns all refs.
276
	 *
277
	 * @return array
278
	 */
279
	protected function getAllRefs()
280
	{
281
		$wc_url = $this->getWorkingCopyUrl();
282
		$revision_log = $this->getRevisionLog($wc_url);
283
284
		return $revision_log->find('refs', 'all_refs');
285
	}
286
287
	/**
288
	 * Return working copy path.
289
	 *
290
	 * @return string
291
	 * @throws \RuntimeException When url was given instead of path.
292
	 */
293
	protected function getPath()
294
	{
295
		// During auto-complete the IO isn't set.
296
		if ( !isset($this->io) ) {
297
			$path = '.';
298
		}
299
		else {
300
			$path = $this->io->getArgument('path');
301
		}
302
303
		if ( !isset($this->_resolvedPathMapping[$path]) ) {
304
			if ( !$this->repositoryConnector->isUrl($path) ) {
305
				if ( !file_exists($path) && file_exists(dirname($path)) ) {
306
					$path = dirname($path);
307
				}
308
309
				$this->_resolvedPathMapping[$path] = realpath($path);
310
			}
311
			else {
312
				if ( !$this->pathAcceptsUrl ) {
313
					throw new \RuntimeException('The "path" argument must be a working copy path and not URL.');
314
				}
315
316
				$this->_resolvedPathMapping[$path] = $this->repositoryConnector->removeCredentials($path);
317
			}
318
		}
319
320
		return $this->_resolvedPathMapping[$path];
321
	}
322
323
}
324