Completed
Push — master ( f155bf...0ec113 )
by Sam
02:35
created

GoogleCloudVision::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * This file contains only the GoogleCloudVision class.
4
 */
5
6
namespace Wikisource\GoogleCloudVisionPHP;
7
8
use Exception;
9
10
class GoogleCloudVision
11
{
12
13
    protected $features = array();
14
    protected $imageContext = array();
15
    protected $image = array();
16
    protected $requestBody = array();
17
    protected $version = "v1";
18
    protected $endpoint = "https://vision.googleapis.com/";
19
    protected $key;
20
21
    /** @var int The maximum size allowed for the image, in bytes. */
22
    protected $imageMaxSize;
23
24
    /** @var string Image type: Google Cloud Storage URI. Note the typo. */
25
    const IMAGE_TYPE_GCS = 'GSC';
26
27
    /** @var string Image type: file path or URL. */
28
    const IMAGE_TYPE_FILE = 'FILE';
29
30
    /** @var string Image type: raw data. */
31
    const IMAGE_TYPE_RAW = 'RAW';
32
33
    /**
34
     * Create a new GCV API object.
35
     */
36
    public function __construct()
37
    {
38
        $this->imageMaxSize = 1024 * 1024 * 4;
39
    }
40
41
    /**
42
     * Change the URL for the API endpoint. Defaults to https://vision.googleapis.com/ but may need to be changed for
43
     * various reasons (e.g. if routing through a proxy server).
44
     *
45
     * @param string $newEndpoint The new URL of the API endpoint.
46
     */
47
    public function setEndpoint($newEndpoint)
48
    {
49
        $this->endpoint = $newEndpoint;
50
    }
51
52
    /**
53
     * Set the permitted maximum size of images.
54
     * This defaults to 4 MB as per the Google Clound Vision API limits documentation.
55
     *
56
     * @param ing $newSize
57
     * @throws Exception
58
     */
59
    public function setImageMaxSize($newSize)
60
    {
61
        if (!is_int($newSize)) {
62
            throw new Exception("Image size must be specified in integer bytes, '$newSize' given");
63
        }
64
        $this->imageMaxSize = $newSize;
65
    }
66
67
    /**
68
     * Set the image that will be sent to the API.
69
     *
70
     * An image can be set from a filename or URL, raw data, or a Google Cloud Storage item.
71
     *
72
     * A Google Cloud Storage image URI must be in the following form: gs://bucket_name/object_name.
73
     * Object versioning is not supported.
74
     * Read more: https://cloud.google.com/vision/reference/rest/v1/images/annotate#imagesource
75
     *
76
     * @param mixed $input The filename, URL, data, etc.
77
     * @param string $type The type that $input should be treated as.
78
     * @return string[] The request body.
79
     * @throws LimitExceededException When the image size is over the maximum permitted.
80
     */
81
    public function setImage($input, $type = self::IMAGE_TYPE_FILE)
82
    {
83
        if ($type === self::IMAGE_TYPE_GCS) {
84
            $this->image['source']['gcsImageUri'] = $input;
85
        } elseif ($type === self::IMAGE_TYPE_FILE) {
86
            $this->image['content'] = $this->convertImgtoBased64($input);
87
        } elseif ($type === self::IMAGE_TYPE_RAW) {
88
            $size = strlen($input);
89
            if ($size > $this->imageMaxSize) {
90
                throw new LimitExceededException("Image size ($size) exceeds permitted size ($this->imageMaxSize)", 1);
91
            }
92
            $this->image['content'] = base64_encode($input);
93
        }
94
        return $this->setRequestBody();
95
    }
96
97
    /**
98
     * Fetch base64-encoded data of the specified image.
99
     *
100
     * @param string $path Path to the image file. Anything supported by file_get_contents is suitable.
101
     * @return string The encoded data as a string or FALSE on failure.
102
     * @throws LimitExceededException When the image size is over the maximum permitted.
103
     */
104
    public function convertImgtoBased64($path)
105
    {
106
        // Get the data.
107
        $data = file_get_contents($path);
108
        // Check the size.
109
        $size = strlen($data);
110
        if ($size > $this->imageMaxSize) {
111
            $msg = "Image size of %s (%s) exceeds permitted size (%s)";
112
            throw new LimitExceededException(sprintf($msg, $path, $size, $this->imageMaxSize), 2);
113
        }
114
        // Return encoded data.
115
        return base64_encode($data);
116
    }
117
118
    /**
119
     * Set the request body, based on the image, features, and imageContext.
120
     *
121
     * @return string[]
122
     */
123
    protected function setRequestBody()
124
    {
125
        if (!empty($this->image)) {
126
            $this->requestBody['requests'][0]['image'] = $this->image;
127
        }
128
        if (!empty($this->features)) {
129
            $this->requestBody['requests'][0]['features'] = $this->features;
130
        }
131
        if (!empty($this->imageContext)) {
132
            $this->requestBody['requests'][0]['imageContext'] = $this->imageContext;
133
        }
134
        return $this->requestBody;
135
    }
136
137
    public function addFeature($type, $maxResults = 1)
138
    {
139
140
        if (!is_numeric($maxResults)) {
141
            throw new Exception("maxResults variable is not valid it should be Integer.", 1);
142
        }
143
144
        $this->features[] = array("type" => $type, "maxResults" => $maxResults);
145
        return $this->setRequestBody();
146
    }
147
148
    public function setImageContext($imageContext)
149
    {
150
        if (!is_array($imageContext)) {
151
            throw new Exception("imageContext variable is not valid it should be Array.", 1);
152
        }
153
        $this->imageContext = $imageContext;
154
        return $this->setRequestBody();
155
    }
156
157
    public function addFeatureUnspecified($maxResults = 1)
158
    {
159
        return $this->addFeature("TYPE_UNSPECIFIED", $maxResults);
160
    }
161
162
    public function addFeatureFaceDetection($maxResults = 1)
163
    {
164
        return $this->addFeature("FACE_DETECTION", $maxResults);
165
    }
166
167
    public function addFeatureLandmarkDetection($maxResults = 1)
168
    {
169
        return $this->addFeature("LANDMARK_DETECTION", $maxResults);
170
    }
171
172
    public function addFeatureLogoDetection($maxResults = 1)
173
    {
174
        return $this->addFeature("LOGO_DETECTION", $maxResults);
175
    }
176
177
    public function addFeatureLabelDetection($maxResults = 1)
178
    {
179
        return $this->addFeature("LABEL_DETECTION", $maxResults);
180
    }
181
182
    public function addFeatureOCR($maxResults = 1)
183
    {
184
        return $this->addFeature("TEXT_DETECTION", $maxResults);
185
    }
186
187
    public function addFeatureSafeSeachDetection($maxResults = 1)
188
    {
189
        return $this->addFeature("SAFE_SEARCH_DETECTION", $maxResults);
190
    }
191
192
    public function addFeatureImageProperty($maxResults = 1)
193
    {
194
        return $this->addFeature("IMAGE_PROPERTIES", $maxResults);
195
    }
196
197
    /**
198
     * Send the request to Google and get the results.
199
     *
200
     * @param string $apiMethod Which API method to use. Currently can only be 'annotate'.
201
     *
202
     * @return string[] The results of the request.
203
     * @throws Exception If any of the key, features, or image have not been set yet.
204
     */
205
    public function request($apiMethod = "annotate")
206
    {
207
        if (empty($this->key) === true) {
208
            $msg = "API Key is empty, please grant from https://console.cloud.google.com/apis/credentials";
209
            throw new Exception($msg);
210
        }
211
212
        if (empty($this->features) === true) {
213
            throw new Exception("Features is can't empty.", 1);
214
        }
215
216
        if (empty($this->image) === true) {
217
            throw new Exception("Images is can't empty.", 1);
218
        }
219
220
        $url = $this->endpoint.$this->version."/images:$apiMethod?key=".$this->key;
221
        return $this->requestServer($url, $this->requestBody);
222
    }
223
224
    /**
225
     * Set the API key.
226
     *
227
     * @param string $key The API key.
228
     *
229
     * @return void
230
     */
231
    public function setKey($key)
232
    {
233
        $this->key = $key;
234
    }
235
236
    /**
237
     * Execute the request and return the result.
238
     *
239
     * @param string $url The full URL to query.
240
     * @param string[] $data The data to send.
241
     *
242
     * @return string[] The resulting information about the image.
243
     */
244
    protected function requestServer($url, $data)
245
    {
246
        $ch = curl_init();
247
        curl_setopt($ch, CURLOPT_URL, $url);
248
        curl_setopt($ch, CURLOPT_HEADER, 0);
249
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
250
        curl_setopt($ch, CURLOPT_POST, 1);
251
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
252
        curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
253
        $res = json_decode(curl_exec($ch), true);
254
        return $res;
255
    }
256
}
257