Passed
Push — master ( f52952...8a81ff )
by
unknown
04:07
created

AlmaApi::executeApiRequest()   B

Complexity

Conditions 9
Paths 27

Size

Total Lines 57
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 31
nc 27
nop 5
dl 0
loc 57
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Service;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use Psr\Log\LoggerInterface;
8
use SimpleXMLElement;
9
10
class AlmaApi
11
{
12
    private $logger;
13
14
    public function __construct(LoggerInterface $logger)
15
    {
16
        $this->logger = $logger;
17
    }
18
19
    /**
20
     * Wrapper for requests to Alma API
21
     *
22
     * @param $urlPath
23
     * @param $method
24
     * @param $requestParams
25
     * @param $templateParamNames
26
     * @param $templateParamValues
27
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
28
     * @throws GuzzleException
29
     */
30
    protected function executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues)
31
    {
32
        $client = new Client(['base_uri' => getenv('API_URL')]);
33
34
        $url = str_replace($templateParamNames, $templateParamValues, $urlPath);
35
        $defaultRequestParams = [
36
            'headers' => [
37
                'Authorization' => 'apikey ' . getenv('API_KEY'),
38
            ]
39
        ];
40
41
        try {
42
            $response = $client->request($method, $url, array_merge_recursive($requestParams, $defaultRequestParams));
43
        } catch (\Exception $e) {
44
            $emergency = true;
45
            $emergencyClientStatusCodes = ['404', '403', '401'];
46
            if ($e->hasResponse()) {
0 ignored issues
show
Bug introduced by
The method hasResponse() does not exist on Exception. It seems like you code against a sub-type of Exception such as GuzzleHttp\Exception\RequestException. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
            if ($e->/** @scrutinizer ignore-call */ hasResponse()) {
Loading history...
47
                $response = $e->getResponse();
0 ignored issues
show
Bug introduced by
The method getResponse() does not exist on Exception. It seems like you code against a sub-type of Exception such as GuzzleHttp\Exception\RequestException. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

47
                /** @scrutinizer ignore-call */ 
48
                $response = $e->getResponse();
Loading history...
48
                $statusCode = $response->getStatusCode();
49
                // 500 errors are always considered and emergency
50
                if (!in_array($statusCode, $emergencyClientStatusCodes) && !preg_match('/5[0-9][0-9]/', $statusCode)) {
51
                    $emergency = false;
52
                }
53
54
                $body = $response->getBody();
55
                try {
56
                    $sxml = new SimpleXMLElement($body);
57
58
                    foreach ($sxml->errorList as $error) {
59
                        $code = $error->error->errorCode;
60
                        $msg = $error->error->errorMessage;
61
                        $this->logger->error("Alma API error (HTTP status code: $statusCode Alma Error Code: $code): $msg");
62
                    }
63
                } catch (\Exception $e1) {
64
                    /**
65
                     *  The Alma API will return a 400 status code in the event that the API key is invalid.
66
                     *  Unfortunately, this same status code is returned under many other circumstances, for
67
                     *  example if a user provides incorrect credentials to log in.  The only way I can figure
68
                     *  out how to distinguish the two is by checking the actual text of the body, which annoyingly
69
                     *  isn't a valid XML response like all the other responses.
70
                     */
71
                    if ($body == 'Invalid API Key') {
72
                        $this->logger->emergency("@web-irt-dev Critical Error: $body :fire:");
73
                    } else {
74
                        $this->logger->error("Unable to parse response from Alma API as XML.  Status code: $statusCode  Body: $body");
75
                    }
76
                }
77
            }
78
79
            if ($emergency) {
80
                $this->logger->emergency("@web-irt-dev Critical Error: Unable to reach the Alma API! :fire:");
81
            }
82
83
            throw $e;
84
        }
85
86
        return $response;
87
    }
88
89
    /**
90
     * Get the users list of fees from Alma
91
     *
92
     * @param $userId
93
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
94
     * @throws GuzzleException
95
     */
96
    public function getUserFees($userId)
97
    {
98
        $method = 'GET';
99
        $urlPath = '/almaws/v1/users/{user_id}/fees';
100
        $templateParamNames = array('{user_id}');
101
        $templateParamValues = array(urlencode($userId));
102
        $query = [
103
            'user_id_type' => 'all_unique',
104
            'status' => 'ACTIVE'
105
        ];
106
        $requestParams = compact('query');
107
108
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
109
    }
110
111
    /**
112
     * Get the user from alma by the user id. Returns 400 status code if user does not exist.
113
     *
114
     * @param $userId
115
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
116
     * @throws GuzzleException
117
     */
118
    public function getUserById($userId)
119
    {
120
        $method = 'GET';
121
        $urlPath = '/almaws/v1/users/{user_id}';
122
        $templateParamNames = array('{user_id}');
123
        $templateParamValues = array(urlencode($userId));
124
        $query = [
125
            'user_id_type' => 'all_unique',
126
            'view' => 'full',
127
            'expand' => 'none'
128
        ];
129
        $requestParams = compact('query');
130
131
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
132
    }
133
134
    /**
135
     * Use the Alma api to search for the user by primary_id.
136
     * This is how we will check that a the provided user id is found in Alma as a primary_id.
137
     *
138
     * @param $userId
139
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
140
     * @throws GuzzleException
141
     */
142
    public function findUserById($userId)
143
    {
144
        $method = 'GET';
145
        $urlPath = '/almaws/v1/users';
146
        $templateParamNames = array();
147
        $templateParamValues = array();
148
        $query = [
149
            'limit' => '10',
150
            'offset' => '0',
151
            'q' => 'primary_id~' . $userId,
152
            'order_by' => 'last_name first_name, primary_id'
153
        ];
154
        $requestParams = compact('query');
155
156
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
157
    }
158
159
    /**
160
     * @param string $userId The alphanumeric userId of the logged in user
161
     * @param string $feeId The Alma specific fee id to be updated
162
     * @param $amount
163
     * @param string $method
164
     * @param null $externalTransactionId
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $externalTransactionId is correct as it would always require null to be passed?
Loading history...
165
     * @param null $comment
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $comment is correct as it would always require null to be passed?
Loading history...
166
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
167
     * @throws GuzzleException
168
     */
169
    public function payUserFee($userId, $feeId, $amount, $method = 'ONLINE', $externalTransactionId = null, $comment = null)
170
    {
171
        $queryParams = [
172
            'op' => 'pay',
173
            'amount' => $amount,
174
            'method' => $method,
175
            'external_transaction_id' => $externalTransactionId,
176
            'comment' => $comment,
177
        ];
178
        /**
179
         * " If no callback is supplied, all entries of array equal to FALSE (see converting to boolean) will be removed."
180
         * - http://php.net/array_filter
181
         */
182
        $queryParams = array_filter($queryParams);
183
184
        return $this->updateUserFee($userId, $feeId, $queryParams);
185
    }
186
187
    /**
188
     * @param string $userId The alphanumeric userId of the logged in user
189
     * @param string $feeId The Alma specific fee id to be updated
190
     * @param array $query The parameters for the query.
191
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
192
     * @throws GuzzleException
193
     */
194
    protected function updateUserFee($userId, $feeId, $query)
195
    {
196
        $method = 'POST';
197
        $urlPath = '/almaws/v1/users/{user_id}/fees/{fee_id}';
198
        $templateParamNames = array('{user_id}', '{fee_id}');
199
        $templateParamValues = array(urlencode($userId), urlencode($feeId));
200
        $requestParams = compact('query');
201
202
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
203
    }
204
205
    /**
206
     * @param string $userId The alphanumeric userId of the logged in user
207
     * @param mixed $body A plain PHP object representing a fee.
208
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
209
     * @throws GuzzleException
210
     */
211
    public function createUserFee($userId, $body)
212
    {
213
        $method = 'POST';
214
        $urlPath = '/almaws/v1/users/{user_id}/fees';
215
        $templateParamNames = array('{user_id}');
216
        $templateParamValues = array(urlencode($userId));
217
218
        $headers = [
219
            'Content-Type' => 'application/json'
220
        ];
221
        $body = json_encode($body);
222
        $requestParams = compact('body', 'headers');
223
224
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
225
    }
226
227
    /**
228
     * @param string $userId The alphanumeric userId of the logged in user
229
     * @param string $userPassword The alphanumeric userPassword of the logged in user
230
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
231
     * @throws GuzzleException
232
     */
233
    public function authenticateUser($userId, $userPassword)
234
    {
235
        $method = 'POST';
236
        $urlPath = '/almaws/v1/users/{user_id}';
237
        $templateParamNames = array('{user_id}');
238
        $templateParamValues = array(urlencode($userId));
239
        $query = [
240
            'user_id_type' => 'all_unique',
241
            'op' => 'auth'
242
        ];
243
244
        $headers = [
245
            'Exl-User-Pw' => $userPassword
246
        ];
247
        $requestParams = compact('query', 'headers');
248
249
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
250
    }
251
}
252