Completed
Push — master ( 01d30b...b017f2 )
by Sam
02:12
created

GoogleCloudVision::request()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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