Passed
Branch master (dd75d0)
by Peter
02:45
created

ApiClient::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 3
1
<?php
2
3
namespace PeterColes\XmlSoccer;
4
5
use Exception;
6
use GuzzleHttp\Client as GuzzleClient;
7
use PeterColes\XmlSoccer\Converters\ObjectConverter;
8
use PeterColes\XmlSoccer\Exceptions\ApiKeyNotAcceptedException;
9
use PeterColes\XmlSoccer\Exceptions\ApiThrottlingException;
10
use PeterColes\XmlSoccer\Exceptions\InvalidXmlException;
11
use PeterColes\XmlSoccer\Exceptions\MissingApiKeyException;
12
use PeterColes\XmlSoccer\Exceptions\RequestFailedException;
13
14
class ApiClient
15
{
16
    /**
17
     * Default API endpoint.
18
     */
19
    protected $apiEndpoint;
20
21
    /**
22
     * Subscriber's API key.
23
     */
24
    protected $apiKey;
25
26
    /**
27
     * Guzzle client instance.
28
     */
29
    protected $guzzleClient;
30
31
    /**
32
     * Data converter instance.
33
     */
34
    protected $converter = null;
35
36
    /**
37
     * Should data be returned as a json encoded string?
38
     */
39
    protected $encode = false;
40
41
    /**
42
     * Optional (recommended) setting of an API key when a new instance is instantiated.
43
     * Setting the API endpoint, default or demo according to the (optional) parameter.
44
     * Advanced users may wish to a Guzzle client with their own configuration settings
45
     * but this will rarely be needed.
46
     *
47
     * @param string | null $apiKey
48
     * @param boolean       $demo
49
     * @param GuzzleClient  $guzzleClient
50
     */
51
    public function __construct($apiKey = null, $demo = false, $guzzleClient = null)
52
    {
53
        $this->setApiKey($apiKey);
54
        $this->setApiEndpoint($demo);
55
        $this->initGuzzleClient($guzzleClient);
56
    }
57
58
    /**
59
     * Override default API endpoint.
60
     *
61
     * @param $apiEndpoint
62
     */
63
    public function setApiEndpoint($demo = false)
64
    {
65
        $this->apiEndpoint = 'http://www.xmlsoccer.com/FootballData'.($demo ? 'Demo' : '').'.asmx';
66
    }
67
68
    /**
69
     * Set or override the API key.
70
     *
71
     * @param $apiKey
72
     */
73
    public function setApiKey($apiKey)
74
    {
75
        $this->apiKey = $apiKey;
76
    }
77
78
    /**
79
     * Accept the requested method and its parameters, make the request to XML Soccer and validate the response.
80
     *
81
     * @param $name
82
     * @param $params
83
     * @return SimpleXMLElement
84
     */
85
    public function __call($method, $params)
86
    {
87
        $xml = $this->request($this->buildUri($method), $this->prepareParams($method, $params));
88
89
        if (false !== strpos($xml, 'Api-key not accepted')) {
90
            throw new ApiKeyNotAcceptedException;
91
        }
92
93
        if (false !== strpos($xml, 'To avoid misuse of the service')) {
94
            throw new ApiThrottlingException;
95
        }
96
97
        try {
98
            $xml = simplexml_load_string($xml);
99
        } catch (Exception $e) {
100
            throw new InvalidXmlException;
101
        }
102
103
        $result = $this->converter ? $this->converter->handle($xml) : $xml;
104
105
        return $this->encode ? json_encode($result) : $result;
106
    }
107
108
    public function object()
109
    {
110
        $this->converter = new ObjectConverter;
111
112
        return $this;
113
    }
114
115
    public function json()
116
    {
117
        $this->encode = true;
118
119
        return $this->object();
120
    } 
121
122
    /**
123
     * Build the base URI for the API from its endpoint and the resource being requested.
124
     *
125
     * @param $method
126
     * @return string
127
     */
128
    protected function buildUri($method)
129
    {
130
        return $this->apiEndpoint.'/'.ucfirst($method);
131
    }
132
133
    /**
134
     * Almost all API calls require an API Key so we add it to the parameters.
135
     *
136
     * @param $params
137
     * @return string
138
     */
139
    protected function prepareParams($method, $params)
140
    {
141
        if ('ImAlive' == ucfirst($method)) {
142
            return null;
143
        }
144
145
        if (!$this->apiKey) {
146
            throw new MissingApiKeyException;
147
        }
148
149
        return array_merge([ 'apiKey' => $this->apiKey ], $params[ 0 ] ?? [ ]);
150
    }
151
152
    /**
153
     * Initialise or inject an instance of the Guzzle client.
154
     *
155
     * @return GuzzleClient
156
     */
157
    protected function initGuzzleClient($guzzleClient = null)
158
    {
159
        $this->guzzleClient = $guzzleClient ?? new GuzzleClient;
160
    }
161
162
    /**
163
     * Make the request to the XML Soccer service and validate response.
164
     *
165
     * @param  string        $uri
166
     * @param  array | null  $params
167
     * @throws RequestFailedException
168
     * @return SimpleXMLElement
169
     */
170
    protected function request($uri, $params)
171
    {
172
        try {
173
            $response = $this->guzzleClient->get($uri, [ 'query' => $params ]);
174
        } catch (Exception $e) {
175
            throw new RequestFailedException;
176
        }
177
178
        return $response->getBody();
179
    }
180
}
181