| Total Complexity | 65 |
| Total Lines | 349 |
| Duplicated Lines | 0 % |
| Changes | 6 | ||
| Bugs | 2 | Features | 0 |
Complex classes like Api 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.
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 Api, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 19 | class Api extends BaseApi |
||
| 20 | { |
||
| 21 | /** |
||
| 22 | * 一次性获取到包含了 serialNumber (原did)的设备列表. |
||
| 23 | * |
||
| 24 | * @return array|mixed |
||
| 25 | */ |
||
| 26 | public function devicesList() |
||
| 57 | } |
||
| 58 | } |
||
| 59 | |||
| 60 | /** |
||
| 61 | * 按照名称获取属性. |
||
| 62 | * |
||
| 63 | * @param $did |
||
| 64 | * @param $type |
||
| 65 | * @param $data | $data = ['brightness', 'on'] |
||
| 66 | * |
||
| 67 | * @throws ApiErrorException |
||
| 68 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 69 | * |
||
| 70 | * @return array|bool|mixed |
||
| 71 | */ |
||
| 72 | public function getPropertyGraceful($did, $type, $data) |
||
| 73 | { |
||
| 74 | $propertyData = [ |
||
| 75 | $did => [ |
||
| 76 | 'type' => $type, |
||
| 77 | 'data' => $data, |
||
| 78 | ], |
||
| 79 | ]; |
||
| 80 | |||
| 81 | return $this->getPropertiesGraceful($propertyData); |
||
| 82 | } |
||
| 83 | |||
| 84 | /** |
||
| 85 | * 按照名称获取多个设备属性. |
||
| 86 | * |
||
| 87 | * @param $data |
||
| 88 | * $data = ['AABBCD-did' => |
||
| 89 | * ['type' => 'urn:miot-spec-v2:device:light:0000A001:yeelink-color1:1', data => ['brightness', 'on']] |
||
| 90 | * ] |
||
| 91 | * |
||
| 92 | * @throws ApiErrorException |
||
| 93 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 94 | * |
||
| 95 | * @return array|bool|mixed |
||
| 96 | */ |
||
| 97 | public function getPropertiesGraceful($data) |
||
| 98 | { |
||
| 99 | if (!empty($data)) { |
||
| 100 | $properties = []; |
||
| 101 | $attributes = []; |
||
| 102 | $instances = []; |
||
| 103 | foreach ($data as $did => $datum) { |
||
| 104 | if (isset($datum['type'])) { |
||
| 105 | $instance = new Instance($datum['type']); |
||
| 106 | $propertiesNodes = $instance->getPropertiesNodes(); |
||
| 107 | $instances[$did] = $propertiesNodes; |
||
| 108 | |||
| 109 | if (!empty($datum['data'])) { |
||
| 110 | foreach ($datum['data'] as $name) { |
||
| 111 | list($sids, $pids) = $instance->getSidPidByName($name); |
||
| 112 | |||
| 113 | if (!$sids || !$pids) { |
||
| 114 | throw new ApiErrorException('Invalid property! did:'.$did.',name: '.$name); |
||
| 115 | } |
||
| 116 | |||
| 117 | foreach ($sids as $sindex => $sid) { |
||
| 118 | $property = $propertiesNodes[($sid.'.'.$pids[$sindex])]; |
||
| 119 | |||
| 120 | if (!$property->canRead()) { |
||
| 121 | throw new ApiErrorException( |
||
| 122 | 'The property does\'t has the read access! did:'.$did.',name: '.$name |
||
| 123 | ); |
||
| 124 | } |
||
| 125 | |||
| 126 | $properties[] = $did.'.'.$sid.'.'.$pids[$sindex]; |
||
| 127 | } |
||
| 128 | } |
||
| 129 | } else { |
||
| 130 | foreach ($propertiesNodes as $property) { |
||
| 131 | $name = $property->getUrn()->getName(); |
||
| 132 | list($sids, $pids) = $instance->getSidPidByName($name); |
||
| 133 | |||
| 134 | if (!$sids || !$pids) { |
||
| 135 | throw new ApiErrorException('Invalid property! did:'.$did.',name: '.$name); |
||
| 136 | } |
||
| 137 | |||
| 138 | foreach ($sids as $sindex => $sid) { |
||
| 139 | $property = $propertiesNodes[($sid.'.'.$pids[$sindex])]; |
||
| 140 | |||
| 141 | if ($property->canRead()) { |
||
| 142 | $properties[] = $did.'.'.$sid.'.'.$pids[$sindex]; |
||
| 143 | } |
||
| 144 | } |
||
| 145 | } |
||
| 146 | } |
||
| 147 | } else { |
||
| 148 | throw new ApiErrorException('Properties data and device type required'); |
||
| 149 | } |
||
| 150 | } |
||
| 151 | |||
| 152 | $response = $this->properties(array_unique($properties)); |
||
| 153 | if (isset($response['properties']) && !empty($response['properties'])) { |
||
| 154 | foreach ($response['properties'] as $res) { |
||
| 155 | $pidArr = explode('.', $res['pid']); |
||
| 156 | if (isset($res['value']) // 是否获取到了值 |
||
| 157 | && isset($res['status']) // 是否有返回状态 |
||
| 158 | && $res['status'] == 0 // 是否正常返回 |
||
| 159 | && isset($pidArr[0]) // did |
||
| 160 | && isset($pidArr[1]) // sid |
||
| 161 | && isset($pidArr[2]) // pid |
||
| 162 | && isset($instances[$pidArr[0]][($pidArr[1].'.'.$pidArr[2])])) { |
||
| 163 | $attributeName = $instances[$pidArr[0]][($pidArr[1].'.'.$pidArr[2])]->getUrn()->getName(); |
||
| 164 | |||
| 165 | if (isset($attributes[$pidArr[0]][$attributeName])) { |
||
| 166 | if (is_array($attributes[$pidArr[0]][$attributeName])) { |
||
| 167 | $attributes[$pidArr[0]][$attributeName][] = $res['value']; |
||
| 168 | } else { |
||
| 169 | $attributes[$pidArr[0]][$attributeName] = [ |
||
| 170 | $attributes[$pidArr[0]][$attributeName], |
||
| 171 | $res['value'], |
||
| 172 | ]; |
||
| 173 | } |
||
| 174 | } else { |
||
| 175 | $attributes[$pidArr[0]][$attributeName] = $res['value']; |
||
| 176 | } |
||
| 177 | } |
||
| 178 | } |
||
| 179 | } |
||
| 180 | |||
| 181 | return $attributes; |
||
| 182 | } else { |
||
| 183 | throw new ApiErrorException('devices data required'); |
||
| 184 | } |
||
| 185 | } |
||
| 186 | |||
| 187 | /** |
||
| 188 | * 按照名称设置属性. |
||
| 189 | * |
||
| 190 | * @param $did |
||
| 191 | * @param $type |
||
| 192 | * @param $data | $data = ['brightness' => 75, 'on' => true] |
||
| 193 | * |
||
| 194 | * @throws ApiErrorException |
||
| 195 | * @throws \MiotApi\Exception\JsonException |
||
| 196 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 197 | * |
||
| 198 | * @return array|bool|mixed |
||
| 199 | */ |
||
| 200 | public function setPropertyGraceful($did, $type, $data) |
||
| 213 | } |
||
| 214 | } |
||
| 215 | |||
| 216 | /** |
||
| 217 | * 按照名称设置多个设备属性. |
||
| 218 | * |
||
| 219 | * @param $data |
||
| 220 | * $data = ['AABBCD-did' => |
||
| 221 | * ['type' => 'urn:miot-spec-v2:device:light:0000A001:yeelink-color1:1', data => ['brightness' => 75, 'on' => true]] |
||
| 222 | * ] |
||
| 223 | * |
||
| 224 | * @throws ApiErrorException |
||
| 225 | * @throws \MiotApi\Exception\JsonException |
||
| 226 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 227 | * |
||
| 228 | * @return array|bool|mixed |
||
| 229 | */ |
||
| 230 | public function setPropertiesGraceful($data) |
||
| 231 | { |
||
| 232 | if (!empty($data)) { |
||
| 233 | $properties = []; |
||
| 234 | foreach ($data as $did => $datum) { |
||
| 235 | if (!empty($datum['data']) && isset($datum['type'])) { |
||
| 236 | $instance = new Instance($datum['type']); |
||
| 237 | $propertiesNodes = $instance->getPropertiesNodes(); |
||
| 238 | |||
| 239 | foreach ($datum['data'] as $name => $value) { |
||
| 240 | list($sids, $pids) = $instance->getSidPidByName($name); |
||
| 241 | |||
| 242 | if (!$sids || !$pids) { |
||
| 243 | throw new ApiErrorException('Invalid property! did:'.$did.',name: '.$name); |
||
| 244 | } |
||
| 245 | |||
| 246 | foreach ($sids as $sindex => $sid) { |
||
| 247 | $property = $propertiesNodes[($sid.'.'.$pids[$sindex])]; |
||
| 248 | |||
| 249 | if (!is_array($value)) { |
||
| 250 | $tmpValue = $value; |
||
| 251 | } else { |
||
| 252 | if (!isset($value[$sindex])) { |
||
| 253 | continue; |
||
| 254 | } |
||
| 255 | $tmpValue = $value[$sindex]; |
||
| 256 | } |
||
| 257 | |||
| 258 | if (!$property->verify($tmpValue)) { |
||
| 259 | throw new ApiErrorException('Invalid property value! did:'.$did.',name: '.$name); |
||
| 260 | } |
||
| 261 | |||
| 262 | if (!$property->canWrite()) { |
||
| 263 | throw new ApiErrorException( |
||
| 264 | 'The property does\'t has the write access! did:'.$did.',name: '.$name |
||
| 265 | ); |
||
| 266 | } |
||
| 267 | |||
| 268 | $properties[] = [ |
||
| 269 | 'pid' => $did.'.'.$sid.'.'.$pids[$sindex], |
||
| 270 | 'value' => $tmpValue, |
||
| 271 | ]; |
||
| 272 | } |
||
| 273 | } |
||
| 274 | } else { |
||
| 275 | throw new ApiErrorException('Properties data and device type required'); |
||
| 276 | } |
||
| 277 | } |
||
| 278 | |||
| 279 | return $this->setProperties([ |
||
| 280 | 'properties' => $properties, |
||
| 281 | ]); |
||
| 282 | } else { |
||
| 283 | throw new ApiErrorException('devices data required'); |
||
| 284 | } |
||
| 285 | } |
||
| 286 | |||
| 287 | /** |
||
| 288 | * 根据 devicesList 方法获取到的设备列表信息 订阅设备属性变化. |
||
| 289 | * |
||
| 290 | * @param $devices |
||
| 291 | * @param $customData |
||
| 292 | * @param $receiverUrl |
||
| 293 | * |
||
| 294 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 295 | * |
||
| 296 | * @return array|bool|mixed |
||
| 297 | */ |
||
| 298 | public function subscriptByDevices($devices, $customData, $receiverUrl) |
||
| 303 | } |
||
| 304 | |||
| 305 | /** |
||
| 306 | * 根据 devicesList 方法获取到的设备列表信息 退订设备属性变化. |
||
| 307 | * |
||
| 308 | * @param $devices |
||
| 309 | * |
||
| 310 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 311 | * |
||
| 312 | * @return array|bool|mixed |
||
| 313 | */ |
||
| 314 | public function unSubscriptByDevices($devices) |
||
| 319 | } |
||
| 320 | |||
| 321 | /** |
||
| 322 | * 根据设备列表和 access列表 获取对于访问方式的属性. |
||
| 323 | * |
||
| 324 | * @param $devices |
||
| 325 | * @param array $access | ['read'] ['read', 'notify'] ['read', 'write', 'notify'] |
||
| 326 | * |
||
| 327 | * @throws \MiotApi\Exception\SpecificationErrorException |
||
| 328 | * |
||
| 329 | * @return array|bool |
||
| 330 | */ |
||
| 331 | protected function getPropertiesByDevices($devices, $access = []) |
||
| 371 |