Passed
Push — feature/api-versions ( d9c41a...e74f44 )
by Robin
12:14
created

JustGivingClient   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 6
dl 0
loc 147
ccs 37
cts 37
cp 1
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A setOptions() 0 5 1
A request() 0 12 1
A buildRequest() 0 13 2
A buildUri() 0 4 1
A buildHeaders() 0 6 1
A __get() 0 14 3
1
<?php
2
3
namespace Konsulting\JustGivingApiSdk;
4
5
use GuzzleHttp\Psr7\Request;
6
use Konsulting\JustGivingApiSdk\Exceptions\ClassNotFoundException;
7
use Konsulting\JustGivingApiSdk\ResourceClients\AccountClient;
8
use Konsulting\JustGivingApiSdk\ResourceClients\CampaignClient;
9
use Konsulting\JustGivingApiSdk\ResourceClients\CharityClient;
10
use Konsulting\JustGivingApiSdk\ResourceClients\CountriesClient;
11
use Konsulting\JustGivingApiSdk\ResourceClients\CurrencyClient;
12
use Konsulting\JustGivingApiSdk\ResourceClients\DonationClient;
13
use Konsulting\JustGivingApiSdk\ResourceClients\EventClient;
14
use Konsulting\JustGivingApiSdk\ResourceClients\FundraisingClient;
15
use Konsulting\JustGivingApiSdk\ResourceClients\LeaderboardClient;
16
use Konsulting\JustGivingApiSdk\ResourceClients\OneSearchClient;
17
use Konsulting\JustGivingApiSdk\ResourceClients\ProjectClient;
18
use Konsulting\JustGivingApiSdk\ResourceClients\SearchClient;
19
use Konsulting\JustGivingApiSdk\ResourceClients\SmsClient;
20
use Konsulting\JustGivingApiSdk\ResourceClients\TeamClient;
21
use Konsulting\JustGivingApiSdk\Support\Auth\AuthValue;
22
use Konsulting\JustGivingApiSdk\Support\Response;
23
use Psr\Http\Client\ClientInterface;
24
use RicardoFiorani\GuzzlePsr18Adapter\Client;
25
26
/**
27
 * Class JustGivingClient
28
 *
29
 * @property AccountClient     account
30
 * @property CampaignClient    campaign
31
 * @property CharityClient     charity
32
 * @property CountriesClient   countries
33
 * @property CurrencyClient    currency
34
 * @property DonationClient    donation
35
 * @property EventClient       event
36
 * @property LeaderboardClient leaderboard
37
 * @property OneSearchClient   oneSearch
38
 * @property FundraisingClient fundraising
39
 * @property ProjectClient     project
40
 * @property SearchClient      search
41
 * @property SmsClient         sms
42
 * @property TeamClient        team
43
 * @property AccountClient     Account
44
 * @property CampaignClient    Campaign
45
 * @property CharityClient     Charity
46
 * @property CountriesClient   Countries
47
 * @property CurrencyClient    Currency
48
 * @property DonationClient    Donation
49
 * @property EventClient       Event
50
 * @property LeaderboardClient Leaderboard
51
 * @property ProjectClient     Project
52
 * @property SearchClient      Search
53
 * @property SmsClient         Sms
54
 * @property TeamClient        Team
55
 */
