diff --git a/docs/toc.json b/docs/toc.json index 447db977acce..2585883aafbb 100644 --- a/docs/toc.json +++ b/docs/toc.json @@ -166,12 +166,42 @@ { "title": "Vision", "type": "vision/visionclient", + "patterns": [ + "/vision" + ], "nav": [{ "title": "Image", "type": "vision/image" }, { "title": "Annotation", - "type": "vision/annotation" + "type": "vision/annotation", + "patterns": [ + "/vision/annotation" + ], + "nav": [ + { + "title": "CropHint", + "type": "vision/annotation/crophint" + }, { + "title": "Document", + "type": "vision/annotation/document" + }, { + "title": "Entity", + "type": "vision/annotation/entity" + }, { + "title": "Face", + "type": "vision/annotation/face" + }, { + "title": "ImageProperties", + "type": "vision/annotation/imageproperties" + }, { + "title": "SafeSearch", + "type": "vision/annotation/safesearch" + }, { + "title": "Web", + "type": "vision/annotation/web" + } + ] }] } ] diff --git a/src/Vision/Annotation.php b/src/Vision/Annotation.php index 3187770600c9..321af9cbfa8c 100644 --- a/src/Vision/Annotation.php +++ b/src/Vision/Annotation.php @@ -17,10 +17,13 @@ namespace Google\Cloud\Vision; +use Google\Cloud\Vision\Annotation\CropHint; +use Google\Cloud\Vision\Annotation\Document; use Google\Cloud\Vision\Annotation\Entity; use Google\Cloud\Vision\Annotation\Face; use Google\Cloud\Vision\Annotation\ImageProperties; use Google\Cloud\Vision\Annotation\SafeSearch; +use Google\Cloud\Vision\Annotation\Web; /** * Represents a [Google Cloud Vision](https://cloud.google.com/vision) image @@ -33,7 +36,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, [ * 'FACE_DETECTION' * ]); @@ -49,42 +52,57 @@ class Annotation private $info; /** - * @var array + * @var Face[]|null */ private $faces; /** - * @var array + * @var Entity[]|null */ private $landmarks; /** - * @var array + * @var Entity[]|null */ private $logos; /** - * @var array + * @var Entity[]|null */ private $labels; /** - * @var array + * @var Entity[]|null */ private $text; /** - * @var SafeSearch + * @var Document|null + */ + private $fullText; + + /** + * @var SafeSearch|null */ private $safeSearch; /** - * @var ImageProperties + * @var ImageProperties|null */ private $imageProperties; /** - * @var array + * @var CropHint[]|null + */ + private $cropHints; + + /** + * @var Web|null + */ + private $web; + + /** + * @var array|null */ private $error; @@ -142,6 +160,10 @@ public function __construct($info) } } + if (isset($info['fullTextAnnotation'])) { + $this->fullText = new Document($info['fullTextAnnotation']); + } + if (isset($info['safeSearchAnnotation'])) { $this->safeSearch = new SafeSearch($info['safeSearchAnnotation']); } @@ -150,6 +172,17 @@ public function __construct($info) $this->imageProperties = new ImageProperties($info['imagePropertiesAnnotation']); } + if (isset($info['cropHintsAnnotation']) && is_array($info['cropHintsAnnotation']['cropHints'])) { + $this->cropHints = []; + foreach ($info['cropHintsAnnotation']['cropHints'] as $hint) { + $this->cropHints[] = new CropHint($hint); + } + } + + if (isset($info['webDetection'])) { + $this->web = new Web($info['webDetection']); + } + if (isset($info['error'])) { $this->error = $info['error']; } @@ -249,6 +282,23 @@ public function text() return $this->text; } + /** + * Return the full text annotation. + * + * Example: + * ``` + * $fullText = $annotation->fullText(); + * ``` + * + * @see https://cloud.google.com/vision/reference/rest/v1/images/annotate#fulltextannotation FullTextAnnotation + * + * @return Document|null + */ + public function fullText() + { + return $this->fullText; + } + /** * Get the result of a safe search detection * @@ -279,6 +329,36 @@ public function imageProperties() return $this->imageProperties; } + /** + * Fetch Crop Hints + * + * Example: + * ``` + * $hints = $annotation->cropHints(); + * ``` + * + * @return CropHint[]|null + */ + public function cropHints() + { + return $this->cropHints; + } + + /** + * Fetch the Web Annotatation. + * + * Example: + * ``` + * $web = $annotation->web(); + * ``` + * + * @return Web|null + */ + public function web() + { + return $this->web; + } + /** * Get error information, if present * diff --git a/src/Vision/Annotation/CropHint.php b/src/Vision/Annotation/CropHint.php new file mode 100644 index 000000000000..36c1eee94167 --- /dev/null +++ b/src/Vision/Annotation/CropHint.php @@ -0,0 +1,83 @@ +vision(); + * + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); + * $image = $vision->image($imageResource, [ 'CROP_HINTS' ]); + * $annotation = $vision->annotate($image); + * + * $hints = $annotation->cropHints(); + * $hint = $hints[0]; + * ``` + * + * @method boundingPoly() { + * The bounding polygon of the recommended crop. + * + * Example: + * ``` + * $poly = $hint->boundingPoly(); + * ``` + * + * @return array [BoundingPoly](https://cloud.google.com/vision/docs/reference/rest/v1/images/annotate#boundingpoly) + * } + * @method confidence() { + * Confidence of this being a salient region. Range [0, 1]. + * + * Example: + * ``` + * $confidence = $hint->confidence(); + * ``` + * + * @return float + * } + * @method importanceFraction() { + * Fraction of importance of this salient region with respect to the + * original image. + * + * Example: + * ``` + * $importance = $hint->importanceFraction(); + * ``` + * + * @return float + * } + */ +class CropHint extends AbstractFeature +{ + use CallTrait; + + /** + * @param array $info Crop Hint result + */ + public function __construct(array $info) + { + $this->info = $info; + } +} diff --git a/src/Vision/Annotation/Document.php b/src/Vision/Annotation/Document.php new file mode 100644 index 000000000000..48e5915a8665 --- /dev/null +++ b/src/Vision/Annotation/Document.php @@ -0,0 +1,81 @@ +vision(); + * + * $imageResource = fopen(__DIR__ . '/assets/the-constitution.jpg', 'r'); + * $image = $vision->image($imageResource, [ 'DOCUMENT_TEXT_DETECTION' ]); + * $annotation = $vision->annotate($image); + * + * $document = $annotation->fullText(); + * ``` + * + * @method pages() { + * Get the document pages. + * + * Example: + * ``` + * $pages = $document->pages(); + * ``` + * + * @return array + * } + * @method text() { + * Get the document text. + * + * Example: + * ``` + * $text = $document->text(); + * ``` + * + * @return string + * } + * @method info() { + * Get the Document Text detection result. + * + * Example: + * ``` + * $info = $document->info(); + * ``` + * + * @return array + * } + */ +class Document extends AbstractFeature +{ + use CallTrait; + + /** + * @param array $info Document Text Annotation response. + */ + public function __construct(array $info) + { + $this->info = $info; + } +} diff --git a/src/Vision/Annotation/Entity.php b/src/Vision/Annotation/Entity.php index a7a988a3046a..937ea4563498 100644 --- a/src/Vision/Annotation/Entity.php +++ b/src/Vision/Annotation/Entity.php @@ -31,7 +31,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, [ 'text' ]); * $annotation = $vision->annotate($image); * diff --git a/src/Vision/Annotation/Face.php b/src/Vision/Annotation/Face.php index eca4d39591a2..6b1369b0809f 100644 --- a/src/Vision/Annotation/Face.php +++ b/src/Vision/Annotation/Face.php @@ -30,7 +30,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, [ 'FACE_DETECTION' ]); * $annotation = $vision->annotate($image); * diff --git a/src/Vision/Annotation/Face/Landmarks.php b/src/Vision/Annotation/Face/Landmarks.php index b0688ef05ff5..5dbb3f5c8fbb 100644 --- a/src/Vision/Annotation/Face/Landmarks.php +++ b/src/Vision/Annotation/Face/Landmarks.php @@ -29,7 +29,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, ['FACE_DETECTION']); * $annotation = $vision->annotate($image); * diff --git a/src/Vision/Annotation/ImageProperties.php b/src/Vision/Annotation/ImageProperties.php index e936b6a75d3a..9b6649c91024 100644 --- a/src/Vision/Annotation/ImageProperties.php +++ b/src/Vision/Annotation/ImageProperties.php @@ -27,7 +27,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, [ 'imageProperties' ]); * $annotation = $vision->annotate($image); * diff --git a/src/Vision/Annotation/SafeSearch.php b/src/Vision/Annotation/SafeSearch.php index 46d34f86bcf4..8e3781f0f481 100644 --- a/src/Vision/Annotation/SafeSearch.php +++ b/src/Vision/Annotation/SafeSearch.php @@ -29,7 +29,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, [ 'safeSearch' ]); * $annotation = $vision->annotate($image); * diff --git a/src/Vision/Annotation/Web.php b/src/Vision/Annotation/Web.php new file mode 100644 index 000000000000..f384be49c3a1 --- /dev/null +++ b/src/Vision/Annotation/Web.php @@ -0,0 +1,170 @@ +vision(); + * + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); + * $image = $vision->image($imageResource, [ 'WEB_DETECTION' ]); + * $annotation = $vision->annotate($image); + * + * $web = $annotation->web(); + * ``` + */ +class Web extends AbstractFeature +{ + /** + * @var WebEntity[] + */ + private $entities; + + /** + * @var WebImage[]|null + */ + private $matchingImages; + + /** + * @var WebImage[]|null + */ + private $partialMatchingImages; + + /** + * @var WebPage[]|null + */ + private $pages; + + /** + * Create a Web result. + * + * @param array $info The annotation result + */ + public function __construct(array $info) + { + $this->info = $info; + + if (isset($info['webEntities'])) { + $this->entities = []; + + foreach ($info['webEntities'] as $entity) { + $this->entities[] = new WebEntity($entity); + } + } + + if (isset($info['fullMatchingImages'])) { + $this->matchingImages = []; + + foreach ($info['fullMatchingImages'] as $image) { + $this->matchingImages[] = new WebImage($image); + } + } + + if (isset($info['partialMatchingImages'])) { + $this->partialMatchingImages = []; + + foreach ($info['partialMatchingImages'] as $image) { + $this->partialMatchingImages[] = new WebImage($image); + } + } + + if (isset($info['pagesWithMatchingImages'])) { + $this->pages = []; + + foreach ($info['pagesWithMatchingImages'] as $page) { + $this->pages[] = new WebPage($page); + } + } + } + + /** + * Entities deduced from similar images on the Internet. + * + * Example: + * ``` + * $entities = $web->entities(); + * ``` + * + * @return WebEntity[]|null + */ + public function entities() + { + return $this->entities; + } + + /** + * Fully matching images from the internet. + * + * Images are most likely near duplicates, and most often are a copy of the + * given query image with a size change. + * + * Example: + * ``` + * $images = $web->matchingImages(); + * ``` + * + * @return WebImage[]|null + */ + public function matchingImages() + { + return $this->matchingImages; + } + + /** + * Partial matching images from the Internet. + * + * Those images are similar enough to share some key-point features. For + * example an original image will likely have partial matching for its crops. + * + * Example: + * ``` + * $images = $web->partialMatchingImages(); + * ``` + * + * @return WebImage[]|null + */ + public function partialMatchingImages() + { + return $this->partialMatchingImages; + } + + /** + * Web pages containing the matching images from the Internet. + * + * Example: + * ``` + * $pages = $web->pages(); + * ``` + * + * @return WebPage[]|null + */ + public function pages() + { + return $this->pages; + } +} diff --git a/src/Vision/Annotation/Web/WebEntity.php b/src/Vision/Annotation/Web/WebEntity.php new file mode 100644 index 000000000000..a6ef07e7a4ae --- /dev/null +++ b/src/Vision/Annotation/Web/WebEntity.php @@ -0,0 +1,85 @@ +vision(); + * + * $imageResource = fopen(__DIR__ . '/assets/eiffel-tower.jpg', 'r'); + * $image = $vision->image($imageResource, ['WEB_DETECTION']); + * $annotation = $vision->annotate($image); + * + * $entities = $annotation->web()->entities(); + * $firstEntity = $entities[0]; + * ``` + * + * @method entityId() { + * The Entity ID + * + * Example: + * ``` + * $id = $entity->entityId(); + * ``` + * + * @return string + * } + * @method score() { + * Overall relevancy score for the image. + * + * Not normalized and not comparable across different image queries. + * + * Example: + * ``` + * $score = $entity->score(); + * ``` + * + * @return float + * } + * @method description() { + * Canonical description of the entity, in English. + * + * Example: + * ``` + * $description = $entity->description(); + * ``` + * + * @return string + * } + */ +class WebEntity extends AbstractFeature +{ + use CallTrait; + + /** + * @param array $info WebEntity info + */ + public function __construct(array $info) + { + $this->info = $info; + } +} diff --git a/src/Vision/Annotation/Web/WebImage.php b/src/Vision/Annotation/Web/WebImage.php new file mode 100644 index 000000000000..6481628ad9be --- /dev/null +++ b/src/Vision/Annotation/Web/WebImage.php @@ -0,0 +1,75 @@ +vision(); + * + * $imageResource = fopen(__DIR__ . '/assets/eiffel-tower.jpg', 'r'); + * $image = $vision->image($imageResource, ['WEB_DETECTION']); + * $annotation = $vision->annotate($image); + * + * $matchingImages = $annotation->web()->matchingImages(); + * $firstImage = $matchingImages[0]; + * ``` + * + * @method url() { + * The result image URL + * + * Example: + * ``` + * $url = $image->url(); + * ``` + * + * @return string + * } + * @method score() { + * Overall relevancy score for the image. + * + * Not normalized and not comparable across different image queries. + * + * Example: + * ``` + * $score = $image->score(); + * ``` + * + * @return float + * } + */ +class WebImage extends AbstractFeature +{ + use CallTrait; + + /** + * @param array $info The WebImage result + */ + public function __construct(array $info) + { + $this->info = $info; + } +} diff --git a/src/Vision/Annotation/Web/WebPage.php b/src/Vision/Annotation/Web/WebPage.php new file mode 100644 index 000000000000..1d229be56fec --- /dev/null +++ b/src/Vision/Annotation/Web/WebPage.php @@ -0,0 +1,75 @@ +vision(); + * + * $imageResource = fopen(__DIR__ . '/assets/eiffel-tower.jpg', 'r'); + * $image = $vision->image($imageResource, ['WEB_DETECTION']); + * $annotation = $vision->annotate($image); + * + * $pages = $annotation->web()->pages(); + * $firstPage = $pages[0]; + * ``` + * + * @method url() { + * The result web page URL + * + * Example: + * ``` + * $url = $image->url(); + * ``` + * + * @return string + * } + * @method score() { + * Overall relevancy score for the image. + * + * Not normalized and not comparable across different image queries. + * + * Example: + * ``` + * $score = $image->score(); + * ``` + * + * @return float + * } + */ +class WebPage extends AbstractFeature +{ + use CallTrait; + + /** + * @param array $info The WebPage result + */ + public function __construct(array $info) + { + $this->info = $info; + } +} diff --git a/src/Vision/Connection/ServiceDefinition/vision-v1.json b/src/Vision/Connection/ServiceDefinition/vision-v1.json index 329a854b0671..2bcdadacfcae 100644 --- a/src/Vision/Connection/ServiceDefinition/vision-v1.json +++ b/src/Vision/Connection/ServiceDefinition/vision-v1.json @@ -44,6 +44,10 @@ "gcsImageUri": { "description": "Google Cloud Storage image URI. It must be in the following form:\n`gs://bucket_name/object_name`. For more\ndetails, please see: https://cloud.google.com/storage/docs/reference-uris.\nNOTE: Cloud Storage object versioning is not supported!", "type": "string" + }, + "ImageUri": { + "description": "Image URI which supports: 1) Google Cloud Storage image URI, which must be in the following form: `gs://bucket_name/object_name` (for details, see [Google Cloud Storage Request URIs](https://cloud.google.com/storage/docs/reference-uris)). NOTE: Cloud Storage object versioning is not supported. 2) Publicly accessible image HTTP/HTTPS URL. This is preferred over the legacy `gcs_image_uri` above. When both `gcs_image_uri` and `image_uri` are specified, `image_uri` takes precedence.", + "type": "string" } }, "id": "ImageSource" @@ -761,8 +765,11 @@ "LOGO_DETECTION", "LABEL_DETECTION", "TEXT_DETECTION", + "DOCUMENT_TEXT_DETECTION", "SAFE_SEARCH_DETECTION", - "IMAGE_PROPERTIES" + "IMAGE_PROPERTIES", + "CROP_HINTS", + "WEB_DETECTION" ], "enumDescriptions": [ "Unspecified feature type.", @@ -771,8 +778,11 @@ "Run logo detection.", "Run label detection.", "Run OCR.", + "Run dense text document OCR. Takes precedence when both DOCUMENT_TEXT_DETECTION and TEXT_DETECTION are present.", "Run various computer vision models to compute image safe-search properties.", - "Compute a set of properties about the image (such as the image's dominant colors)." + "Compute a set of properties about the image (such as the image's dominant colors).", + "Run crop hints.", + "Run web annotation." ], "type": "string" }, diff --git a/src/Vision/Image.php b/src/Vision/Image.php index 50e8f2e85404..5e3dceeaacfd 100644 --- a/src/Vision/Image.php +++ b/src/Vision/Image.php @@ -47,7 +47,7 @@ * $cloud = new ServiceBuilder(); * $vision = $cloud->vision(); * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = $vision->image($imageResource, [ * 'FACE_DETECTION' * ]); @@ -58,7 +58,7 @@ * // Images can be directly instantiated. * use Google\Cloud\Vision\Image; * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = new Image($imageResource, [ * 'FACE_DETECTION' * ]); @@ -94,7 +94,7 @@ * * use Google\Cloud\Vision\Image; * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = new Image($imageResource, [ * 'FACE_DETECTION', * 'LOGO_DETECTION' @@ -123,15 +123,18 @@ * * use Google\Cloud\Vision\Image; * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = new Image($imageResource, [ * 'faces', // Corresponds to `FACE_DETECTION` * 'landmarks', // Corresponds to `LANDMARK_DETECTION` * 'logos', // Corresponds to `LOGO_DETECTION` * 'labels', // Corresponds to `LABEL_DETECTION` - * 'text', // Corresponds to `TEXT_DETECTION` + * 'text', // Corresponds to `TEXT_DETECTION`, + * 'document', // Corresponds to `DOCUMENT_TEXT_DETECTION` * 'safeSearch', // Corresponds to `SAFE_SEARCH_DETECTION` - * 'imageProperties' // Corresponds to `IMAGE_PROPERTIES` + * 'imageProperties',// Corresponds to `IMAGE_PROPERTIES` + * 'crop', // Corresponds to `CROP_HINTS` + * 'web' // Corresponds to `WEB_DETECTION` * ]); * ``` * @@ -141,8 +144,8 @@ class Image { const TYPE_BYTES = 'bytes'; - const TYPE_STORAGE = 'storage'; const TYPE_STRING = 'string'; + const TYPE_URI = 'uri'; /** * @var mixed @@ -166,16 +169,31 @@ class Image /** * A map of short names to identifiers recognized by Cloud Vision. + * * @var array */ private $featureShortNames = [ - 'faces' => 'FACE_DETECTION', - 'landmarks' => 'LANDMARK_DETECTION', - 'logos' => 'LOGO_DETECTION', - 'labels' => 'LABEL_DETECTION', - 'text' => 'TEXT_DETECTION', - 'safeSearch' => 'SAFE_SEARCH_DETECTION', - 'imageProperties' => 'IMAGE_PROPERTIES' + 'faces' => 'FACE_DETECTION', + 'landmarks' => 'LANDMARK_DETECTION', + 'logos' => 'LOGO_DETECTION', + 'labels' => 'LABEL_DETECTION', + 'text' => 'TEXT_DETECTION', + 'document' => 'DOCUMENT_TEXT_DETECTION', + 'safeSearch' => 'SAFE_SEARCH_DETECTION', + 'imageProperties' => 'IMAGE_PROPERTIES', + 'crop' => 'CROP_HINTS', + 'web' => 'WEB_DETECTION' + ]; + + /** + * A list of allowed url schemes. + * + * @var array + */ + private $urlSchemes = [ + 'http', + 'https', + 'gs' ]; /** @@ -183,15 +201,15 @@ class Image * * @param resource|string|StorageObject $image An image to configure with * the given settings. This parameter will accept a resource, a - * string of bytes, or an instance of - * {@see Google\Cloud\Storage\StorageObject}. + * string of bytes, the URI of an image in a publicly-accessible + * web location, or an instance of {@see Google\Cloud\Storage\StorageObject}. * @param array $features A list of cloud vision * [features](https://cloud.google.com/vision/reference/rest/v1/images/annotate#type) * to apply to the image. Google Cloud Platform Client Library provides a set of abbreviated * names which can be used in the interest of brevity in place of * the names offered by the cloud vision service. These names are - * `faces`, `landmarks`, `logos`, `labels`, `text`, `safeSearch` - * and `imageProperties`. + * `faces`, `landmarks`, `logos`, `labels`, `text`, `document`, + * `safeSearch`, `imageProperties`, `crop`, and `web`. * @param array $options { * Configuration Options * @@ -218,22 +236,24 @@ public function __construct($image, array $features, array $options = []) $this->features = $this->normalizeFeatures($features); - if ($image instanceof StorageObject) { + $this->image = $image; + if (is_string($image) && in_array(parse_url($image, PHP_URL_SCHEME), $this->urlSchemes)) { + $this->type = self::TYPE_URI; + } elseif (is_string($image)) { + $this->type = self::TYPE_STRING; + } elseif ($image instanceof StorageObject) { $identity = $image->identity(); $uri = sprintf('gs://%s/%s', $identity['bucket'], $identity['object']); - $this->type = self::TYPE_STORAGE; + $this->type = self::TYPE_URI; $this->image = $uri; - } elseif (is_string($image)) { - $this->type = self::TYPE_STRING; - $this->image = $image; } elseif (is_resource($image)) { $this->type = self::TYPE_BYTES; $this->image = Psr7\stream_for($image); } else { throw new InvalidArgumentException( 'Given image is not valid. ' . - 'Image must be a string of bytes, a google storage object, or a resource.' + 'Image must be a string of bytes, a google storage object, a valid image URI, or a resource.' ); } } @@ -248,7 +268,7 @@ public function __construct($image, array $features, array $options = []) * ``` * use Google\Cloud\Vision\Image; * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * $image = new Image($imageResource, [ * 'FACE_DETECTION' * ]); @@ -302,7 +322,7 @@ private function imageObject($encode) return [ 'source' => [ - 'gcsImageUri' => $this->image + 'imageUri' => $this->image ] ]; } diff --git a/src/Vision/VisionClient.php b/src/Vision/VisionClient.php index d44aa345149c..3ee0eb437477 100644 --- a/src/Vision/VisionClient.php +++ b/src/Vision/VisionClient.php @@ -24,7 +24,7 @@ use Psr\Cache\CacheItemPoolInterface; /** - * Google Cloud Vision client allows you to understand the content of an image, + * Google Cloud Vision allows you to understand the content of an image, * classify images into categories, detect text, objects, faces and more. Find * more information at * [Google Cloud Vision docs](https://cloud.google.com/vision/docs/). @@ -110,7 +110,7 @@ public function __construct(array $config = []) * * Example: * ``` - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * * $image = $vision->image($imageResource, [ * 'FACE_DETECTION' @@ -120,7 +120,7 @@ public function __construct(array $config = []) * ``` * // Setting maxResults for a feature * - * $imageResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * * $image = $vision->image($imageResource, [ * 'FACE_DETECTION' @@ -133,8 +133,8 @@ public function __construct(array $config = []) * * @param resource|string|StorageObject $image An image to configure with * the given settings. This parameter will accept a resource, a - * string of bytes, or an instance of - * {@see Google\Cloud\Storage\StorageObject}. + * string of bytes, the URI of an image in a publicly-accessible + * web location, or an instance of {@see Google\Cloud\Storage\StorageObject}. * @param array $features A list of cloud vision * [features](https://cloud.google.com/vision/reference/rest/v1/images/annotate#type) * to apply to the image. @@ -169,8 +169,8 @@ public function image($image, array $features, array $options = []) * // In the example below, both images will have the same settings applied. * // They will both run face detection and return up to 10 results. * - * $familyPhotoResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); - * $weddingPhotoResource = fopen(__DIR__ .'/assets/wedding-photo.jpg', 'r'); + * $familyPhotoResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); + * $weddingPhotoResource = fopen(__DIR__ . '/assets/wedding-photo.jpg', 'r'); * * $images = $vision->images([$familyPhotoResource, $weddingPhotoResource], [ * 'FACE_DETECTION' @@ -183,7 +183,8 @@ public function image($image, array $features, array $options = []) * * @param resource[]|string[]|StorageObject[] $images An array of images * to configure with the given settings. Each member of the set can - * be a resource, a string of bytes, or an instance of + * be a resource, a string of bytes, the URI of an image in a + * publicly-accessible web location, or an instance of * {@see Google\Cloud\Storage\StorageObject}. * @param array $features A list of cloud vision features to apply to each image. * @param array $options See {@see Google\Cloud\Vision\Image::__construct()} for @@ -206,7 +207,7 @@ public function images(array $images, array $features, array $options = []) * * Example: * ``` - * $familyPhotoResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); + * $familyPhotoResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); * * $image = $vision->image($familyPhotoResource, [ * 'FACE_DETECTION' @@ -232,8 +233,8 @@ public function annotate(Image $image, array $options = []) * ``` * $images = []; * - * $familyPhotoResource = fopen(__DIR__ .'/assets/family-photo.jpg', 'r'); - * $eiffelTowerResource = fopen(__DIR__ .'/assets/eiffel-tower.jpg', 'r'); + * $familyPhotoResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r'); + * $eiffelTowerResource = fopen(__DIR__ . '/assets/eiffel-tower.jpg', 'r'); * * $images[] = $vision->image($familyPhotoResource, [ * 'FACE_DETECTION' diff --git a/tests/snippets/Speech/SpeechClientTest.php b/tests/snippets/Speech/SpeechClientTest.php index b8d572eca60c..b823391e0152 100644 --- a/tests/snippets/Speech/SpeechClientTest.php +++ b/tests/snippets/Speech/SpeechClientTest.php @@ -34,7 +34,7 @@ class SpeechClientTest extends SnippetTestCase public function setUp() { - $this->testFile = "'" . __DIR__ .'/../fixtures/Speech/demo.flac' . "'"; + $this->testFile = "'" . __DIR__ . '/../fixtures/Speech/demo.flac' . "'"; $this->connection = $this->prophesize(ConnectionInterface::class); $this->client = new \SpeechClientStub; $this->client->setConnection($this->connection->reveal()); diff --git a/tests/snippets/Vision/Annotation/CropHintTest.php b/tests/snippets/Vision/Annotation/CropHintTest.php new file mode 100644 index 000000000000..7a9f60d7fae4 --- /dev/null +++ b/tests/snippets/Vision/Annotation/CropHintTest.php @@ -0,0 +1,102 @@ +info = [ + 'boundingPoly' => ['foo' => 'bar'], + 'confidence' => 0.4, + 'importanceFraction' => 0.1 + ]; + + $this->hint = new CropHint($this->info); + } + + public function testClass() + { + $connectionStub = $this->prophesize(ConnectionInterface::class); + + $connectionStub->annotate(Argument::any()) + ->willReturn([ + 'responses' => [ + [ + 'cropHintsAnnotation' => [ + 'cropHints' => [[]] + ] + ] + ] + ]); + + $snippet = $this->snippetFromClass(CropHint::class); + $snippet->addLocal('connectionStub', $connectionStub->reveal()); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); + $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); + $property = $reflection->getProperty(\'connection\'); + $property->setAccessible(true); + $property->setValue($vision, $connectionStub); + $property->setAccessible(false);' + ); + + $res = $snippet->invoke('hint'); + $this->assertInstanceOf(CropHint::class, $res->returnVal()); + } + + public function testBoundingPoly() + { + $snippet = $this->snippetFromMagicMethod(CropHint::class, 'boundingPoly'); + $snippet->addLocal('hint', $this->hint); + + $res = $snippet->invoke('poly'); + $this->assertEquals($this->info['boundingPoly'], $res->returnVal()); + } + + public function testConfidence() + { + $snippet = $this->snippetFromMagicMethod(CropHint::class, 'confidence'); + $snippet->addLocal('hint', $this->hint); + + $res = $snippet->invoke('confidence'); + $this->assertEquals($this->info['confidence'], $res->returnVal()); + } + + public function testImportanceFraction() + { + $snippet = $this->snippetFromMagicMethod(CropHint::class, 'importanceFraction'); + $snippet->addLocal('hint', $this->hint); + + $res = $snippet->invoke('importance'); + $this->assertEquals($this->info['importanceFraction'], $res->returnVal()); + } +} diff --git a/tests/snippets/Vision/Annotation/DocumentTest.php b/tests/snippets/Vision/Annotation/DocumentTest.php new file mode 100644 index 000000000000..d34f67997519 --- /dev/null +++ b/tests/snippets/Vision/Annotation/DocumentTest.php @@ -0,0 +1,98 @@ +info = [ + 'pages' => [['foo' => 'bar']], + 'text' => 'hello world' + ]; + $this->document = new Document($this->info); + } + + public function testClass() + { + $connectionStub = $this->prophesize(ConnectionInterface::class); + + $connectionStub->annotate(Argument::any()) + ->willReturn([ + 'responses' => [ + [ + 'fullTextAnnotation' => [[]] + ] + ] + ]); + + $snippet = $this->snippetFromClass(Document::class); + $snippet->addLocal('connectionStub', $connectionStub->reveal()); + $snippet->replace( + "__DIR__ . '/assets/the-constitution.jpg'", + "'php://temp'" + ); + $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); + $property = $reflection->getProperty(\'connection\'); + $property->setAccessible(true); + $property->setValue($vision, $connectionStub); + $property->setAccessible(false);' + ); + + $res = $snippet->invoke('document'); + $this->assertInstanceOf(Document::class, $res->returnVal()); + } + + public function testPages() + { + $snippet = $this->snippetFromMagicMethod(Document::class, 'pages'); + $snippet->addLocal('document', $this->document); + + $res = $snippet->invoke('pages'); + $this->assertEquals($this->info['pages'], $res->returnVal()); + } + + public function testText() + { + $snippet = $this->snippetFromMagicMethod(Document::class, 'text'); + $snippet->addLocal('document', $this->document); + + $res = $snippet->invoke('text'); + $this->assertEquals($this->info['text'], $res->returnVal()); + } + + public function testInfo() + { + $snippet = $this->snippetFromMagicMethod(Document::class, 'info'); + $snippet->addLocal('document', $this->document); + + $res = $snippet->invoke('info'); + $this->assertEquals($this->info, $res->returnVal()); + } +} diff --git a/tests/snippets/Vision/Annotation/EntityTest.php b/tests/snippets/Vision/Annotation/EntityTest.php index b19d7b2268dd..d990ee8c27ce 100644 --- a/tests/snippets/Vision/Annotation/EntityTest.php +++ b/tests/snippets/Vision/Annotation/EntityTest.php @@ -62,7 +62,10 @@ public function testClass() $snippet = $this->snippetFromClass(Entity::class); $snippet->addLocal('connectionStub', $connectionStub->reveal()); - $snippet->setLine(5, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); $property = $reflection->getProperty(\'connection\'); $property->setAccessible(true); @@ -161,5 +164,4 @@ public function testProperties() $res = $snippet->invoke(); $this->assertEquals($this->entityData['properties'], $res->output()); } - } diff --git a/tests/snippets/Vision/Annotation/Face/LandmarksTest.php b/tests/snippets/Vision/Annotation/Face/LandmarksTest.php index 9dc833cf7993..858a6a810f6e 100644 --- a/tests/snippets/Vision/Annotation/Face/LandmarksTest.php +++ b/tests/snippets/Vision/Annotation/Face/LandmarksTest.php @@ -98,7 +98,10 @@ public function testClass() $snippet = $this->snippetFromClass(Landmarks::class); $snippet->addLocal('connectionStub', $connectionStub->reveal()); - $snippet->setLine(5, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); $property = $reflection->getProperty(\'connection\'); $property->setAccessible(true); diff --git a/tests/snippets/Vision/Annotation/FaceTest.php b/tests/snippets/Vision/Annotation/FaceTest.php index 58dec319541c..81a9127a5a83 100644 --- a/tests/snippets/Vision/Annotation/FaceTest.php +++ b/tests/snippets/Vision/Annotation/FaceTest.php @@ -74,7 +74,10 @@ public function testClass() $snippet = $this->snippetFromClass(Face::class); $snippet->addLocal('connectionStub', $connectionStub->reveal()); - $snippet->setLine(5, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); $property = $reflection->getProperty(\'connection\'); $property->setAccessible(true); diff --git a/tests/snippets/Vision/Annotation/ImagePropertiesTest.php b/tests/snippets/Vision/Annotation/ImagePropertiesTest.php index 03ea867f8f86..62c8c8f82f64 100644 --- a/tests/snippets/Vision/Annotation/ImagePropertiesTest.php +++ b/tests/snippets/Vision/Annotation/ImagePropertiesTest.php @@ -53,7 +53,10 @@ public function testClass() $snippet = $this->snippetFromClass(ImageProperties::class); $snippet->addLocal('connectionStub', $connectionStub->reveal()); - $snippet->setLine(5, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); $property = $reflection->getProperty(\'connection\'); $property->setAccessible(true); diff --git a/tests/snippets/Vision/Annotation/SafeSearchTest.php b/tests/snippets/Vision/Annotation/SafeSearchTest.php index e9695f1dde87..b0af9e9a5c30 100644 --- a/tests/snippets/Vision/Annotation/SafeSearchTest.php +++ b/tests/snippets/Vision/Annotation/SafeSearchTest.php @@ -58,7 +58,10 @@ public function testClass() $snippet = $this->snippetFromClass(SafeSearch::class); $snippet->addLocal('connectionStub', $connectionStub->reveal()); - $snippet->setLine(5, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); $property = $reflection->getProperty(\'connection\'); $property->setAccessible(true); @@ -70,14 +73,6 @@ public function testClass() $this->assertInstanceOf(SafeSearch::class, $res->returnVal()); } - public function testInfo() - { - $snippet = $this->snippetFromMagicMethod(SafeSearch::class, 'info'); - $snippet->addLocal('safeSearch', $this->ss); - - $this->assertEquals($this->ssData, $snippet->invoke('info')->returnVal()); - } - public function testAdult() { $snippet = $this->snippetFromMagicMethod(SafeSearch::class, 'adult'); @@ -122,6 +117,7 @@ public function testIsAdult() $res = $snippet->invoke(); $this->assertEquals(sprintf('Image contains %s content.', 'adult'), $res->output()); } + public function testIsSpoof() { $snippet = $this->snippetFromMethod(SafeSearch::class, 'isSpoof'); @@ -130,6 +126,7 @@ public function testIsSpoof() $res = $snippet->invoke(); $this->assertEquals(sprintf('Image contains %s content.', 'spoofed'), $res->output()); } + public function testIsMedical() { $snippet = $this->snippetFromMethod(SafeSearch::class, 'isMedical'); @@ -138,6 +135,7 @@ public function testIsMedical() $res = $snippet->invoke(); $this->assertEquals(sprintf('Image contains %s content.', 'medical'), $res->output()); } + public function testIsViolent() { $snippet = $this->snippetFromMethod(SafeSearch::class, 'isViolent'); @@ -146,4 +144,13 @@ public function testIsViolent() $res = $snippet->invoke(); $this->assertEquals(sprintf('Image contains %s content.', 'violent'), $res->output()); } + + public function testInfo() + { + $snippet = $this->snippetFromMagicMethod(SafeSearch::class, 'info'); + $snippet->addLocal('safeSearch', $this->ss); + + $res = $snippet->invoke('info'); + $this->assertEquals($this->ssData, $res->returnVal()); + } } diff --git a/tests/snippets/Vision/Annotation/Web/WebEntityTest.php b/tests/snippets/Vision/Annotation/Web/WebEntityTest.php new file mode 100644 index 000000000000..62009e184dcb --- /dev/null +++ b/tests/snippets/Vision/Annotation/Web/WebEntityTest.php @@ -0,0 +1,103 @@ +info = [ + 'entityId' => 'foo', + 'score' => 0.1, + 'description' => 'bar' + ]; + $this->entity = new WebEntity($this->info); + } + + public function testClass() + { + $connectionStub = $this->prophesize(ConnectionInterface::class); + + $connectionStub->annotate(Argument::any()) + ->willReturn([ + 'responses' => [ + [ + 'webDetection' => [ + 'webEntities' => [ + [] + ] + ] + ] + ] + ]); + + $snippet = $this->snippetFromClass(WebEntity::class); + $snippet->addLocal('connectionStub', $connectionStub->reveal()); + $snippet->replace( + "__DIR__ . '/assets/eiffel-tower.jpg'", + "'php://temp'" + ); + $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); + $property = $reflection->getProperty(\'connection\'); + $property->setAccessible(true); + $property->setValue($vision, $connectionStub); + $property->setAccessible(false);' + ); + + $res = $snippet->invoke('firstEntity'); + $this->assertInstanceOf(WebEntity::class, $res->returnVal()); + } + + public function testEntityId() + { + $snippet = $this->snippetFromMagicMethod(WebEntity::class, 'entityId'); + $snippet->addLocal('entity', $this->entity); + + $res = $snippet->invoke('id'); + $this->assertEquals($this->info['entityId'], $res->returnVal()); + } + + public function testScore() + { + $snippet = $this->snippetFromMagicMethod(WebEntity::class, 'score'); + $snippet->addLocal('entity', $this->entity); + + $res = $snippet->invoke('score'); + $this->assertEquals($this->info['score'], $res->returnVal()); + } + + public function testDescription() + { + $snippet = $this->snippetFromMagicMethod(WebEntity::class, 'description'); + $snippet->addLocal('entity', $this->entity); + + $res = $snippet->invoke('description'); + $this->assertEquals($this->info['description'], $res->returnVal()); + } +} diff --git a/tests/snippets/Vision/Annotation/Web/WebImageTest.php b/tests/snippets/Vision/Annotation/Web/WebImageTest.php new file mode 100644 index 000000000000..b8ced484b27c --- /dev/null +++ b/tests/snippets/Vision/Annotation/Web/WebImageTest.php @@ -0,0 +1,93 @@ +info = [ + 'url' => 'http://foo.bar/image.jpg', + 'score' => 0.1, + ]; + $this->image = new WebImage($this->info); + } + + public function testClass() + { + $connectionStub = $this->prophesize(ConnectionInterface::class); + + $connectionStub->annotate(Argument::any()) + ->willReturn([ + 'responses' => [ + [ + 'webDetection' => [ + 'fullMatchingImages' => [ + [] + ] + ] + ] + ] + ]); + + $snippet = $this->snippetFromClass(WebImage::class); + $snippet->addLocal('connectionStub', $connectionStub->reveal()); + $snippet->replace( + "__DIR__ . '/assets/eiffel-tower.jpg'", + "'php://temp'" + ); + $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); + $property = $reflection->getProperty(\'connection\'); + $property->setAccessible(true); + $property->setValue($vision, $connectionStub); + $property->setAccessible(false);' + ); + + $res = $snippet->invoke('firstImage'); + $this->assertInstanceOf(WebImage::class, $res->returnVal()); + } + + public function testurl() + { + $snippet = $this->snippetFromMagicMethod(WebImage::class, 'url'); + $snippet->addLocal('image', $this->image); + + $res = $snippet->invoke('url'); + $this->assertEquals($this->info['url'], $this->image->url()); + } + + public function testscore() + { + $snippet = $this->snippetFromMagicMethod(WebImage::class, 'score'); + $snippet->addLocal('image', $this->image); + + $res = $snippet->invoke('score'); + $this->assertEquals($this->info['score'], $this->image->score()); + } +} diff --git a/tests/snippets/Vision/Annotation/Web/WebPageTest.php b/tests/snippets/Vision/Annotation/Web/WebPageTest.php new file mode 100644 index 000000000000..5e74eafcbe7e --- /dev/null +++ b/tests/snippets/Vision/Annotation/Web/WebPageTest.php @@ -0,0 +1,93 @@ +info = [ + 'url' => 'http://foo.bar/image.jpg', + 'score' => 0.1, + ]; + $this->image = new WebPage($this->info); + } + + public function testClass() + { + $connectionStub = $this->prophesize(ConnectionInterface::class); + + $connectionStub->annotate(Argument::any()) + ->willReturn([ + 'responses' => [ + [ + 'webDetection' => [ + 'pagesWithMatchingImages' => [ + [] + ] + ] + ] + ] + ]); + + $snippet = $this->snippetFromClass(WebPage::class); + $snippet->addLocal('connectionStub', $connectionStub->reveal()); + $snippet->replace( + "__DIR__ . '/assets/eiffel-tower.jpg'", + "'php://temp'" + ); + $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); + $property = $reflection->getProperty(\'connection\'); + $property->setAccessible(true); + $property->setValue($vision, $connectionStub); + $property->setAccessible(false);' + ); + + $res = $snippet->invoke('firstPage'); + $this->assertInstanceOf(WebPage::class, $res->returnVal()); + } + + public function testurl() + { + $snippet = $this->snippetFromMagicMethod(WebPage::class, 'url'); + $snippet->addLocal('image', $this->image); + + $res = $snippet->invoke('url'); + $this->assertEquals($this->info['url'], $this->image->url()); + } + + public function testscore() + { + $snippet = $this->snippetFromMagicMethod(WebPage::class, 'score'); + $snippet->addLocal('image', $this->image); + + $res = $snippet->invoke('score'); + $this->assertEquals($this->info['score'], $this->image->score()); + } +} diff --git a/tests/snippets/Vision/Annotation/WebTest.php b/tests/snippets/Vision/Annotation/WebTest.php new file mode 100644 index 000000000000..38f849b2a8c3 --- /dev/null +++ b/tests/snippets/Vision/Annotation/WebTest.php @@ -0,0 +1,120 @@ +info = [ + 'webEntities' => [ + [] + ], + 'fullMatchingImages' => [ + [] + ], + 'partialMatchingImages' => [ + [] + ], + 'pagesWithMatchingImages' => [ + [] + ] + ]; + $this->web = new Web($this->info); + } + + public function testClass() + { + $connectionStub = $this->prophesize(ConnectionInterface::class); + + $connectionStub->annotate(Argument::any()) + ->willReturn([ + 'responses' => [ + [ + 'webDetection' => [] + ] + ] + ]); + + $snippet = $this->snippetFromClass(Web::class); + $snippet->addLocal('connectionStub', $connectionStub->reveal()); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); + $snippet->insertAfterLine(3, '$reflection = new \ReflectionClass($vision); + $property = $reflection->getProperty(\'connection\'); + $property->setAccessible(true); + $property->setValue($vision, $connectionStub); + $property->setAccessible(false);' + ); + + $res = $snippet->invoke('web'); + $this->assertInstanceOf(Web::class, $res->returnVal()); + } + + public function testEntities() + { + $snippet = $this->snippetFromMethod(Web::class, 'entities'); + $snippet->addLocal('web', $this->web); + + $res = $snippet->invoke('entities'); + $this->assertInstanceOf(WebEntity::class, $res->returnVal()[0]); + } + + public function testMatchingImages() + { + $snippet = $this->snippetFromMethod(Web::class, 'matchingImages'); + $snippet->addLocal('web', $this->web); + + $res = $snippet->invoke('images'); + $this->assertInstanceOf(WebImage::class, $res->returnVal()[0]); + } + + public function testPartialMatchingImages() + { + $snippet = $this->snippetFromMethod(Web::class, 'partialMatchingImages'); + $snippet->addLocal('web', $this->web); + + $res = $snippet->invoke('images'); + $this->assertInstanceOf(WebImage::class, $res->returnVal()[0]); + } + + public function testPages() + { + $snippet = $this->snippetFromMethod(Web::class, 'pages'); + $snippet->addLocal('web', $this->web); + + $res = $snippet->invoke('pages'); + $this->assertInstanceOf(WebPage::class, $res->returnVal()[0]); + } +} diff --git a/tests/snippets/Vision/AnnotationTest.php b/tests/snippets/Vision/AnnotationTest.php index 6412667a4dca..16f9dd158454 100644 --- a/tests/snippets/Vision/AnnotationTest.php +++ b/tests/snippets/Vision/AnnotationTest.php @@ -19,10 +19,13 @@ use Google\Cloud\Dev\Snippet\SnippetTestCase; use Google\Cloud\Vision\Annotation; +use Google\Cloud\Vision\Annotation\CropHint; +use Google\Cloud\Vision\Annotation\Document; use Google\Cloud\Vision\Annotation\Entity; use Google\Cloud\Vision\Annotation\Face; use Google\Cloud\Vision\Annotation\ImageProperties; use Google\Cloud\Vision\Annotation\SafeSearch; +use Google\Cloud\Vision\Annotation\Web; use Google\Cloud\Vision\Connection\ConnectionInterface; use Prophecy\Argument; @@ -35,8 +38,8 @@ public function testClass() { $snippet = $this->snippetFromClass(Annotation::class); $snippet->replace( - '__DIR__ .\'/assets/family-photo.jpg\'', - '\'php://temp\'' + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" ); $connectionStub = $this->prophesize(ConnectionInterface::class); @@ -151,6 +154,42 @@ public function testImageProperties() $this->assertInstanceOf(ImageProperties::class, $res->returnVal()); } + public function testFullText() + { + $ft = ['foo' => 'bar']; + $snippet = $this->snippetFromMethod(Annotation::class, 'fullText'); + $snippet->addLocal('annotation', new Annotation([ + 'fullTextAnnotation' => $ft + ])); + + $res = $snippet->invoke('fullText'); + $this->assertInstanceOf(Document::class, $res->returnVal()); + } + + public function testCropHints() + { + $snippet = $this->snippetFromMethod(Annotation::class, 'cropHints'); + $snippet->addLocal('annotation', new Annotation([ + 'cropHintsAnnotation' => [ + 'cropHints' => [[]] + ] + ])); + + $res = $snippet->invoke('hints'); + $this->assertInstanceOf(CropHint::class, $res->returnVal()[0]); + } + + public function testWeb() + { + $snippet = $this->snippetFromMethod(Annotation::class, 'web'); + $snippet->addLocal('annotation', new Annotation([ + 'webDetection' => [] + ])); + + $res = $snippet->invoke('web'); + $this->assertInstanceOf(Web::class, $res->returnVal()); + } + public function testError() { $snippet = $this->snippetFromMethod(Annotation::class, 'error'); diff --git a/tests/snippets/Vision/ImageTest.php b/tests/snippets/Vision/ImageTest.php index 3d2dac623442..5473e64df24a 100644 --- a/tests/snippets/Vision/ImageTest.php +++ b/tests/snippets/Vision/ImageTest.php @@ -29,7 +29,10 @@ class ImageTest extends SnippetTestCase public function testImageFromServiceBuilder() { $snippet = $this->snippetFromClass(Image::class, 'default'); - $snippet->setLine(6, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('image'); $this->assertInstanceOf(Image::class, $res->returnVal()); @@ -38,7 +41,10 @@ public function testImageFromServiceBuilder() public function testDirectInstantiation() { $snippet = $this->snippetFromClass(Image::class, 'direct'); - $snippet->setLine(4, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('image'); $this->assertInstanceOf(Image::class, $res->returnVal()); @@ -76,7 +82,10 @@ public function testMaxResults() public function testFeatureShortcuts() { $snippet = $this->snippetFromClass(Image::class, 'shortcut'); - $snippet->setLine(5, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('image'); $this->assertInstanceOf(Image::class, $res->returnVal()); @@ -85,7 +94,10 @@ public function testFeatureShortcuts() public function testRequestObject() { $snippet = $this->snippetFromMethod(Image::class, 'requestObject'); - $snippet->setLine(2, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('requestObj'); $this->assertTrue(array_key_exists('image', $res->returnVal())); diff --git a/tests/snippets/Vision/VisionClientTest.php b/tests/snippets/Vision/VisionClientTest.php index 9d543b2fc957..4b7d677541c7 100644 --- a/tests/snippets/Vision/VisionClientTest.php +++ b/tests/snippets/Vision/VisionClientTest.php @@ -60,7 +60,10 @@ public function testImage() $snippet = $this->snippetFromMethod(VisionClient::class, 'image'); $snippet->addLocal('vision', $this->client); - $snippet->setLine(0, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('image'); @@ -72,7 +75,10 @@ public function testImageWithMaxResults() $snippet = $this->snippetFromMethod(VisionClient::class, 'image', 1); $snippet->addLocal('vision', $this->client); - $snippet->setLine(2, '$imageResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('image'); @@ -84,8 +90,15 @@ public function testImages() $snippet = $this->snippetFromMethod(VisionClient::class, 'images'); $snippet->addLocal('vision', $this->client); - $snippet->setLine(3, '$familyPhotoResource = fopen(\'php://temp\', \'r\');'); - $snippet->setLine(4, '$weddingPhotoResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); + + $snippet->replace( + "__DIR__ . '/assets/wedding-photo.jpg'", + "'php://temp'" + ); $res = $snippet->invoke('images'); $this->assertInstanceOf(Image::class, $res->returnVal()[0]); @@ -97,7 +110,10 @@ public function testAnnotate() $snippet = $this->snippetFromMethod(VisionClient::class, 'annotate'); $snippet->addLocal('vision', $this->client); - $snippet->setLine(0, '$familyPhotoResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); $this->connection->annotate(Argument::any()) ->shouldBeCalled() @@ -119,8 +135,15 @@ public function testAnnotateBatch() $snippet = $this->snippetFromMethod(VisionClient::class, 'annotateBatch'); $snippet->addLocal('vision', $this->client); - $snippet->setLine(2, '$familyPhotoResource = fopen(\'php://temp\', \'r\');'); - $snippet->setLine(3, '$eiffelTowerResource = fopen(\'php://temp\', \'r\');'); + $snippet->replace( + "__DIR__ . '/assets/family-photo.jpg'", + "'php://temp'" + ); + + $snippet->replace( + "__DIR__ . '/assets/eiffel-tower.jpg'", + "'php://temp'" + ); $this->connection->annotate(Argument::any()) ->shouldBeCalled() diff --git a/tests/snippets/bootstrap.php b/tests/snippets/bootstrap.php index 1b6d6c687a58..d6448ffe6885 100644 --- a/tests/snippets/bootstrap.php +++ b/tests/snippets/bootstrap.php @@ -2,7 +2,7 @@ // Provide a project ID. If you're mocking your service calls (and if you aren't // start now) you don't need anything else. -putenv('GOOGLE_APPLICATION_CREDENTIALS='. __DIR__ .'/keyfile-stub.json'); +putenv('GOOGLE_APPLICATION_CREDENTIALS='. __DIR__ . '/keyfile-stub.json'); use Google\Cloud\Dev\Snippet\Container; use Google\Cloud\Dev\Snippet\Coverage\Coverage; @@ -12,7 +12,7 @@ require __DIR__ . '/../../vendor/autoload.php'; $parser = new Parser; -$scanner = new Scanner($parser, __DIR__ .'/../../src'); +$scanner = new Scanner($parser, __DIR__ . '/../../src'); $coverage = new Coverage($scanner); $coverage->buildListToCover(); @@ -22,11 +22,11 @@ register_shutdown_function(function () { $uncovered = Container::$coverage->uncovered(); - if (!file_exists(__DIR__ .'/../../build')) { - mkdir(__DIR__ .'/../../build', 0777, true); + if (!file_exists(__DIR__ . '/../../build')) { + mkdir(__DIR__ . '/../../build', 0777, true); } - file_put_contents(__DIR__ .'/../../build/snippets-uncovered.json', json_encode($uncovered, JSON_PRETTY_PRINT)); + file_put_contents(__DIR__ . '/../../build/snippets-uncovered.json', json_encode($uncovered, JSON_PRETTY_PRINT)); if (!empty($uncovered)) { echo sprintf("\033[31mNOTICE: %s uncovered snippets! See build/snippets-uncovered.json for a report.\n", count($uncovered)); diff --git a/tests/system/Vision/AnnotationsTest.php b/tests/system/Vision/AnnotationsTest.php new file mode 100644 index 000000000000..cd160140ade6 --- /dev/null +++ b/tests/system/Vision/AnnotationsTest.php @@ -0,0 +1,169 @@ +client = parent::$vision; + } + + public function testAnnotate() + { + $image = $this->client->image( + file_get_contents($this->getFixtureFilePath('landmark.jpg')) , [ + 'LANDMARK_DETECTION', + 'SAFE_SEARCH_DETECTION', + 'IMAGE_PROPERTIES', + 'CROP_HINTS', + 'WEB_DETECTION' + ] + ); + + $res = $this->client->annotate($image); + $this->assertInstanceOf(Annotation::class, $res); + + // Landmarks + $this->assertInstanceOf(Entity::class, $res->landmarks()[0]); + $this->assertEquals('Eiffel Tower', $res->landmarks()[0]->description()); + + // Safe Search + $this->assertInstanceOf(SafeSearch::class, $res->safeSearch()); + $this->assertEquals('VERY_UNLIKELY', $res->safeSearch()->adult()); + $this->assertEquals('VERY_UNLIKELY', $res->safeSearch()->spoof()); + $this->assertEquals('VERY_UNLIKELY', $res->safeSearch()->medical()); + $this->assertEquals('VERY_UNLIKELY', $res->safeSearch()->violence()); + $this->assertFalse($res->safeSearch()->isAdult()); + $this->assertFalse($res->safeSearch()->isSpoof()); + $this->assertFalse($res->safeSearch()->isMedical()); + $this->assertFalse($res->safeSearch()->isViolent()); + + // Image Properties + $this->assertInstanceOf(ImageProperties::class, $res->imageProperties()); + $this->assertTrue(is_array($res->imageProperties()->colors())); + + // Crop Hints + $this->assertInstanceOf(CropHint::class, $res->cropHints()[0]); + $this->assertTrue(isset($res->cropHints()[0]->boundingPoly()['vertices'])); + $this->assertTrue(is_float($res->cropHints()[0]->confidence())); + $this->assertTrue(!is_null($res->cropHints()[0]->importanceFraction())); + + // Web Annotation + $this->assertInstanceOf(Web::class, $res->web()); + $this->assertInstanceOf(WebEntity::class, $res->web()->entities()[0]); + + $desc = array_filter($res->web()->entities(), function ($e) { + return ($e->description() === 'Eiffel Tower'); + }); + $this->assertTrue(count($desc) > 0); + + $this->assertInstanceOf(WebImage::class, $res->web()->matchingImages()[0]); + $this->assertInstanceOf(WebImage::class, $res->web()->partialMatchingImages()[0]); + $this->assertInstanceOf(WebPage::class, $res->web()->pages()[0]); + } + + public function testFaceAndLabelDetection() + { + $image = $this->client->image( + file_get_contents($this->getFixtureFilePath('obama.jpg')) , [ + 'FACE_DETECTION', + 'LABEL_DETECTION' + ] + ); + + $res = $this->client->annotate($image); + + $this->assertInstanceOf(Annotation::class, $res); + + // Face Detection + $this->assertInstanceOf(Face::class, $res->faces()[0]); + $this->assertInstanceOf(Landmarks::class, $res->faces()[0]->landmarks()); + $this->assertTrue($res->faces()[0]->isJoyful()); + $this->assertFalse($res->faces()[0]->isSorrowful()); + $this->assertFalse($res->faces()[0]->isAngry()); + $this->assertFalse($res->faces()[0]->isSurprised()); + $this->assertFalse($res->faces()[0]->isUnderExposed()); + $this->assertFalse($res->faces()[0]->isBlurred()); + $this->assertFalse($res->faces()[0]->hasHeadwear()); + + // Label Detection + $this->assertInstanceOf(Entity::class, $res->labels()[0]); + } + + public function testLogoDetection() + { + $image = $this->client->image( + file_get_contents($this->getFixtureFilePath('google.jpg')) , [ + 'LOGO_DETECTION' + ] + ); + + $res = $this->client->annotate($image); + $this->assertInstanceOf(Annotation::class, $res); + $this->assertInstanceOf(Entity::class, $res->logos()[0]); + $this->assertEquals('Google', $res->logos()[0]->description()); + } + + public function testTextDetection() + { + $image = $this->client->image( + file_get_contents($this->getFixtureFilePath('text.jpg')) , [ + 'TEXT_DETECTION' + ] + ); + + $res = $this->client->annotate($image); + $this->assertInstanceOf(Annotation::class, $res); + $this->assertInstanceOf(Entity::class, $res->text()[0]); + $this->assertEquals("Hello World.", explode("\n", $res->text()[0]->description())[0]); + $this->assertEquals("Goodby World!", explode("\n", $res->text()[0]->description())[1]); + } + + public function testDocumentTextDetection() + { + $image = $this->client->image( + file_get_contents($this->getFixtureFilePath('text.jpg')) , [ + 'DOCUMENT_TEXT_DETECTION' + ] + ); + + $res = $this->client->annotate($image); + + $this->assertInstanceOf(Annotation::class, $res); + $this->assertInstanceOf(Document::class, $res->fullText()); + } +} diff --git a/tests/system/Vision/VisionTestCase.php b/tests/system/Vision/VisionTestCase.php new file mode 100644 index 000000000000..40fca44dc242 --- /dev/null +++ b/tests/system/Vision/VisionTestCase.php @@ -0,0 +1,47 @@ + $keyFilePath + ]); + self::$hasSetUp = true; + } + + protected function getFixtureFilePath($file) + { + return __DIR__ .'/fixtures/'. $file; + } +} diff --git a/tests/system/Vision/fixtures/google.jpg b/tests/system/Vision/fixtures/google.jpg new file mode 100644 index 000000000000..29834cfede17 Binary files /dev/null and b/tests/system/Vision/fixtures/google.jpg differ diff --git a/tests/system/Vision/fixtures/landmark.jpg b/tests/system/Vision/fixtures/landmark.jpg new file mode 100644 index 000000000000..aeae47494078 Binary files /dev/null and b/tests/system/Vision/fixtures/landmark.jpg differ diff --git a/tests/system/Vision/fixtures/obama.jpg b/tests/system/Vision/fixtures/obama.jpg new file mode 100644 index 000000000000..e5128d3fe85f Binary files /dev/null and b/tests/system/Vision/fixtures/obama.jpg differ diff --git a/tests/system/Vision/fixtures/text.jpg b/tests/system/Vision/fixtures/text.jpg new file mode 100644 index 000000000000..55f1db964e89 Binary files /dev/null and b/tests/system/Vision/fixtures/text.jpg differ diff --git a/tests/unit/Vision/Annotation/CropHintTest.php b/tests/unit/Vision/Annotation/CropHintTest.php new file mode 100644 index 000000000000..971a9198a628 --- /dev/null +++ b/tests/unit/Vision/Annotation/CropHintTest.php @@ -0,0 +1,55 @@ +info = [ + 'boundingPoly' => ['foo' => 'bar'], + 'confidence' => 0.4, + 'importanceFraction' => 0.1 + ]; + + $this->hint = new CropHint($this->info); + } + + public function testBoundingPoly() + { + $this->assertEquals($this->info['boundingPoly'], $this->hint->boundingPoly()); + } + + public function testConfidence() + { + $this->assertEquals($this->info['confidence'], $this->hint->confidence()); + } + + public function testImportanceFraction() + { + $this->assertEquals($this->info['importanceFraction'], $this->hint->importanceFraction()); + } +} diff --git a/tests/unit/Vision/Annotation/DocumentTest.php b/tests/unit/Vision/Annotation/DocumentTest.php new file mode 100644 index 000000000000..6e6ece9658c4 --- /dev/null +++ b/tests/unit/Vision/Annotation/DocumentTest.php @@ -0,0 +1,38 @@ + 'bar' + ]; + + $e = new Document($res); + + $this->assertEquals($res, $e->info()); + $this->assertEquals('bar', $e->foo()); + } +} diff --git a/tests/unit/Vision/Annotation/Web/WebEntityTest.php b/tests/unit/Vision/Annotation/Web/WebEntityTest.php new file mode 100644 index 000000000000..2ea3269ea43a --- /dev/null +++ b/tests/unit/Vision/Annotation/Web/WebEntityTest.php @@ -0,0 +1,54 @@ +info = [ + 'entityId' => 'foo', + 'score' => 1, + 'description' => 'bar' + ]; + $this->entity = new WebEntity($this->info); + } + + public function testEntityId() + { + $this->assertEquals($this->info['entityId'], $this->entity->entityId()); + } + + public function testScore() + { + $this->assertEquals($this->info['score'], $this->entity->score()); + } + + public function testDescription() + { + $this->assertEquals($this->info['description'], $this->entity->description()); + } +} diff --git a/tests/unit/Vision/Annotation/Web/WebImageTest.php b/tests/unit/Vision/Annotation/Web/WebImageTest.php new file mode 100644 index 000000000000..f5da1e1de743 --- /dev/null +++ b/tests/unit/Vision/Annotation/Web/WebImageTest.php @@ -0,0 +1,48 @@ +info = [ + 'url' => 'http://foo.bar/bat', + 'score' => 0.4 + ]; + $this->image = new WebImage($this->info); + } + + public function testUrl() + { + $this->assertEquals($this->info['url'], $this->image->url()); + } + + public function testScore() + { + $this->assertEquals($this->info['score'], $this->image->score()); + } +} diff --git a/tests/unit/Vision/Annotation/Web/WebPageTest.php b/tests/unit/Vision/Annotation/Web/WebPageTest.php new file mode 100644 index 000000000000..488ad080ec8c --- /dev/null +++ b/tests/unit/Vision/Annotation/Web/WebPageTest.php @@ -0,0 +1,48 @@ +info = [ + 'url' => 'http://foo.bar/bat', + 'score' => 0.4 + ]; + $this->image = new WebPage($this->info); + } + + public function testUrl() + { + $this->assertEquals($this->info['url'], $this->image->url()); + } + + public function testScore() + { + $this->assertEquals($this->info['score'], $this->image->score()); + } +} diff --git a/tests/unit/Vision/Annotation/WebTest.php b/tests/unit/Vision/Annotation/WebTest.php new file mode 100644 index 000000000000..1b449043471f --- /dev/null +++ b/tests/unit/Vision/Annotation/WebTest.php @@ -0,0 +1,75 @@ +info = [ + 'webEntities' => [ + ['foo' => 'bar'] + ], + 'fullMatchingImages' => [ + ['foo' => 'bar'] + ], + 'partialMatchingImages' => [ + ['foo' => 'bar'] + ], + 'pagesWithMatchingImages' => [ + ['foo' => 'bar'] + ] + ]; + $this->annotation = new Web($this->info); + } + + public function testEntities() + { + $this->assertInstanceOf(WebEntity::class, $this->annotation->entities()[0]); + $this->assertEquals($this->info['webEntities'][0], $this->annotation->entities()[0]->info()); + } + + public function testMatchingImages() + { + $this->assertInstanceOf(WebImage::class, $this->annotation->matchingImages()[0]); + $this->assertEquals($this->info['fullMatchingImages'][0], $this->annotation->matchingImages()[0]->info()); + } + + public function testPartialMatchingImages() + { + $this->assertInstanceOf(WebImage::class, $this->annotation->partialMatchingImages()[0]); + $this->assertEquals($this->info['partialMatchingImages'][0], $this->annotation->partialMatchingImages()[0]->info()); + } + + public function testPages() + { + $this->assertInstanceOf(WebPage::class, $this->annotation->pages()[0]); + $this->assertEquals($this->info['pagesWithMatchingImages'][0], $this->annotation->pages()[0]->info()); + } +} diff --git a/tests/unit/Vision/AnnotationTest.php b/tests/unit/Vision/AnnotationTest.php index 746b2f003e30..b89b37b725c8 100644 --- a/tests/unit/Vision/AnnotationTest.php +++ b/tests/unit/Vision/AnnotationTest.php @@ -18,10 +18,13 @@ namespace Google\Cloud\Tests\Vision; use Google\Cloud\Vision\Annotation; +use Google\Cloud\Vision\Annotation\CropHint; +use Google\Cloud\Vision\Annotation\Document; use Google\Cloud\Vision\Annotation\Entity; use Google\Cloud\Vision\Annotation\Face; use Google\Cloud\Vision\Annotation\ImageProperties; use Google\Cloud\Vision\Annotation\SafeSearch; +use Google\Cloud\Vision\Annotation\Web; /** * @group vision @@ -40,7 +43,10 @@ public function testConstruct() 'textAnnotations' => ['foo' => ['bat' => 'bar']], 'safeSearchAnnotation' => ['foo' => ['bat' => 'bar']], 'imagePropertiesAnnotation' => ['foo' => ['bat' => 'bar']], - 'error' => ['foo' => ['bat' => 'bar']] + 'error' => ['foo' => ['bat' => 'bar']], + 'fullTextAnnotation' => ['foo' => 'bar'], + 'cropHintsAnnotation' => ['cropHints' => [['bat' => 'bar']]], + 'webDetection' => ['foo' => ['bat' => 'bar']], ]; $ann = new Annotation($res); @@ -53,6 +59,9 @@ public function testConstruct() $this->assertInstanceOf(SafeSearch::class, $ann->safeSearch()); $this->assertInstanceOf(ImageProperties::class, $ann->imageProperties()); $this->assertEquals($res['error'], $ann->error()); + $this->assertInstanceOf(Document::class, $ann->fullText()); + $this->assertInstanceOf(CropHint::class, $ann->cropHints()[0]); + $this->assertInstanceOf(Web::class, $ann->web()); $this->assertEquals($res, $ann->info()); } diff --git a/tests/unit/Vision/ImageTest.php b/tests/unit/Vision/ImageTest.php index 7ba69af573a8..c2b2fb948359 100644 --- a/tests/unit/Vision/ImageTest.php +++ b/tests/unit/Vision/ImageTest.php @@ -25,7 +25,7 @@ */ class ImageTest extends \PHPUnit_Framework_TestCase { - public function testWithBytes() + public function testWithString() { $bytes = file_get_contents(__DIR__ .'/../fixtures/vision/eiffel-tower.jpg'); $image = new Image($bytes, ['landmarks']); @@ -47,7 +47,7 @@ public function testWithStorage() $image = new Image($object, [ 'landmarks' ]); $res = $image->requestObject(); - $this->assertEquals($res['image']['source']['gcsImageUri'], $gcsUri); + $this->assertEquals($res['image']['source']['imageUri'], $gcsUri); $this->assertEquals($res['features'], [ ['type' => 'LANDMARK_DETECTION'] ]); } @@ -63,6 +63,17 @@ public function testWithResource() $this->assertEquals($res['features'], [ ['type' => 'LANDMARK_DETECTION'] ]); } + public function testWithExternalImage() + { + $externalUri = 'http://google.com/image.jpg'; + $image = new Image($externalUri, ['landmarks']); + + $res = $image->requestObject(); + + $this->assertEquals($res['image']['source']['imageUri'], $externalUri); + $this->assertEquals($res['features'], [ ['type' => 'LANDMARK_DETECTION'] ]); + } + /** * @expectedException InvalidArgumentException */ @@ -87,13 +98,16 @@ public function testMaxResults() public function testShortNamesMapping() { $names = [ - 'faces' => 'FACE_DETECTION', - 'landmarks' => 'LANDMARK_DETECTION', - 'logos' => 'LOGO_DETECTION', - 'labels' => 'LABEL_DETECTION', - 'text' => 'TEXT_DETECTION', - 'safeSearch' => 'SAFE_SEARCH_DETECTION', - 'imageProperties' => 'IMAGE_PROPERTIES' + 'faces' => 'FACE_DETECTION', + 'landmarks' => 'LANDMARK_DETECTION', + 'logos' => 'LOGO_DETECTION', + 'labels' => 'LABEL_DETECTION', + 'text' => 'TEXT_DETECTION', + 'document' => 'DOCUMENT_TEXT_DETECTION', + 'safeSearch' => 'SAFE_SEARCH_DETECTION', + 'imageProperties' => 'IMAGE_PROPERTIES', + 'crop' => 'CROP_HINTS', + 'web' => 'WEB_DETECTION' ]; $bytes = 'foo'; @@ -122,4 +136,26 @@ public function testBytesWithoutEncoding() $encodedRes = $image->requestObject(); $this->assertEquals($encodedRes['image']['content'], base64_encode($bytes)); } + + public function testUrlSchemes() + { + $urls = [ + 'http://foo.bar', + 'https://foo.bar', + 'gs://foo/bar', + 'ssh://foo/bar' + ]; + + $images = [ + new Image($urls[0], ['faces']), + new Image($urls[1], ['faces']), + new Image($urls[2], ['faces']), + new Image($urls[3], ['faces']), + ]; + + $this->assertEquals($urls[0], $images[0]->requestObject()['image']['source']['imageUri']); + $this->assertEquals($urls[1], $images[1]->requestObject()['image']['source']['imageUri']); + $this->assertEquals($urls[2], $images[2]->requestObject()['image']['source']['imageUri']); + $this->assertFalse(isset($images[3]->requestObject()['image']['source']['imageUri'])); + } }