Passed
Push — master ( 85fd9a...e9971f )
by Alexander
02:00
created

FunctionDataCollector   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 221
Duplicated Lines 0 %

Test Coverage

Coverage 94.51%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 89
c 1
b 0
f 0
dl 0
loc 221
ccs 86
cts 91
cp 0.9451
rs 10
wmc 21

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getStatistics() 0 8 1
B processFunctionParameters() 0 74 9
B collectData() 0 51 6
A deleteData() 0 4 2
A deleteFunctions() 0 33 3
1
<?php
2
/**
3
 * This file is part of the Code-Insight 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/code-insight
9
 */
10
11
namespace ConsoleHelpers\CodeInsight\KnowledgeBase\DataCollector;
12
13
14
use Go\ParserReflection\ReflectionFileNamespace;
15
16
class FunctionDataCollector extends AbstractDataCollector
17
{
18
19
	/**
20
	 * Collect data from a namespace.
21
	 *
22
	 * @param integer                 $file_id   File id.
23
	 * @param ReflectionFileNamespace $namespace Namespace.
24
	 *
25
	 * @return void
26
	 */
27 4
	public function collectData($file_id, ReflectionFileNamespace $namespace)
28
	{
29 4
		$sql = 'SELECT Name, Id
30
				FROM Functions
31
				WHERE FileId = :file_id';
32 4
		$old_functions = $this->db->fetchPairs($sql, array(
33 4
			'file_id' => $file_id,
34
		));
35
36 4
		$insert_sql = '	INSERT INTO Functions (FileId, Name, ParameterCount, RequiredParameterCount, IsVariadic, ReturnsReference, HasReturnType, ReturnType)
37
						VALUES (:file_id, :name, :parameter_count, :required_parameter_count, :is_variadic, :returns_reference, :has_return_type, :return_type)';
38 4
		$update_sql = '	UPDATE Functions
39
						SET	ParameterCount = :parameter_count,
40
							RequiredParameterCount = :required_parameter_count,
41
							IsVariadic = :is_variadic,
42
							ReturnsReference = :returns_reference,
43
							ReturnType = :return_type,
44
							HasReturnType = :has_return_type
45
						WHERE FileId = :file_id AND Name = :name';
46
47 4
		$new_functions = array();
48
49 4
		foreach ( $namespace->getFunctions() as $function ) {
50 4
			$function_name = $function->getName();
51 4
			$new_functions[] = $function_name;
52
53 4
			$has_return_type = $function->hasReturnType();
54 4
			$return_type = $has_return_type ? (string)$function->getReturnType() : null;
55
56 4
			$this->db->perform(
57 4
				isset($old_functions[$function_name]) ? $update_sql : $insert_sql,
58
				array(
59 4
					'file_id' => $file_id,
60 4
					'name' => $function_name,
61 4
					'parameter_count' => $function->getNumberOfParameters(),
62 4
					'required_parameter_count' => $function->getNumberOfRequiredParameters(),
63 4
					'is_variadic' => (int)$function->isVariadic(),
64 4
					'returns_reference' => (int)$function->returnsReference(),
65 4
					'has_return_type' => (int)$has_return_type,
66 4
					'return_type' => $return_type,
67
				)
68
			);
69
70 4
			$function_id = isset($old_functions[$function_name]) ? $old_functions[$function_name] : $this->db->lastInsertId();
71 4
			$this->processFunctionParameters($function_id, $function);
72
		}
73
74 4
		$delete_functions = array_diff(array_keys($old_functions), $new_functions);
75
76 4
		if ( $delete_functions ) {
77
			$this->deleteFunctions($file_id, $delete_functions);
78
		}
79 4
	}
80
81
	/**
82
	 * Deletes functions.
83
	 *
84
	 * @param integer $file_id   File ID.
85
	 * @param array   $functions Methods.
86
	 *
87
	 * @return void
88
	 */
89 1
	protected function deleteFunctions($file_id, array $functions)
90
	{
91 1
		if ( $functions ) {
92
			// Delete only given functions.
93
			$sql = 'SELECT Id
94
					FROM Functions
95
					WHERE FileId = :file_id AND Name IN (:names)';
96
			$function_ids = $this->db->fetchCol($sql, array(
97
				'file_id' => $file_id,
98
				'names' => $functions,
99
			));
100
		}
101
		else {
102
			// Delete all functions in a file.
103 1
			$sql = 'SELECT Id
104
					FROM Functions
105
					WHERE FileId = :file_id';
106 1
			$function_ids = $this->db->fetchCol($sql, array(
107 1
				'file_id' => $file_id,
108
			));
109
		}
110
111
		// @codeCoverageIgnoreStart
112
		if ( !$function_ids ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $function_ids 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...
113
			return;
114
		}
115
		// @codeCoverageIgnoreEnd
116
117 1
		$sql = 'DELETE FROM Functions WHERE Id IN (:function_ids)';
118 1
		$this->db->perform($sql, array('function_ids' => $function_ids));
119
120 1
		$sql = 'DELETE FROM FunctionParameters WHERE FunctionId IN (:function_ids)';
121 1
		$this->db->perform($sql, array('function_ids' => $function_ids));
122 1
	}
123
124
	/**
125
	 * Processes function parameters.
126
	 *
127
	 * @param integer             $function_id Function ID.
128
	 * @param \ReflectionFunction $function    Function.
129
	 *
130
	 * @return void
131
	 */
132 4
	protected function processFunctionParameters($function_id, \ReflectionFunction $function)
133
	{
134 4
		$sql = 'SELECT Name
135
				FROM FunctionParameters
136
				WHERE FunctionId = :function_id';
137 4
		$old_parameters = $this->db->fetchCol($sql, array(
138 4
			'function_id' => $function_id,
139
		));
140
141 4
		$insert_sql = '	INSERT INTO FunctionParameters (FunctionId, Name, Position, TypeClass, HasType, TypeName, AllowsNull, IsArray, IsCallable, IsOptional, IsVariadic, CanBePassedByValue, IsPassedByReference, HasDefaultValue, DefaultValue, DefaultConstant)
142
						VALUES (:function_id, :name, :position, :type_class, :has_type, :type_name, :allows_null, :is_array, :is_callable, :is_optional, :is_variadic, :can_be_passed_by_value, :is_passed_by_reference, :has_default_value, :default_value, :default_constant)';
143 4
		$update_sql = '	UPDATE FunctionParameters
144
						SET	Position = :position,
145
							TypeClass = :type_class,
146
							HasType = :has_type,
147
							TypeName = :type_name,
148
							AllowsNull = :allows_null,
149
							IsArray = :is_array,
150
							IsCallable = :is_callable,
151
							IsOptional = :is_optional,
152
							IsVariadic = :is_variadic,
153
							CanBePassedByValue = :can_be_passed_by_value,
154
							IsPassedByReference = :is_passed_by_reference,
155
							HasDefaultValue = :has_default_value,
156
							DefaultValue = :default_value,
157
							DefaultConstant = :default_constant
158
						WHERE FunctionId = :function_id AND Name = :name';
159
160 4
		$new_parameters = array();
161
162 4
		foreach ( $function->getParameters() as $position => $parameter ) {
163 4
			$parameter_name = $parameter->getName();
164 4
			$new_parameters[] = $parameter_name;
165
166 4
			$type_class = $parameter->getClass();
167 4
			$type_class = $type_class ? $type_class->getName() : null;
168
169 4
			$has_type = $parameter->hasType();
170 4
			$type_name = $has_type ? (string)$parameter->getType() : null;
171
172 4
			$has_default_value = $parameter->isDefaultValueAvailable();
173 4
			$default_value_is_constant = $has_default_value ? $parameter->isDefaultValueConstant() : false;
174
175 4
			$this->db->perform(
176 4
				in_array($parameter_name, $old_parameters) ? $update_sql : $insert_sql,
177
				array(
178 4
					'function_id' => $function_id,
179 4
					'name' => $parameter_name,
180 4
					'position' => $position,
181 4
					'type_class' => $type_class,
182 4
					'has_type' => (int)$has_type,
183 4
					'type_name' => $type_name,
184 4
					'allows_null' => (int)$parameter->allowsNull(),
185 4
					'is_array' => (int)$parameter->isArray(),
186 4
					'is_callable' => (int)$parameter->isCallable(),
187 4
					'is_optional' => (int)$parameter->isOptional(),
188 4
					'is_variadic' => (int)$parameter->isVariadic(),
189 4
					'can_be_passed_by_value' => (int)$parameter->canBePassedByValue(),
190 4
					'is_passed_by_reference' => (int)$parameter->isPassedByReference(),
191 4
					'has_default_value' => (int)$has_default_value,
192 4
					'default_value' => $has_default_value ? json_encode($parameter->getDefaultValue()) : null,
193 4
					'default_constant' => $default_value_is_constant ? $parameter->getDefaultValueConstantName() : null,
194
				)
195
			);
196
		}
197
198 4
		$delete_parameters = array_diff($old_parameters, $new_parameters);
199
200 4
		if ( $delete_parameters ) {
201 1
			$sql = 'DELETE FROM FunctionParameters
202
					WHERE FunctionId = :function_id AND Name IN (:names)';
203 1
			$this->db->perform($sql, array(
204 1
				'function_id' => $function_id,
205 1
				'names' => $delete_parameters,
206
			));
207
		}
208 4
	}
209
210
	/**
211
	 * Delete previously collected data for a files.
212
	 *
213
	 * @param array $file_ids File IDs.
214
	 *
215
	 * @return void
216
	 */
217 1
	public function deleteData(array $file_ids)
218
	{
219 1
		foreach ( $file_ids as $file_id ) {
220 1
			$this->deleteFunctions($file_id, array());
221
		}
222 1
	}
223
224
	/**
225
	 * Returns statistics about the code.
226
	 *
227
	 * @return array
228
	 */
229 1
	public function getStatistics()
230
	{
231 1
		$sql = 'SELECT COUNT(*)
232
				FROM Functions';
233 1
		$function_count = $this->db->fetchValue($sql);
234
235
		return array(
236 1
			'Functions' => $function_count,
237
		);
238
	}
239
240
}
241