BinaryData   B
last analyzed

Complexity

Total Complexity 49

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 49
lcom 1
cbo 0
dl 0
loc 244
rs 8.5454
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 3
C __toString() 0 56 21
A getUUID() 0 3 1
A getList() 0 9 2
A getMap() 0 10 2
A getText() 0 3 1
A getBigInt() 0 9 2
A getVarInt() 0 10 4
A getTimestamp() 0 5 2
A getBlob() 0 3 1
A getBoolean() 0 3 2
A getDecimal() 0 12 2
A getDouble() 0 3 1
A getFloat() 0 3 1
A getInet() 0 3 1
A getInt() 0 3 1
A bcdechex() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like BinaryData often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BinaryData, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace evseevnn\Cassandra\Protocol;
3
use evseevnn\Cassandra\Enum\DataTypeEnum;
4
5
class BinaryData {
6
7
	/**
8
	 * @var int
9
	 */
10
	private $type;
11
12
	/**
13
	 * @var mixed
14
	 */
15
	private $value;
16
17
	/**
18
	 * @var array
19
	 */
20
	private $keyType;
21
22
	/**
23
	 * @var array
24
	 */
25
	private $valueType;
26
27
	/**
28
	 * @param array $dataType
29
	 * @param mixed $value
30
	 */
31
	public function __construct(array $dataType, $value) {
32
		$this->type = $dataType['type'];
33
		$this->value = $value;
34
		if (isset($dataType['key'])) $this->keyType = $dataType['key'];
35
		if (isset($dataType['value'])) $this->valueType = $dataType['value'];
36
	}
37
38
	/**
39
	 * @return string
40
	 */
41
	public function __toString() {
42
		switch($this->type) {
43
			case DataTypeEnum::CUSTOM:
44
			case DataTypeEnum::BLOB:
45
				return $this->getBlob();
46
47
			case DataTypeEnum::TIMESTAMP:
48
				return $this->getTimestamp();
49
50
			case DataTypeEnum::COUNTER:
51
			case DataTypeEnum::BIGINT:
52
				return $this->getBigInt();
53
54
			case DataTypeEnum::VARINT:
55
				return $this->getVarInt();
56
57
			case DataTypeEnum::BOOLEAN:
58
				return $this->getBoolean();
59
60
			case DataTypeEnum::COLLECTION_SET:
61
			case DataTypeEnum::COLLECTION_LIST:
62
				return $this->getList();
63
64
			case DataTypeEnum::COLLECTION_MAP:
65
				return $this->getMap();
66
67
			case DataTypeEnum::DECIMAL:
68
				return $this->getDecimal();
69
70
			case DataTypeEnum::DOUBLE:
71
				return $this->getDouble();
72
73
			case DataTypeEnum::FLOAT:
74
				return $this->getFloat();
75
76
			case DataTypeEnum::INET:
77
				return $this->getInet();
78
79
			case DataTypeEnum::INT:
80
				return $this->getInt();
81
82
			case DataTypeEnum::ASCII:
83
			case DataTypeEnum::VARCHAR:
84
			case DataTypeEnum::TEXT:
85
				return $this->getText();
86
87
			case DataTypeEnum::TIMEUUID:
88
			case DataTypeEnum::UUID:
89
				return $this->getUUID();
90
91
			default:
92
				trigger_error('Unknown type.');
93
		}
94
95
		return '';
96
	}
97
98
	/**
99
	 * Return binary uuid
100
	 * @return string
101
	 */
102
	private function getUUID() {
103
		return pack('H*', str_replace('-', '', $this->value));
104
	}
105
106
	/**
107
	 * @return string
108
	 */
109
	private function getList() {
110
		$data = pack('n', count($this->value));
111
		foreach($this->value as $item) {
112
			$itemPacked = new BinaryData($this->valueType, $item);
113
			$data .= pack('n', strlen($itemPacked)) . $itemPacked;
114
		}
115
116
		return $data;
117
	}
118
119
	/**
120
	 * @return string
121
	 */
122
	private function getMap() {
123
		$data = pack('n', count($this->value));
124
		foreach($this->value as $key => $item) {
125
			$keyPacked = new BinaryData($this->keyType, $key);
126
			$data .= pack('n', strlen($keyPacked)) . $keyPacked;
127
			$itemPacked = new BinaryData($this->valueType, $item);
128
			$data .= pack('n', strlen($itemPacked)) . $itemPacked;
129
		}
130
		return $data;
131
	}
132
133
	/**
134
	 * @return string
135
	 */
136
	private function getText() {
137
		return (string)$this->value;
138
	}
139
140
	/**
141
	 * @return string
142
	 */
143
	private function getBigInt() {
144
		if (!$value = intval($this->value))
145
				trigger_error('BigInt value ' . $value . ' not an int', E_USER_ERROR);
146
		$highMap = 0xffffffff00000000;
147
		$lowMap = 0x00000000ffffffff;
148
		$higher = ($value & $highMap) >>32;
149
		$lower = $value & $lowMap;
150
		return pack('NN', $higher, $lower);
151
	}
152
153
	/**
154
	 * @return string
155
	 */
156
	private function getVarInt() {
157
		if (!(float)$this->value && !(int)$this->value)
158
				trigger_error('VarInt value ' . $this->value . ' not an int or float', E_USER_ERROR);
159
160
		$hex = $this->bcdechex($this->value);
161
		if (strlen($hex) % 2 != 0)
162
			$hex = '0'.$hex;
163
164
		return pack('H*', $hex);
165
	}
166
167
	/**
168
	 * @return string
169
	 */
170
	private function getTimestamp() {
171
		// for use timestamp = 10 digits. happy for time()!
172
		if (strlen($this->value) === 10) $this->value *= 1000;
173
		return $this->getBigInt();
174
	}
175
176
	/**
177
	 * @return string
178
	 */
179
	private function getBlob() {
180
		return pack('N', strlen($this->value)) . $this->value;
181
	}
182
183
	/**
184
	 * @return string
185
	 */
186
	private function getBoolean() {
187
		return $this->value ? chr(1) : chr(0);
188
	}
189
190
	/**
191
	 * @return string
192
	 */
193
	private function getDecimal() {
194
		$scaleLen = strlen(strstr($this->value, ','));
195
		if ($scaleLen) {
196
			$scaleLen -= 1;
197
			$this->value = str_replace(',', '', $this->value);
198
		}
199
		$highMap = 0xffffffff00000000;
200
		$lowMap = 0x00000000ffffffff;
201
		$higher = ($this->value & $highMap) >>32;
202
		$lower = $this->value & $lowMap;
203
		return pack('NNN', $scaleLen, $higher, $lower);
204
	}
205
206
	/**
207
	 * @return string
208
	 */
209
	private function getDouble() {
210
		return strrev(pack('d', $this->value));
211
	}
212
213
	/**
214
	 * @return string
215
	 */
216
	private function getFloat() {
217
		return strrev(pack('f', $this->value));
218
	}
219
220
	/**
221
	 * @return string
222
	 */
223
	private function getInet() {
224
		return inet_pton($this->value);
225
	}
226
227
	/**
228
	 * @return string
229
	 */
230
	private function getInt() {
231
		return pack('N', $this->value);
232
	}
233
234
	/**
235
	 *
236
	 * @param string $dec
237
	 * @return string
238
	 */
239
	private function bcdechex($dec) {
240
		$last = bcmod($dec, 16);
241
		$remain = bcdiv(bcsub($dec, $last), 16);
242
243
		if ($remain == 0)
244
			return dechex($last);
245
246
		return $this->bcdechex($remain) . dechex($last);
247
	}
248
}
249