Failed Conditions
Push — master ( 1523fb...3c2402 )
by Alexander
03:05
created

PathsPlugin::processProject()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 35
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 35
ccs 23
cts 23
cp 1
rs 8.439
cc 5
eloc 20
nc 4
nop 2
crap 5
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\Database\DatabaseCache;
16
use ConsoleHelpers\SVNBuddy\Repository\Connector\Connector;
17
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\PathCollisionDetector;
18
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\RepositoryFiller;
19
use ConsoleHelpers\SVNBuddy\Repository\RevisionLog\RevisionLog;
20
21
class PathsPlugin extends AbstractRepositoryCollectorPlugin
22
{
23
24
	const TYPE_NEW = 'new';
25
26
	const TYPE_EXISTING = 'existing';
27
28
	const STATISTIC_PATH_ADDED = 'path_added';
29
30
	const STATISTIC_PATH_FOUND = 'path_found';
31
32
	const STATISTIC_PROJECT_ADDED = 'project_added';
33
34
	const STATISTIC_PROJECT_FOUND = 'project_found';
35
36
	const STATISTIC_PROJECT_COLLISION_FOUND = 'project_collision_found';
37
38
	const STATISTIC_REF_ADDED = 'ref_added';
39
40
	const STATISTIC_REF_FOUND = 'ref_found';
41
42
	const STATISTIC_COMMIT_ADDED_TO_PROJECT = 'commit_added_to_project';
43
44
	const STATISTIC_COMMIT_ADDED_TO_REF = 'commit_added_to_ref';
45
46
	const STATISTIC_EMPTY_COMMIT = 'empty_commit';
47
48
	/**
49
	 * Database cache.
50
	 *
51
	 * @var DatabaseCache
52
	 */
53
	private $_databaseCache;
54
55
	/**
56
	 * Projects.
57
	 *
58
	 * @var array
59
	 */
60
	private $_projects = array(
61
		self::TYPE_NEW => array(),
62
		self::TYPE_EXISTING => array(),
63
	);
64
65
	/**
66
	 * Refs.
67
	 *
68
	 * @var array
69
	 */
70
	private $_refs = array();
71
72
	/**
73
	 * Repository connector.
74
	 *
75
	 * @var Connector
76
	 */
77
	private $_repositoryConnector;
78
79
	/**
80
	 * Path collision detector.
81
	 *
82
	 * @var PathCollisionDetector
83
	 */
84
	private $_pathCollisionDetector;
85
86
	/**
87
	 * Create paths revision log plugin.
88
	 *
89
	 * @param ExtendedPdoInterface  $database                Database.
90
	 * @param RepositoryFiller      $repository_filler       Repository filler.
91
	 * @param DatabaseCache         $database_cache          Database cache.
92
	 * @param Connector             $repository_connector    Repository connector.
93
	 * @param PathCollisionDetector $path_collision_detector Path collision detector.
94
	 */
95 37
	public function __construct(
96
		ExtendedPdoInterface $database,
97
		RepositoryFiller $repository_filler,
98
		DatabaseCache $database_cache,
99
		Connector $repository_connector,
100
		PathCollisionDetector $path_collision_detector
101
	) {
102 37
		parent::__construct($database, $repository_filler);
103
104 37
		$this->_databaseCache = $database_cache;
105 37
		$this->_repositoryConnector = $repository_connector;
106 37
		$this->_pathCollisionDetector = $path_collision_detector;
107
108 37
		$this->initDatabaseCache();
109 37
	}
110
111
	/**
112
	 * Hook, that is called before "RevisionLog::refresh" method call.
113
	 *
114
	 * @return void
115
	 */
116 37
	public function whenDatabaseReady()
117
	{
118
		$sql = 'SELECT Path
119 37
				FROM Projects';
120 37
		$project_paths = $this->database->fetchCol($sql);
121
122 37
		$this->_pathCollisionDetector->addPaths($project_paths);
123 37
	}
124
125
	/**
126
	 * Initializes database cache.
127
	 *
128
	 * @return void
129
	 */
130 37
	protected function initDatabaseCache()
131
	{
132 37
		$this->_databaseCache->cacheTable('Projects');
133 37
		$this->_databaseCache->cacheTable('ProjectRefs');
134 37
		$this->_databaseCache->cacheTable('Paths');
135 37
	}
136
137
	/**
138
	 * Returns plugin name.
139
	 *
140
	 * @return string
141
	 */
142 26
	public function getName()
143
	{
144 26
		return 'paths';
145
	}
146
147
	/**
148
	 * Returns revision query flags.
149
	 *
150
	 * @return array
151
	 */
152 1
	public function getRevisionQueryFlags()
153
	{
154 1
		return array(RevisionLog::FLAG_VERBOSE);
155
	}
156
157
	/**
158
	 * Defines parsing statistic types.
159
	 *
160
	 * @return array
161
	 */
162 37
	public function defineStatisticTypes()
163
	{
164
		return array(
165 37
			self::STATISTIC_PATH_ADDED,
166 37
			self::STATISTIC_PATH_FOUND,
167 37
			self::STATISTIC_PROJECT_ADDED,
168 37
			self::STATISTIC_PROJECT_FOUND,
169 37
			self::STATISTIC_PROJECT_COLLISION_FOUND,
170 37
			self::STATISTIC_REF_ADDED,
171 37
			self::STATISTIC_REF_FOUND,
172 37
			self::STATISTIC_COMMIT_ADDED_TO_PROJECT,
173 37
			self::STATISTIC_COMMIT_ADDED_TO_REF,
174 37
			self::STATISTIC_EMPTY_COMMIT,
175 37
		);
176
	}
177
178
	/**
179
	 * Does actual parsing.
180
	 *
181
	 * @param integer           $revision  Revision.
182
	 * @param \SimpleXMLElement $log_entry Log Entry.
183
	 *
184
	 * @return void
185
	 */
186 19
	protected function doParse($revision, \SimpleXMLElement $log_entry)
187
	{
188
		// Reset cached info after previous revision processing.
189 19
		$this->_projects = array(
190 19
			self::TYPE_NEW => array(),
191 19
			self::TYPE_EXISTING => array(),
192
		);
193 19
		$this->_refs = array();
194
195
		// This is empty revision.
196 19
		if ( !isset($log_entry->paths) ) {
197 1
			$this->recordStatistic(self::STATISTIC_EMPTY_COMMIT);
198
199 1
			return;
200
		}
201
202 18
		foreach ( $this->sortPaths($log_entry->paths) as $path_node ) {
203 18
			$kind = (string)$path_node['kind'];
204 18
			$action = (string)$path_node['action'];
205 18
			$path = $this->adaptPathToKind((string)$path_node, $kind);
206
207 18
			if ( $path_node['copyfrom-rev'] !== null ) {
208 1
				$copy_revision = (int)$path_node['copyfrom-rev'];
209 1
				$copy_path = $this->adaptPathToKind((string)$path_node['copyfrom-path'], $kind);
210 1
				$copy_path_id = $this->processPath($copy_path, $copy_revision, '', false);
211 1
			}
212
213 18
			$this->repositoryFiller->addPathToCommit(
214 18
				$revision,
215 18
				$action,
216 18
				$kind,
217 18
				$this->processPath($path, $revision, $action),
218 18
				isset($copy_revision) ? $copy_revision : null,
219 18
				isset($copy_path_id) ? $copy_path_id : null
220 18
			);
221 18
		}
222
223 18
		foreach ( array_keys($this->_projects[self::TYPE_EXISTING]) as $project_id ) {
224 1
			$this->addCommitToProject($revision, $project_id);
225 18
		}
226
227 18
		foreach ( $this->_projects[self::TYPE_NEW] as $project_id => $project_path ) {
228 5
			$associated_revisions = $this->addMissingCommitsToProject($project_id, $project_path);
229
230 5
			if ( !in_array($revision, $associated_revisions) ) {
231 3
				$this->addCommitToProject($revision, $project_id);
232 3
			}
233 18
		}
234
235 18
		foreach ( array_keys($this->_refs) as $ref_id ) {
236 5
			$this->addCommitToRef($revision, $ref_id);
237 18
		}
238 18
	}
239
240
	/**
241
	 * Sorts paths to move parent folders above their sub-folders.
242
	 *
243
	 * @param \SimpleXMLElement $paths Paths.
244
	 *
245
	 * @return \SimpleXMLElement[]
246
	 */
247 18
	protected function sortPaths(\SimpleXMLElement $paths)
248
	{
249 18
		$sorted_paths = array();
250
251 18
		foreach ( $paths->path as $path_node ) {
252 18
			$sorted_paths[(string)$path_node] = $path_node;
253 18
		}
254
255 18
		ksort($sorted_paths, defined('SORT_NATURAL') ? SORT_NATURAL : SORT_STRING);
256
257 18
		return $sorted_paths;
258
	}
259
260
	/**
261
	 * Processes path.
262
	 *
263
	 * @param string  $path     Path.
264
	 * @param integer $revision Revision.
265
	 * @param string  $action   Action.
266
	 * @param boolean $is_usage This is usage.
267
	 *
268
	 * @return integer
269
	 */
270 18
	protected function processPath($path, $revision, $action, $is_usage = true)
271
	{
272 18
		$path_hash = $this->repositoryFiller->getPathChecksum($path);
273
274
		$sql = 'SELECT Id, ProjectPath, RefName, RevisionAdded, RevisionDeleted, RevisionLastSeen
275
				FROM Paths
276 18
				WHERE PathHash = :path_hash';
277 18
		$path_data = $this->_databaseCache->getFromCache(
278 18
			'Paths',
279 18
			$path_hash,
280 18
			$sql,
281 18
			array('path_hash' => $path_hash)
282 18
		);
283
284 18
		if ( $path_data !== false ) {
285 8
			if ( $action ) {
286 7
				$fields_hash = $this->repositoryFiller->getPathTouchFields($action, $revision, $path_data);
0 ignored issues
show
Bug introduced by
It seems like $path_data defined by $this->_databaseCache->g...h_hash' => $path_hash)) on line 277 can also be of type boolean; however, ConsoleHelpers\SVNBuddy\...r::getPathTouchFields() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
287
288 7
				if ( $fields_hash ) {
289 7
					$touched_paths = $this->repositoryFiller->touchPath($path, $revision, $fields_hash);
290
291 7
					foreach ( $touched_paths as $touched_path_hash => $touched_path_fields_hash ) {
292 7
						if ( $this->_databaseCache->getFromCache('Paths', $touched_path_hash) !== false ) {
293 7
							$this->_databaseCache->setIntoCache('Paths', $touched_path_hash, $touched_path_fields_hash);
294 7
						}
295 7
					}
296 7
				}
297 7
			}
298
299 8
			if ( $path_data['ProjectPath'] && $path_data['RefName'] ) {
300 1
				$project_id = $this->processProject($path_data['ProjectPath'], $is_usage);
301 1
				$this->processRef($project_id, $path_data['RefName'], $is_usage);
302 1
			}
303
304 8
			$this->recordStatistic(self::STATISTIC_PATH_FOUND);
305
306 8
			return $path_data['Id'];
307
		}
308
309 18
		$ref = $this->_repositoryConnector->getRefByPath($path);
310
311 18
		if ( $ref !== false ) {
312 6
			$project_path = substr($path, 0, strpos($path, $ref));
313
314 6
			if ( $this->_pathCollisionDetector->isCollision($project_path) ) {
315 2
				$project_path = $ref = '';
316 2
				$this->recordStatistic(self::STATISTIC_PROJECT_COLLISION_FOUND);
317 2
			}
318 6
		}
319
		else {
320 14
			$project_path = '';
321
		}
322
323 18
		$path_id = $this->repositoryFiller->addPath($path, (string)$ref, $project_path, $revision);
324 18
		$this->_databaseCache->setIntoCache('Paths', $path_hash, array(
325 18
			'Id' => $path_id,
326 18
			'ProjectPath' => $project_path,
327 18
			'RefName' => (string)$ref,
328 18
			'RevisionAdded' => $revision,
329 18
			'RevisionDeleted' => null,
330 18
			'RevisionLastSeen' => $revision,
331 18
		));
332
333 18
		if ( $project_path && $ref ) {
334 5
			$project_id = $this->processProject($project_path, $is_usage);
335 5
			$this->processRef($project_id, $ref, $is_usage);
336 5
		}
337
338 18
		$this->recordStatistic(self::STATISTIC_PATH_ADDED);
339
340 18
		return $path_id;
341
	}
342
343
	/**
344
	 * Adapts path to kind.
345
	 *
346
	 * @param string $path Path.
347
	 * @param string $kind Kind.
348
	 *
349
	 * @return string
350
	 */
351 18
	protected function adaptPathToKind($path, $kind)
352
	{
353 18
		if ( $kind === 'dir' ) {
354 12
			$path .= '/';
355 12
		}
356
357 18
		return $path;
358
	}
359
360
	/**
361
	 * Processes project.
362
	 *
363
	 * @param string  $project_path Project path.
364
	 * @param boolean $is_usage     This is usage.
365
	 *
366
	 * @return integer
367
	 */
368 5
	protected function processProject($project_path, $is_usage = true)
369
	{
370
		$sql = 'SELECT Id
371
				FROM Projects
372 5
				WHERE Path = :path';
373 5
		$project_data = $this->_databaseCache->getFromCache(
374 5
			'Projects',
375 5
			$project_path,
376 5
			$sql,
377 5
			array('path' => $project_path)
378 5
		);
379
380 5
		if ( $project_data !== false ) {
381 2
			$project_id = $project_data['Id'];
382
383
			// Don't consider project both new & existing (e.g. when single commit adds several branches).
384 2
			if ( $is_usage && !isset($this->_projects[self::TYPE_NEW][$project_id]) ) {
385 1
				$this->_projects[self::TYPE_EXISTING][$project_id] = $project_path;
386 1
				$this->recordStatistic(self::STATISTIC_PROJECT_FOUND);
387 1
			}
388
389 2
			return $project_id;
390
		}
391
392 5
		$project_id = $this->repositoryFiller->addProject($project_path);
393 5
		$this->_databaseCache->setIntoCache('Projects', $project_path, array('Id' => $project_id));
394 5
		$this->_pathCollisionDetector->addPaths(array($project_path));
395
396 5
		if ( $is_usage ) {
397 5
			$this->_projects[self::TYPE_NEW][$project_id] = $project_path;
398 5
			$this->recordStatistic(self::STATISTIC_PROJECT_ADDED);
399 5
		}
400
401 5
		return $project_id;
402
	}
403
404
	/**
405
	 * Processes ref.
406
	 *
407
	 * @param integer $project_id Project ID.
408
	 * @param string  $ref        Ref.
409
	 * @param boolean $is_usage   This is usage.
410
	 *
411
	 * @return integer
412
	 */
413 5
	protected function processRef($project_id, $ref, $is_usage = true)
414
	{
415 5
		$cache_key = $project_id . ':' . $ref;
416
417
		$sql = 'SELECT Id
418
				FROM ProjectRefs
419 5
				WHERE ProjectId = :project_id AND Name = :ref';
420 5
		$ref_data = $this->_databaseCache->getFromCache(
421 5
			'ProjectRefs',
422 5
			$cache_key,
423 5
			$sql,
424 5
			array('project_id' => $project_id, 'ref' => $ref)
425 5
		);
426
427 5
		if ( $ref_data !== false ) {
428 1
			$ref_id = $ref_data['Id'];
429
430 1
			if ( $is_usage ) {
431 1
				$this->_refs[$ref_id] = true;
432 1
			}
433
434 1
			$this->recordStatistic(self::STATISTIC_REF_FOUND);
435
436 1
			return $ref_id;
437
		}
438
439 5
		$ref_id = $this->repositoryFiller->addRefToProject($ref, $project_id);
440 5
		$this->_databaseCache->setIntoCache('ProjectRefs', $cache_key, array('Id' => $ref_id));
441
442 5
		if ( $is_usage ) {
443 5
			$this->_refs[$ref_id] = true;
444 5
		}
445
446 5
		$this->recordStatistic(self::STATISTIC_REF_ADDED);
447
448 5
		return $ref_id;
449
	}
450
451
	/**
452
	 * Retroactively map paths/commits to project, where path doesn't contain ref.
453
	 *
454
	 * @param integer $project_id   Project ID.
455
	 * @param string  $project_path Project path.
456
	 *
457
	 * @return array
458
	 */
459 5
	protected function addMissingCommitsToProject($project_id, $project_path)
460
	{
461
		$sql = "SELECT Id
462
				FROM Paths
463 5
				WHERE ProjectPath = '' AND Path LIKE :path_matcher";
464 5
		$paths_without_project = $this->database->fetchCol($sql, array('path_matcher' => $project_path . '%'));
465
466 5
		if ( !$paths_without_project ) {
467 3
			return array();
468
		}
469
470 2
		$this->repositoryFiller->movePathsIntoProject($paths_without_project, $project_path);
471
472
		$sql = 'SELECT Revision
473
				FROM CommitPaths
474 2
				WHERE PathId IN (:path_ids)';
475 2
		$commit_revisions = $this->database->fetchCol($sql, array('path_ids' => $paths_without_project));
476
477 2
		foreach ( array_unique($commit_revisions) as $commit_revision ) {
478 2
			$this->addCommitToProject($commit_revision, $project_id);
479 2
		}
480
481 2
		return $commit_revisions;
482
	}
483
484
	/**
485
	 * Associates revision with project.
486
	 *
487
	 * @param integer $revision   Revision.
488
	 * @param integer $project_id Project.
489
	 *
490
	 * @return void
491
	 */
492 5
	protected function addCommitToProject($revision, $project_id)
493
	{
494 5
		$this->repositoryFiller->addCommitToProject($revision, $project_id);
495 5
		$this->recordStatistic(self::STATISTIC_COMMIT_ADDED_TO_PROJECT);
496 5
	}
497
498
	/**
499
	 * Associates revision with ref.
500
	 *
501
	 * @param integer $revision Revision.
502
	 * @param integer $ref_id   Ref.
503
	 *
504
	 * @return void
505
	 */
506 5
	protected function addCommitToRef($revision, $ref_id)
507
	{
508 5
		$this->repositoryFiller->addCommitToRef($revision, $ref_id);
509 5
		$this->recordStatistic(self::STATISTIC_COMMIT_ADDED_TO_REF);
510 5
	}
511
512
	/**
513
	 * Find revisions by collected data.
514
	 *
515
	 * @param array       $criteria     Criteria.
516
	 * @param string|null $project_path Project path.
517
	 *
518
	 * @return array
519
	 */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
520 10
	public function find(array $criteria, $project_path)
521
	{
522 10
		if ( !$criteria ) {
523 1
			return array();
524
		}
525
526 9
		$project_id = $this->getProject($project_path);
527
528 8
		if ( reset($criteria) === '' ) {
529
			// Include revisions from all paths.
530
			$sql = 'SELECT cpa.Revision
531
					FROM CommitPaths cpa
532
					JOIN CommitProjects cpr ON cpr.Revision = cpa.Revision
533 1
					WHERE cpr.ProjectId = :project_id';
534 1
			$path_revisions = array_flip($this->database->fetchCol($sql, array('project_id' => $project_id)));
535 1
		}
536
		else {
537
			// Include revisions from given sub-path only.
538 7
			$path_revisions = array();
539
540 7
			foreach ( $criteria as $criterion ) {
541 7
				if ( strpos($criterion, ':') !== false ) {
542 3
					list ($field, $value) = explode(':', $criterion, 2);
543
544 3
					if ( $field === 'action' ) {
545
						$sql = 'SELECT cpa.Revision
546
								FROM CommitPaths cpa
547
								JOIN CommitProjects cpr ON cpr.Revision = cpa.Revision
548 2
								WHERE cpr.ProjectId = :project_id AND cpa.Action LIKE :action';
549 2
						$tmp_revisions = $this->database->fetchCol($sql, array(
550 2
							'project_id' => $project_id,
551 2
							'action' => $value,
552 2
						));
553 2
					}
554 2
					elseif ( $field === 'kind' ) {
555
						$sql = 'SELECT cpa.Revision
556
								FROM CommitPaths cpa
557
								JOIN CommitProjects cpr ON cpr.Revision = cpa.Revision
558 1
								WHERE cpr.ProjectId = :project_id AND cpa.Kind LIKE :kind';
559 1
						$tmp_revisions = $this->database->fetchCol($sql, array(
560 1
							'project_id' => $project_id,
561 1
							'kind' => $value,
562 1
						));
563 1
					}
564
					else {
565 1
						$error_msg = 'Searching by "%s" is not supported by "%s" plugin.';
566 1
						throw new \InvalidArgumentException(sprintf($error_msg, $field, $this->getName()));
567
					}
568 2
				}
569
				else {
570 4
					$path = $criterion;
571
572 4
					if ( substr($path, -1, 1) === '/' ) {
573
						// Folder given > search also in it's sub-folders.
574
						$sql = 'SELECT cpa.Revision
575
							FROM CommitPaths cpa
576
							JOIN Paths p ON p.Id = cpa.PathId
577
							JOIN CommitProjects cpr ON cpr.Revision = cpa.Revision
578 2
							WHERE cpr.ProjectId = :project_id AND p.Path LIKE :path';
579 2
						$tmp_revisions = $this->database->fetchCol($sql, array(
580 2
							'project_id' => $project_id,
581 2
							'path' => $path . '%',
582 2
						));
583 2
					}
584
					else {
585
						// File given > search for that file specifically.
586
						$sql = 'SELECT cpa.Revision
587
							FROM CommitPaths cpa
588
							JOIN Paths p ON p.Id = cpa.PathId
589
							JOIN CommitProjects cpr ON cpr.Revision = cpa.Revision
590 2
							WHERE cpr.ProjectId = :project_id AND p.PathHash = :path_hash';
591 2
						$tmp_revisions = $this->database->fetchCol($sql, array(
592 2
							'project_id' => $project_id,
593 2
							'path_hash' => $this->repositoryFiller->getPathChecksum($path),
594 2
						));
595
					}
596
				}
597
598 6
				foreach ( $tmp_revisions as $revision ) {
599 5
					$path_revisions[$revision] = true;
600 6
				}
601 6
			}
602
		}
603
604 7
		$path_revisions = array_keys($path_revisions);
605 7
		sort($path_revisions, SORT_NUMERIC);
606
607 7
		return $path_revisions;
608
	}
609
610
	/**
611
	 * Returns information about revisions.
612
	 *
613
	 * @param array $revisions Revisions.
614
	 *
615
	 * @return array
616
	 */
617 2
	public function getRevisionsData(array $revisions)
618
	{
619 2
		$results = array();
620
621
		$sql = 'SELECT cp.Revision, p1.Path, cp.Kind, cp.Action, p2.Path AS CopyPath, cp.CopyRevision
622
				FROM CommitPaths cp
623
				JOIN Paths p1 ON p1.Id = cp.PathId
624
				LEFT JOIN Paths p2 ON p2.Id = cp.CopyPathId
625 2
				WHERE cp.Revision IN (:revision_ids)';
626 2
		$revisions_data = $this->database->fetchAll($sql, array('revision_ids' => $revisions));
627
628 2
		foreach ( $revisions_data as $revision_data ) {
629 1
			$revision = $revision_data['Revision'];
630
631 1
			if ( !isset($results[$revision]) ) {
632 1
				$results[$revision] = array();
633 1
			}
634
635 1
			$results[$revision][] = array(
636 1
				'path' => $revision_data['Path'],
637 1
				'kind' => $revision_data['Kind'],
638 1
				'action' => $revision_data['Action'],
639 1
				'copyfrom-path' => $revision_data['CopyPath'],
640 1
				'copyfrom-rev' => $revision_data['CopyRevision'],
641
			);
642 2
		}
643
644 2
		$this->assertNoMissingRevisions($revisions, $results);
645
646 1
		return $results;
647
	}
648
649
	/**
650
	 * Frees consumed memory.
651
	 *
652
	 * @return void
653
	 *
654
	 * @codeCoverageIgnore
655
	 */
656
	protected function freeMemoryManually()
657
	{
658
		parent::freeMemoryManually();
659
660
		$this->_databaseCache->clear();
661
	}
662
663
}
664