1
|
|
|
<?php |
2
|
|
|
namespace Nkey\DDG\API; |
3
|
|
|
|
4
|
|
|
use Nkey\DDG\API\Model\Icon; |
5
|
|
|
use Nkey\DDG\API\Model\QueryResult; |
6
|
|
|
use Nkey\DDG\API\Model\RelatedTopic; |
7
|
|
|
use Webmozart\Json\JsonDecoder; |
8
|
|
|
use ReflectionClass; |
9
|
|
|
use ReflectionMethod; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* This class provides means for parsing json from duckduckgo api into a local model |
13
|
|
|
* |
14
|
|
|
* @author Maik Greubel <[email protected]> |
15
|
|
|
* @license Apache 2.0 |
16
|
|
|
*/ |
17
|
|
|
class QueryResultParser |
18
|
|
|
{ |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Parse a payload json string |
22
|
|
|
* |
23
|
|
|
* @param string $payload |
24
|
|
|
* The payload to parse |
25
|
|
|
* @return QueryResult |
26
|
|
|
*/ |
27
|
2 |
|
public function parseQueryResult(string $payload): QueryResult |
28
|
|
|
{ |
29
|
2 |
|
$decoder = new JsonDecoder(); |
30
|
|
|
|
31
|
2 |
|
$json = $decoder->decode($payload); |
32
|
|
|
|
33
|
2 |
|
$result = new QueryResult(); |
34
|
|
|
|
35
|
2 |
|
$ref = new ReflectionClass($result); |
36
|
2 |
|
$methods = $ref->getMethods(ReflectionMethod::IS_PUBLIC); |
37
|
2 |
View Code Duplication |
foreach ($methods as $method) { |
|
|
|
|
38
|
2 |
|
if (($propertyName = $this->getPropertyName($method))) { |
39
|
2 |
|
if ($propertyName === 'Meta') { |
40
|
2 |
|
$result = $this->parseMeta($result, $json->meta); |
41
|
2 |
|
continue; |
42
|
|
|
} |
43
|
2 |
|
$this->assignPropertyValue($method, $result, $json, $propertyName); |
44
|
|
|
} |
45
|
|
|
} |
46
|
|
|
|
47
|
2 |
|
$result = $this->parseRelatedTopics($result, $json->RelatedTopics); |
48
|
2 |
|
return $result; |
49
|
|
|
} |
50
|
|
|
|
51
|
2 |
|
private function assignPropertyValue(ReflectionMethod $method, $destObject, $object, $propertyName) { |
52
|
2 |
|
if (property_exists($object, $propertyName)) { |
53
|
2 |
|
$property = $object->$propertyName; |
54
|
2 |
|
$method->invoke($destObject, $property); |
55
|
|
|
} |
56
|
2 |
|
} |
57
|
|
|
|
58
|
2 |
|
private function getPropertyName(ReflectionMethod $method) { |
59
|
2 |
|
$propertyName = false; |
60
|
2 |
|
if (substr($method->name, 0, 3) === 'set') { |
61
|
2 |
|
$propertyName = substr($method->name, 3); |
62
|
|
|
} |
63
|
|
|
|
64
|
2 |
|
return $propertyName; |
65
|
|
|
} |
66
|
|
|
|
67
|
2 |
|
private function parseRelatedTopics(QueryResult $result, $relatedTopics) |
68
|
|
|
{ |
69
|
2 |
|
foreach ($relatedTopics as $relatedTopic) { |
70
|
2 |
|
$topic = new RelatedTopic(); |
71
|
2 |
|
$ref = new ReflectionClass($topic); |
72
|
2 |
|
$methods = $ref->getMethods(ReflectionMethod::IS_PUBLIC); |
73
|
2 |
View Code Duplication |
foreach ($methods as $method) { |
|
|
|
|
74
|
2 |
|
if (($propertyName = $this->getPropertyName($method))) { |
75
|
2 |
|
if ($propertyName === 'Icon') { |
76
|
2 |
|
$topic = $this->parseIcon($topic, $relatedTopic->Icon); |
77
|
2 |
|
continue; |
78
|
|
|
} |
79
|
2 |
|
$this->assignPropertyValue($method, $topic, $relatedTopic, $propertyName); |
80
|
|
|
} |
81
|
|
|
} |
82
|
2 |
|
$result->addRelatedTopic($topic); |
83
|
|
|
} |
84
|
|
|
|
85
|
2 |
|
return $result; |
86
|
|
|
} |
87
|
|
|
|
88
|
2 |
|
private function parseIcon(RelatedTopic $topic, $icon): RelatedTopic |
89
|
|
|
{ |
90
|
2 |
|
$ico = new Icon(); |
91
|
|
|
|
92
|
2 |
|
$ref = new ReflectionClass($ico); |
93
|
2 |
|
$methods = $ref->getMethods(ReflectionMethod::IS_PUBLIC); |
94
|
2 |
|
foreach ($methods as $method) { |
95
|
2 |
|
if (($propertyName = $this->getPropertyName($method))) { |
96
|
2 |
|
if (property_exists($icon, $propertyName)) { |
97
|
2 |
|
$property = $icon->$propertyName; |
98
|
|
|
|
99
|
2 |
|
if ($propertyName === 'Height' || $propertyName === 'Width') { |
100
|
2 |
|
$property = intval($property); |
101
|
|
|
} |
102
|
2 |
|
$method->invoke($ico, $property); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
2 |
|
$topic->setIcon($ico); |
108
|
|
|
|
109
|
2 |
|
return $topic; |
110
|
|
|
} |
111
|
|
|
|
112
|
2 |
|
private function parseMeta(QueryResult $result, $meta): QueryResult |
|
|
|
|
113
|
|
|
{ |
114
|
2 |
|
return $result; |
115
|
|
|
} |
116
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.