Completed
Push — master ( 9971c7...a2516e )
by Peter
19:50
created

FileWalker::scan()   D

Complexity

Conditions 14
Paths 17

Size

Total Lines 89
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 89
ccs 0
cts 67
cp 0
rs 4.9516
cc 14
eloc 37
nc 17
nop 1
crap 210

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This software package is licensed under AGPL, Commercial license.
5
 *
6
 * @package maslosoft/addendum
7
 * @licence AGPL, Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]> (Meta container, further improvements, bugfixes)
9
 * @copyright Copyright (c) Maslosoft (Meta container, further improvements, bugfixes)
10
 * @copyright Copyright (c) Jan Suchal (Original version, builder, parser)
11
 * @link http://maslosoft.com/addendum/ - maslosoft addendum
12
 * @link https://code.google.com/p/addendum/ - original addendum project
13
 */
14
15
namespace Maslosoft\Addendum\Utilities;
16
17
use DirectoryIterator;
18
19
/**
20
 * FileWalker
21
 *
22
 * This walks recursivelly on symlinks too, with loop detection.
23
 * Will process only files starting with Capital Letters.
24
 *
25
 * Will skip files with identical content.
26
 *
27
 * This class is meant to replace AnnotationUtility::fileWalker method.
28
 *
29
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
30
 */
31
class FileWalker
32
{
33
34
	/**
35
	 * Pahts to scan
36
	 * @var string[]
37
	 */
38
	private $paths = [];
39
40
	/**
41
	 * Patterns to match for annotations
42
	 * @var string[]
43
	 */
44
	private $patterns = [];
45
46
	/**
47
	 * Callback to execute on file
48
	 * @var callback
49
	 */
50
	private $callback;
51
52
	/**
53
	 * List of visited real paths
54
	 * @var bool[]
55
	 */
56
	private $visited = [];
57
58
	/**
59
	 * Wether sum was parsed
60
	 * @var bool[]
61
	 */
62
	private $sum = [];
63
64
	public function __construct($annotations, $callback, $paths)
65
	{
66
		$this->paths = $paths;
67
		$this->callback = $callback;
68
		$this->patterns = [];
69
70
		foreach ($annotations as $annotation)
71
		{
72
			$annotation = preg_replace('~^@~', '', $annotation);
73
			$this->patterns[] = sprintf('~@%s~', $annotation);
74
		}
75
	}
76
77
	public function walk()
78
	{
79
		foreach ($this->paths as $path)
80
		{
81
			$this->scan($path);
82
		}
83
	}
84
85
	private function scan($path)
86
	{
87
		// Check if should be visited
88
		$real = realpath($path);
89
		if (!empty($this->visited[$real]))
90
		{
91
			return;
92
		}
93
		// Mark real path as visited
94
		$this->visited[$real] = true;
95
96
		// Scan real path
97
		$iterator = new DirectoryIterator($real);
98
		foreach ($iterator as $info)
99
		{
100
			if ($info->isDot())
101
			{
102
				continue;
103
			}
104
105
			// Recurse, loop prevention check is on top of this function
106
			if ($info->isDir())
107
			{
108
				$this->scan($info->getPathname());
109
				continue;
110
			}
111
112
			$file = $info->getPathname();
113
114
			// Check if should be processed
115
			if (!empty($this->visited[$file]))
116
			{
117
				continue;
118
			}
119
120
			// Mark as processed
121
			$this->visited[$file] = true;
122
123
			// Only php
124
			if (!preg_match('~^.+\.php$~i', $file))
125
			{
126
				continue;
127
			}
128
129
			// Only starting with capital letter
130
			if (!preg_match('~^[A-Z]~', $info->getBasename()))
131
			{
132
				continue;
133
			}
134
135
			$parse = false;
136
137
			if (is_readable($file))
138
			{
139
				$contents = file_get_contents($file);
140
			}
141
			else
142
			{
143
				// TODO Log this
144
				continue;
145
			}
146
147
			// Check for file checksum
148
			$sum = md5($contents);
149
			// Check if should be processed
150
			if (!empty($this->sum[$sum]))
151
			{
152
				continue;
153
			}
154
			$this->sum[$sum] = true;
155
156
			foreach ($this->patterns as $pattern)
157
			{
158
				if ($parse)
159
				{
160
					continue;
161
				}
162
				if (preg_match($pattern, $contents))
163
				{
164
					$parse = true;
165
				}
166
			}
167
			if (!$parse)
168
			{
169
				continue;
170
			}
171
			call_user_func($this->callback, $file, $contents);
172
		}
173
	}
174
175
}
176