56
class JustGivingClient
57
{
58
    /**
59
     * The clients that have been instantiated.
60
     *
61
     * @var array
62
     */
63
    protected $clients = [];
64
65
    /**
66
     * The client to execute the HTTP requests.
67
     *
68
     * @var ClientInterface
69
     */
70
    protected $httpClient;
71
72
    /**
73
     * The client options.
74
     *
75
     * @var array
76
     */
77
    protected $options = [
78
        'api_version' => 1,
79
        'root_domain' => 'https://api.justgiving.com',
80
    ];
81
82
    /**
83
     * @var AuthValue
84
     */
85
    private $auth;
86
87
    /**
88
     * JustGivingClient constructor.
89
     *
90
     * @param AuthValue       $auth
91
     * @param ClientInterface $client
92
     * @param array           $options
93
     */
94 89
    public function __construct(AuthValue $auth, ClientInterface $client = null, $options = [])
95
    {
96 89
        $this->auth = $auth;
97 89
        $this->httpClient = $client ?: new Client;
98 89
        $this->setOptions($options);
99 89
    }
100
101
    /**
102
     * Set the client options, using defaults for any that are not provided.
103
     *
104
     * @param array $options
105
     */
106 89
    private function setOptions(array $options)
107
    {
108 89
        $this->options['root_domain'] = $options['root_domain'] ?? $this->options['root_domain'];
109 89
        $this->options['api_version'] = $options['api_version'] ?? $this->options['api_version'];
110 89
    }
111
112
    /**
113
     * Proxy a request onto the HTTP client, using the fully qualified URI.
114
     *
115
     * @param string $method
116
     * @param string $uri
117
     * @param array  $httpOptions   Custom options for the HTTP client (e.g. headers)
118
     * @param array  $clientOptions Custom options for the JustGiving client (e.g. API version)
119
     * @return Response
120
     * @throws \Psr\Http\Client\ClientExceptionInterface
121
     */
122 74
    public function request($method, $uri, $httpOptions = [], $clientOptions = [])
123
    {
124 74
        $optionsBackup = $this->options;
125 74
        $this->setOptions($clientOptions);
126
127 74
        $request = $this->buildRequest($method, $uri, $httpOptions);
128 74
        $response = $this->httpClient->sendRequest($request);
129
130 74
        $this->options = $optionsBackup;
131
132 74
        return new Response($response);
133
    }
134
135
    /**
136
     * Build the PSR-7 request object. Encode JSON payload and set headers if needed.
137
     *
138
     * @param string $method
139
     * @param string $uri
140
     * @param array  $options
141
     * @return Request
142
     */
143 74
    private function buildRequest($method, $uri, $options)
144
    {
145 74
        $headers = $options['headers'] ?? [];
146 74
        $body = $options['body'] ?? null;
147 74
        $version = $options['version'] ?? '1.1';
148
149 74
        if (isset($options['json'])) {
150 29
            $headers += ['Content-Type' => 'application/json'];
151 29
            $body = json_encode($options['json']);
152
        }
153
154 74
        return new Request($method, $this->buildUri($uri), $this->buildHeaders($headers), $body, $version);
155
    }
156
157
    /**
158
     * Build the full URI using the root URI and API version.
159
     *
160
     * @param string $uri
161
     * @return string
162
     */
163 74
    private function buildUri($uri)
164
    {
165 74
        return $this->options['root_domain'] . '/v' . $this->options['api_version'] . '/' . $uri;
166
    }
167
168
    /**
169
     * Merge the per-request headers with the auth headers.
170
     *
171
     * @param array $requestHeaders
172
     * @return array
173
     */
174 74
    private function buildHeaders($requestHeaders)
175
    {
176 74
        $defaultHeaders = ['Accept' => 'application/json'];
177
178 74
        return array_merge($defaultHeaders, $this->auth->getHeaders(), $requestHeaders);
179
    }
180
181
    /**
182
     * Allow API classes to be called as properties. Return a singleton client class.
183
     *
184
     * @param string $property
185
     * @return mixed
186
     * @throws \Exception
187
     */
188 77
    public function __get($property)
189
    {
190 77
        $class = __NAMESPACE__ . '\\ResourceClients\\' . ucfirst($property) . 'Client';
191
192 77
        if (! class_exists($class)) {
193 1
            throw new ClassNotFoundException($class);
194
        }
195
196 76
        $this->clients[$class] = isset($this->clients[$class])
197 18
            ? $this->clients[$class]
198 76
            : new $class($this);
199
200 76
        return $this->clients[$class];
201
    }
202
}
203