Completed
Push — master ( 5e49cf...3d1f7c )
by Alexander
02:26
created

Command::_getCacheKey()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 3
nop 0
crap 4
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\Repository\Connector;
12
13
14
use ConsoleHelpers\ConsoleKit\ConsoleIO;
15
use ConsoleHelpers\SVNBuddy\Cache\CacheManager;
16
use ConsoleHelpers\SVNBuddy\Exception\RepositoryCommandException;
17
use ConsoleHelpers\SVNBuddy\Process\IProcessFactory;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Process\Exception\ProcessFailedException;
20
use Symfony\Component\Process\Process;
21
22
class Command
23
{
24
25
	/**
26
	 * Process factory.
27
	 *
28
	 * @var IProcessFactory
29
	 */
30
	private $_processFactory;
31
32
	/**
33
	 * Command line.
34
	 *
35
	 * @var string
36
	 */
37
	private $_commandLine;
38
39
	/**
40
	 * Console IO.
41
	 *
42
	 * @var ConsoleIO
43
	 */
44
	private $_io;
45
46
	/**
47
	 * Cache manager.
48
	 *
49
	 * @var CacheManager
50
	 */
51
	private $_cacheManager;
52
53
	/**
54
	 * Cache duration.
55
	 *
56
	 * @var mixed
57
	 */
58
	private $_cacheDuration;
59
60
	/**
61
	 * Text that when different from cached will invalidate the cache.
62
	 *
63
	 * @var string
64
	 */
65
	private $_cacheInvalidator;
66
67
	/**
68
	 * Creates a command instance.
69
	 *
70
	 * @param string          $command_line    Command line.
71
	 * @param ConsoleIO       $io              Console IO.
72
	 * @param CacheManager    $cache_manager   Cache manager.
73
	 * @param IProcessFactory $process_factory Process factory.
74
	 */
75 90
	public function __construct(
76
		$command_line,
77
		ConsoleIO $io,
1 ignored issue
show
Comprehensibility introduced by
Avoid variables with short names like $io. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
78
		CacheManager $cache_manager,
79
		IProcessFactory $process_factory
80
	) {
81 90
		$this->_commandLine = $command_line;
82 90
		$this->_io = $io;
83 90
		$this->_cacheManager = $cache_manager;
84 90
		$this->_processFactory = $process_factory;
85 90
	}
86
87
	/**
88
	 * Set cache duration.
89
	 *
90
	 * @param string $invalidator Invalidator.
91
	 *
92
	 * @return self
93
	 */
94 16
	public function setCacheInvalidator($invalidator)
95
	{
96 16
		$this->_cacheInvalidator = $invalidator;
97
98 16
		return $this;
99
	}
100
101
	/**
102
	 * Set cache duration.
103
	 *
104
	 * @param mixed $duration Duration (seconds if numeric OR whatever "strtotime" accepts).
105
	 *
106
	 * @return self
107
	 */
108 52
	public function setCacheDuration($duration)
109
	{
110 52
		$this->_cacheDuration = $duration;
111
112 52
		return $this;
113
	}
114
115
	/**
116
	 * Runs the command.
117
	 *
118
	 * @param callable|null $callback Callback.
119
	 *
120
	 * @return string|\SimpleXMLElement
121
	 */
122 90
	public function run($callback = null)
123
	{
124 90
		$cache_key = $this->_getCacheKey();
125
126 90
		if ( $cache_key ) {
127 56
			$output = $this->_cacheManager->getCache($cache_key, $this->_cacheInvalidator, $this->_cacheDuration);
128
129 56
			if ( isset($output) && is_callable($callback) ) {
130 6
				call_user_func($callback, Process::OUT, $output);
131 6
			}
132 56
		}
133
134 90
		if ( !isset($output) ) {
135 61
			$output = $this->_doRun($callback);
136
137 58
			if ( $cache_key ) {
138 25
				$this->_cacheManager->setCache($cache_key, $output, $this->_cacheInvalidator, $this->_cacheDuration);
139 25
			}
140 58
		}
141
142 87
		if ( strpos($this->_commandLine, '--xml') !== false ) {
143 40
			return simplexml_load_string($output);
144
		}
145
146 48
		return $output;
147
	}
148
149
	/**
150
	 * Returns cache key for a command.
151
	 *
152
	 * @return string
153
	 */
154 90
	private function _getCacheKey()
155
	{
156 90
		if ( $this->_cacheInvalidator || $this->_cacheDuration ) {
157 56
			if ( preg_match(Connector::URL_REGEXP, $this->_commandLine, $regs) ) {
158 23
				return $regs[2] . $regs[3] . $regs[4] . '/command:' . $this->_commandLine;
159
			}
160
161 33
			return 'misc/command:' . $this->_commandLine;
162
		}
163
164 35
		return '';
165
	}
166
167
	/**
168
	 * Runs the command.
169
	 *
170
	 * @param callable|null $callback Callback.
171
	 *
172
	 * @return string
173
	 * @throws RepositoryCommandException When command execution failed.
174
	 */
175 61
	private function _doRun($callback = null)
176
	{
177 61
		$process = $this->_processFactory->createProcess($this->_commandLine, 1200);
178
179
		try {
180 61
			$start = microtime(true);
181 61
			$process->mustRun($callback);
182
183 58
			if ( $this->_io->isVerbose() ) {
184 1
				$runtime = sprintf('%01.2f', microtime(true) - $start);
185 1
				$this->_io->writeln(
186 1
					array('', '<debug>[svn, ' . round($runtime, 2) . 's]: ' . $this->_commandLine . '</debug>')
187 1
				);
188 1
			}
189
190 58
			$output = (string)$process->getOutput();
191
192 58
			if ( $this->_io->isDebug() ) {
193 1
				$this->_io->writeln($output, OutputInterface::OUTPUT_RAW);
194 1
			}
195
196 58
			return $output;
197
		}
198 4
		catch ( ProcessFailedException $e ) {
199 1
			throw new RepositoryCommandException(
200 1
				$this->_commandLine,
201 1
				$process->getErrorOutput()
202 1
			);
203
		}
204
	}
205
206
	/**
207
	 * Runs an svn command and displays output in real time.
208
	 *
209
	 * @param array $replacements Replacements for the output.
210
	 *
211
	 * @return string
212
	 */
213 3
	public function runLive(array $replacements = array())
214
	{
215 3
		return $this->run($this->_createLiveOutputCallback($replacements));
216
	}
217
218
	/**
219
	 * Creates "live output" callback.
220
	 *
221
	 * @param array $replacements Replacements for the output.
222
	 *
223
	 * @return callable
224
	 */
225 3
	private function _createLiveOutputCallback(array $replacements = array())
226
	{
227 3
		$io = $this->_io;
1 ignored issue
show
Comprehensibility introduced by
Avoid variables with short names like $io. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
228
229 3
		$replace_froms = array_keys($replacements);
230 3
		$replace_tos = array_values($replacements);
231
232 3
		return function ($type, $buffer) use ($io, $replace_froms, $replace_tos) {
233 2
			foreach ( $replace_froms as $index => $replace_from ) {
234 2
				$replace_to = $replace_tos[$index];
235
236 2
				if ( substr($replace_from, 0, 1) === '/' && substr($replace_from, -1, 1) === '/' ) {
237 2
					$buffer = preg_replace($replace_from, $replace_to, $buffer);
238 2
				}
239
				else {
240 2
					$buffer = str_replace($replace_from, $replace_to, $buffer);
241
				}
242 2
			}
243
244 2
			if ( $type === Process::ERR ) {
245 1
				$buffer = '<error>ERR:</error> ' . $buffer;
246 1
			}
247
248 2
			$io->write($buffer);
249 3
		};
250
	}
251
252
}
253