Passed
Push — master ( 0c53b5...2c1757 )
by Alexander
11:19
created

AbstractPlugin::getRawRevisionsData()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 9.9332
cc 4
nc 4
nop 4
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\RevisionLog\Plugin;
12
13
14
use Aura\Sql\ExtendedPdoInterface;
15
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\RepositoryFiller;
16
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\RevisionLog;
17
18
abstract class AbstractPlugin implements IPlugin
19
{
20
21
	/**
22
	 * Database.
23
	 *
24
	 * @var ExtendedPdoInterface
25
	 */
26
	protected $database;
27
28
	/**
29
	 * Repository filler.
30
	 *
31
	 * @var RepositoryFiller
32
	 */
33
	protected $repositoryFiller;
34
35
	/**
36
	 * Revision log.
37
	 *
38
	 * @var RevisionLog
39
	 */
40
	protected $revisionLog;
41
42
	/**
43
	 * Parsing statistics.
44
	 *
45
	 * @var array
46
	 */
47
	private $_statistics = array();
48
49
	/**
50
	 * Creates plugin instance.
51
	 *
52
	 * @param ExtendedPdoInterface $database          Database.
53
	 * @param RepositoryFiller     $repository_filler Repository filler.
54
	 */
55 130
	public function __construct(ExtendedPdoInterface $database, RepositoryFiller $repository_filler)
56
	{
57 130
		$this->database = $database;
58 130
		$this->repositoryFiller = $repository_filler;
59
60 130
		$this->_resetParsingStatistics();
61
	}
62
63
	/**
64
	 * Resets parsing statistics.
65
	 *
66
	 * @return void
67
	 */
68 130
	private function _resetParsingStatistics()
69
	{
70 130
		$this->_statistics = array();
71
72 130
		foreach ( $this->defineStatisticTypes() as $parsing_statistic_type ) {
73 119
			$this->_statistics[$parsing_statistic_type] = 0;
74
		}
75
	}
76
77
	/**
78
	 * Returns raw information about revisions.
79
	 *
80
	 * @param string  $sql                  SQL.
81
	 * @param string  $revisions_param_name Revisions param name.
82
	 * @param array   $revisions            Revisions.
83
	 * @param boolean $assoc                Use first column as returned array key.
84
	 *
85
	 * @return array
86
	 */
87 8
	protected function getRawRevisionsData($sql, $revisions_param_name, array $revisions, $assoc = false)
88
	{
89
		// Several queries on a smaller revision set appear to be much faster, then one query for all revisions.
90 8
		$revisions_data = array();
91
92 8
		if ( $assoc ) {
93 2
			foreach ( array_chunk($revisions, 500) as $revisions_chunk ) {
94 2
				$revisions_data += $this->database->fetchAssoc($sql, array($revisions_param_name => $revisions_chunk));
95
			}
96
97 2
			return $revisions_data;
98
		}
99
100 6
		foreach ( array_chunk($revisions, 500) as $revisions_chunk ) {
101 6
			$revisions_data = array_merge(
102 6
				$revisions_data,
103 6
				$this->database->fetchAll($sql, array($revisions_param_name => $revisions_chunk))
104 6
			);
105
		}
106
107 6
		return $revisions_data;
108
	}
109
110
	/**
111
	 * Hook, that is called before "RevisionLog::refresh" method call.
112
	 *
113
	 * @return void
114
	 */
115 85
	public function whenDatabaseReady()
116
	{
117
118 85
	}
119
120
	/**
121
	 * Records parsing statistics.
122
	 *
123
	 * @param string  $type   Type.
124
	 * @param integer $to_add Number to add.
125
	 *
126
	 * @return void
127
	 */
128 35
	protected function recordStatistic($type, $to_add = 1)
129
	{
130 35
		$this->_statistics[$type] += $to_add;
131
	}
132
133
	/**
134
	 * Returns parsing statistics.
135
	 *
136
	 * @return array
137
	 */
138 38
	public function getStatistics()
139
	{
140 38
		return $this->_statistics;
141
	}
142
143
	/**
144
	 * Adds results for missing revisions.
145
	 *
146
	 * @param array $revisions Revisions.
147
	 * @param array $results   Results.
148
	 *
149
	 * @return array
150
	 */
151 4
	protected function addMissingResults(array $revisions, array $results)
152
	{
153 4
		foreach ( $this->_getMissingRevisions($revisions, $results) as $missing_revision ) {
154 4
			$results[$missing_revision] = array();
155
		}
156
157 4
		return $results;
158
	}
159
160
	/**
161
	 * Adds results for missing revisions.
162
	 *
163
	 * @param array $revisions Revisions.
164
	 * @param array $results   Results.
165
	 *
166
	 * @return void
167
	 * @throws \InvalidArgumentException When some revisions are missing in results.
168
	 */
169 4
	protected function assertNoMissingRevisions(array $revisions, array $results)
170
	{
171 4
		$missing_revisions = $this->_getMissingRevisions($revisions, $results);
172
173 4
		if ( !$missing_revisions ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $missing_revisions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
174 2
			return;
175
		}
176
177 2
		throw new \InvalidArgumentException(sprintf(
178 2
			'Revision(-s) "%s" not found by "%s" plugin.',
179 2
			implode('", "', $missing_revisions),
180 2
			$this->getName()
181 2
		));
182
	}
183
184
	/**
185
	 * Returns revisions, that are missing in results.
186
	 *
187
	 * @param array $revisions Revisions.
188
	 * @param array $results   Results.
189
	 *
190
	 * @return array
191
	 */
192 8
	private function _getMissingRevisions(array $revisions, array $results)
193
	{
194 8
		return array_diff($revisions, array_keys($results));
195
	}
196
197
	/**
198
	 * Returns last revision processed by plugin.
199
	 *
200
	 * @return integer
201
	 */
202 57
	public function getLastRevision()
203
	{
204 57
		$sql = 'SELECT LastRevision
205
				FROM PluginData
206 57
				WHERE Name = :name';
207 57
		$last_revision = $this->database->fetchValue($sql, array('name' => $this->getName()));
208
209 57
		return $last_revision !== false ? $last_revision : 0;
210
	}
211
212
	/**
213
	 * Sets last revision processed by plugin.
214
	 *
215
	 * @param integer $last_revision Last revision.
216
	 *
217
	 * @return void
218
	 */
219 38
	protected function setLastRevision($last_revision)
220
	{
221 38
		$sql = 'REPLACE INTO PluginData (Name, LastRevision)
222 38
				VALUES (:name, :last_revision)';
223 38
		$this->database->perform($sql, array('name' => $this->getName(), 'last_revision' => $last_revision));
224
	}
225
226
	/**
227
	 * Finds project by path.
228
	 *
229
	 * @param string $path Path.
230
	 *
231
	 * @return integer
232
	 * @throws \InvalidArgumentException When project can't be found.
233
	 */
234 39
	protected function getProject($path)
235
	{
236 39
		$sql = 'SELECT Id
237
				FROM Projects
238 39
				WHERE Path = :path';
239 39
		$project_id = $this->database->fetchValue($sql, array('path' => $path));
240
241 39
		if ( $project_id === false ) {
242 5
			throw new \InvalidArgumentException('The project with "' . $path . '" path not found.');
243
		}
244
245 34
		return $project_id;
246
	}
247
248
	/**
249
	 * Automatically free memory, when >200MB is used.
250
	 *
251
	 * @return void
252
	 *
253
	 * @codeCoverageIgnore
254
	 */
255
	protected function freeMemoryAutomatically()
256
	{
257
		$memory_usage = memory_get_usage();
258
259
		if ( $memory_usage > 200 * 1024 * 1024 ) {
260
			$this->freeMemoryManually();
261
		}
262
	}
263
264
	/**
265
	 * Frees consumed memory manually.
266
	 *
267
	 * @return void
268
	 *
269
	 * @codeCoverageIgnore
270
	 */
271
	protected function freeMemoryManually()
272
	{
273
		$profiler = $this->database->getProfiler();
274
275
		if ( is_object($profiler) && $profiler->isActive() ) {
276
			$profiler->resetProfiles();
0 ignored issues
show
Bug introduced by
The method resetProfiles() does not exist on Aura\Sql\Profiler\ProfilerInterface. It seems like you code against a sub-type of Aura\Sql\Profiler\ProfilerInterface such as ConsoleHelpers\SVNBuddy\Database\StatementProfiler. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

276
			$profiler->/** @scrutinizer ignore-call */ 
277
              resetProfiles();
Loading history...
277
		}
278
	}
279
280
	/**
281
	 * Sets reference to revision log.
282
	 *
283
	 * @param RevisionLog $revision_log Revision log.
284
	 *
285
	 * @return void
286
	 */
287 4
	public function setRevisionLog(RevisionLog $revision_log)
288
	{
289 4
		$this->revisionLog = $revision_log;
290
	}
291
292
}
293