Completed
Push — master ( 5f5fca...2fa1e0 )
by Bjørn
12:28 queued 02:24
created

Ewww::getQuota()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 1
dl 0
loc 21
ccs 0
cts 15
cp 0
crap 2
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
namespace WebPConvert\Convert\Converters;
4
5
use WebPConvert\Convert\BaseConverters\AbstractCloudCurlConverter;
6
use WebPConvert\Convert\Exceptions\ConversionFailedException;
7
use WebPConvert\Convert\Exceptions\ConversionFailed\ConverterNotOperationalException;
8
use WebPConvert\Convert\Exceptions\ConversionFailed\ConverterNotOperational\SystemRequirementsNotMetException;
9
10
class Ewww extends AbstractCloudCurlConverter
11
{
12
    protected $supportsLossless = false;
13
14 1
    protected function getOptionDefinitionsExtra()
15
    {
16
        return [
17 1
            ['key', 'string', '', true, true]
18 1
        ];
19
    }
20
21
    /**
22
     * Check operationality of Ewww converter.
23
     *
24
     * @throws SystemRequirementsNotMetException  if system requirements are not met (curl)
25
     * @throws ConverterNotOperationalException   if key is missing or invalid, or quota has exceeded
26
     */
27 1
    protected function checkOperationality()
28
    {
29
        // First check for curl requirements
30 1
        parent::checkOperationality();
31
32 1
        $options = $this->options;
33
34 1
        if ($options['key'] == '') {
35 1
            throw new ConverterNotOperationalException('Missing API key.');
36
        }
37
        if (strlen($options['key']) < 20) {
38
            throw new ConverterNotOperationalException(
39
                'Key is invalid. Keys are supposed to be 32 characters long - your key is much shorter'
40
            );
41
        }
42
43
        $keyStatus = self::getKeyStatus($options['key']);
44
        switch ($keyStatus) {
45
            case 'great':
46
                break;
47
            case 'exceeded':
48
                throw new ConverterNotOperationalException('quota has exceeded');
49
                break;
50
            case 'invalid':
51
                throw new ConverterNotOperationalException('key is invalid');
52
                break;
53
        }
54
    }
55
56
    // Although this method is public, do not call directly.
57
    // You should rather call the static convert() function, defined in AbstractConverter, which
58
    // takes care of preparing stuff before calling doConvert, and validating after.
59
    protected function doActualConvert()
60
    {
61
62
        $options = $this->options;
63
64
        $ch = self::initCurl();
65
66
        $curlOptions = [
67
            'api_key' => $options['key'],
68
            'webp' => '1',
69
            'file' => curl_file_create($this->source),
70
            'domain' => $_SERVER['HTTP_HOST'],
71
            'quality' => $this->getCalculatedQuality(),
72
            'metadata' => ($options['metadata'] == 'none' ? '0' : '1')
73
        ];
74
75
        curl_setopt_array(
76
            $ch,
77
            [
78
            CURLOPT_URL => "https://optimize.exactlywww.com/v2/",
79
            CURLOPT_HTTPHEADER => [
80
                'User-Agent: WebPConvert',
81
                'Accept: image/*'
82
            ],
83
            CURLOPT_POSTFIELDS => $curlOptions,
84
            CURLOPT_BINARYTRANSFER => true,
85
            CURLOPT_RETURNTRANSFER => true,
86
            CURLOPT_HEADER => false,
87
            CURLOPT_SSL_VERIFYPEER => false
88
            ]
89
        );
90
91
        $response = curl_exec($ch);
92
93
        if (curl_errno($ch)) {
94
            throw new ConversionFailedException(curl_error($ch));
95
        }
96
97
        // The API does not always return images.
98
        // For example, it may return a message such as '{"error":"invalid","t":"exceeded"}
99
        // Messages has a http content type of ie 'text/html; charset=UTF-8
100
        // Images has application/octet-stream.
101
        // So verify that we got an image back.
102
        if (curl_getinfo($ch, CURLINFO_CONTENT_TYPE) != 'application/octet-stream') {
103
            //echo curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
104
            curl_close($ch);
105
106
            /* May return this: {"error":"invalid","t":"exceeded"} */
107
            $responseObj = json_decode($response);
108
            if (isset($responseObj->error)) {
109
                //echo 'error:' . $responseObj->error . '<br>';
110
                //echo $response;
111
                //self::blacklistKey($key);
112
                //throw new SystemRequirementsNotMetException('The key is invalid. Blacklisted it!');
113
                throw new ConverterNotOperationalException('The key is invalid');
114
            }
115
116
            throw new ConversionFailedException(
117
                'ewww api did not return an image. It could be that the key is invalid. Response: '
118
                . $response
119
            );
120
        }
121
122
        // Not sure this can happen. So just in case
123
        if ($response == '') {
124
            throw new ConversionFailedException('ewww api did not return anything');
125
        }
126
127
        $success = file_put_contents($this->destination, $response);
128
129
        if (!$success) {
130
            throw new ConversionFailedException('Error saving file');
131
        }
132
    }
133
134
    /**
135
     *  Keep subscription alive by optimizing a jpeg
136
     *  (ewww closes accounts after 6 months of inactivity - and webp conversions seems not to be counted? )
137
     */
138
    public static function keepSubscriptionAlive($source, $key)
139
    {
140
        try {
141
            $ch = curl_init();
142
        } catch (\Exception $e) {
143
            return 'curl is not installed';
144
        }
145
        if ($ch === false) {
146
            return 'curl could not be initialized';
147
        }
148
        curl_setopt_array(
149
            $ch,
150
            [
151
            CURLOPT_URL => "https://optimize.exactlywww.com/v2/",
152
            CURLOPT_HTTPHEADER => [
153
                'User-Agent: WebPConvert',
154
                'Accept: image/*'
155
            ],
156
            CURLOPT_POSTFIELDS => [
157
                'api_key' => $key,
158
                'webp' => '0',
159
                'file' => curl_file_create($source),
160
                'domain' => $_SERVER['HTTP_HOST'],
161
                'quality' => 60,
162
                'metadata' => 0
163
            ],
164
            CURLOPT_BINARYTRANSFER => true,
165
            CURLOPT_RETURNTRANSFER => true,
166
            CURLOPT_HEADER => false,
167
            CURLOPT_SSL_VERIFYPEER => false
168
            ]
169
        );
170
171
        $response = curl_exec($ch);
172
        if (curl_errno($ch)) {
173
            return 'curl error' . curl_error($ch);
174
        }
175
        if (curl_getinfo($ch, CURLINFO_CONTENT_TYPE) != 'application/octet-stream') {
176
            curl_close($ch);
177
178
            /* May return this: {"error":"invalid","t":"exceeded"} */
179
            $responseObj = json_decode($response);
180
            if (isset($responseObj->error)) {
181
                return 'The key is invalid';
182
            }
183
184
            return 'ewww api did not return an image. It could be that the key is invalid. Response: ' . $response;
185
        }
186
187
        // Not sure this can happen. So just in case
188
        if ($response == '') {
189
            return 'ewww api did not return anything';
190
        }
191
192
        return true;
193
    }
194
195
    /*
196
        public static function blacklistKey($key)
197
        {
198
        }
199
200
        public static function isKeyBlacklisted($key)
201
        {
202
        }*/
203
204
    /**
205
     *  Return "great", "exceeded" or "invalid"
206
     */
207 2
    public static function getKeyStatus($key)
208
    {
209 2
        $ch = self::initCurl();
210
211 2
        curl_setopt($ch, CURLOPT_URL, "https://optimize.exactlywww.com/verify/");
212 2
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
213 2
        curl_setopt(
214 2
            $ch,
215 2
            CURLOPT_POSTFIELDS,
216
            [
217
            'api_key' => $key
218 2
            ]
219 2
        );
220
221
        // The 403 forbidden is avoided with this line.
222 2
        curl_setopt(
223 2
            $ch,
224 2
            CURLOPT_USERAGENT,
225
            'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)'
226 2
        );
227
228 2
        $response = curl_exec($ch);
229
        // echo $response;
230 2
        if (curl_errno($ch)) {
231
            throw new \Exception(curl_error($ch));
232
        }
233 2
        curl_close($ch);
234
235
        // Possible responses:
236
        // “great” = verification successful
237
        // “exceeded” = indicates a valid key with no remaining image credits.
238
        // an empty response indicates that the key is not valid
239
240 2
        if ($response == '') {
241
            return 'invalid';
242
        }
243 2
        $responseObj = json_decode($response);
244 2
        if (isset($responseObj->error)) {
245 2
            if ($responseObj->error == 'invalid') {
246 2
                return 'invalid';
247
            } else {
248
                throw new \Exception('Ewww returned unexpected error: ' . $response);
249
            }
250
        }
251 1
        if (!isset($responseObj->status)) {
252
            throw new \Exception('Ewww returned unexpected response to verify request: ' . $response);
253
        }
254 1
        switch ($responseObj->status) {
255 1
            case 'great':
256 1
            case 'exceeded':
257 1
                return $responseObj->status;
258
        }
259
        throw new \Exception('Ewww returned unexpected status to verify request: "' . $responseObj->status . '"');
260
    }
261
262 1
    public static function isWorkingKey($key)
263
    {
264 1
        return (self::getKeyStatus($key) == 'great');
265
    }
266
267 1
    public static function isValidKey($key)
268
    {
269 1
        return (self::getKeyStatus($key) != 'invalid');
270
    }
271
272
    public static function getQuota($key)
273
    {
274
        $ch = self::initCurl();
275
276
        curl_setopt($ch, CURLOPT_URL, "https://optimize.exactlywww.com/quota/");
277
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
278
        curl_setopt(
279
            $ch,
280
            CURLOPT_POSTFIELDS,
281
            [
282
            'api_key' => $key
283
            ]
284
        );
285
        curl_setopt(
286
            $ch,
287
            CURLOPT_USERAGENT,
288
            'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)'
289
        );
290
291
        $response = curl_exec($ch);
292
        return $response; // ie -830 23. Seems to return empty for invalid keys
293
        // or empty
294
        //echo $response;
295
    }
296
}
297